关于WPARAM和LPARAM参数

从前,Windows 是 16 位的。每条message信息都可以携带两段数据,分别称为 WPARAM 和 LPARAM。在消息参数传递中对指针类型使用强制类型转换,这是一种常见用法。第一个参数是一个 16 位值("word"),因此称为 W;第二个参数是一个 32 位值("long"),因此称为 L。
W 参数用于传递句柄和整数。L 参数用于传递指针。
当 Windows 转换为 32 位时,WPARAM 参数也变为 32 位值。一个字的大小变成了32bit。(在 64 位 Windows 中,两个参数都是 64 位值!)。
了解这些术语的起源很有帮助。如果查看一下窗口消息的设计,就会发现如果消息使用指针,指针通常会在 LPARAM 中传递,而如果消息使用句柄或整数,则会在 WPARAM 中传递。(如果一条信息两个都包含,则整数放在 WPARAM 中,指针放在 LPARAM 中)。
学会了这一点,记忆窗口消息的参数就容易多了。相反,如果一条消息违反了这一规则,那么你的大脑就会说: "不,这不对"。
Once upon a time, Windows was 16-bit. Each message could carry with it two pieces of data, called WPARAM and LPARAM. It is the common practice of passing casted pointers as message parameters. The first one was a 16-bit value (“word”), so it was called W. The second one was a 32-bit value (“long”), so it was called L.
You used the W parameter to pass things like handles and integers. You used the L parameter to pass pointers.
When Windows was converted to 32-bit, the WPARAM parameter grew to a 32-bit value as well. The word changes to 32-bit. (And in 64-bit Windows, both parameters are 64-bit values!)
It is helpful to understand the origin of the terms. If you look at the design of window messages, you will see that if the message takes a pointer, the pointer is usually passed in the LPARAM, whereas if the message takes a handle or an integer, then it is passed in the WPARAM. (And if a message takes both, the integer goes in the WPARAM and the pointer goes in the LPARAM.)
Once you learn this, it makes remembering the parameters for window messages a little easier. Conversely, if a message breaks this rule, then it sort of makes your brain say, “No, that’s not right.”
LPARAM 是 LONG_PTR 的类型定义,在 win32 中是 long(有符号 32 位),在 x86_64 中是 __int64 (有符号 64 位)。
WPARAM 是 UINT_PTR 的类型定义,在 win32 中是无符号 int(32 位无符号),在 x86_64 中是__int64(64 位无符号)。
LPARAM is a typedef for LONG_PTR which is a long (signed 32-bit) on win32 and __int64 (signed 64-bit) on x86_64.
WPARAM is a typedef for UINT_PTR which is an unsigned int (unsigned 32-bit) on win32 and unsigned __int64 (unsigned 64-bit) on x86_64.
====== 分割线 ====== 
Windows的SDK里代码,经常有WPARAM和LPARAM这两个参数,作为一个消息结构体的两个成员,传递信息。WPARAM通常用来表示句柄或数值,LPARAM通常用来表示一个指针。在平时编写代码时,也会使用这两个参数来传递数据,这时就要注意区分两个类型。
LPARAM因为是会被用作指针的类型,所以使用时,赋值要使用指针类型,或者类型的长度不能小于指针的类型。而WPARAM作为普通数值使用,可以使用当前平台的一个字,或者是固定的长度类型。
今天遇到的问题,就和这两个类型相关。示例代码如下,使用的是unsigned int类型,传递的参数名借用了WPARAM和LPARAM。
#include <stdio.h>
void func(unsigned int LPARAM, unsigned int WPARAM)
{
  unsigned int * value;
  printf("Input LPARAM: 0x%lX \n", LPARAM);
  value = (unsigned int *) LPARAM;
  *value = 100;
  printf("WPARAM is %d\n", WPARAM);
}
int main()
{
  unsigned int foo, bar;
  printf("foo addr: 0x%lX \n", &foo);
  func(&foo, bar);
  return 0;
}
        
这段代码,在ARM 32平台上执行是没问题的,但执行在ARM 64和x86-64的Ubuntu虚拟机平台上,就崩了。
我PC的处理器: Intel(R) Core(TM) i5-8400H CPU @ 2.50GHz   2.50 GHz, 64-bit operating system, x64-based processor, Windows 64系统,上面安装的64 bit的Ubuntu虚拟机。
编译并之执行上面代码:
$ gcc -o x86 test.c
$ ./x86
foo addr: 0x7FFE0163AD10
Input LPARAM: 0x163AD10
Segmentation fault (core dumped)
因为在64 位系统上,unsigned int类型大多还是4字节,long int才是8字节,而指针类型,是8字节,这样一转换,就直接挂了。
所以使用LPARAM和WPARAM参数的较好的方式如下:
#include <stdint.h>
#include <stdio.h>
void func(intptr_t LPARAM, uint32_t WPARAM)
{
  int * value;
  printf("Input LPARAM: 0x%lX \n", LPARAM);
  value = (int *) LPARAM;
  *value = 100;
  printf("Input WPARAM is %d \n", WPARAM);
}
int main()
{
  unsigned int foo, bar;
  bar = 1000;
  printf("foo addr size %ld %ld, value 0x%lX\n", sizeof(&foo), sizeof(unsigned long) , (unsigned long)&foo);
  func((intptr_t)&foo, bar);
  printf("foo is %d, bar is %d. \n", foo, bar);
  return 0;
}
     
输出:
$ gcc -o x86 test.c
$ ./x86
foo addr size 8 8, value 0x7FFE82FD8750
Input LPARAM: 0x7FFE82FD8750
Input WPARAM is 1000
foo is 100, bar is 1000.
LPARAM类型使用intptr_t类型,在stdint.h中定义,32位系统就是4字节,64位系统就是8字节,适配系统,大小自动调节。
WPARAM类型使用uint32_t类型,在stdint.h中定义,使用固定大小,正常应该能满足需求,并且32位、64位系统的int 类型大多同样是4字节。
参考:
1,Microsoft
What do the letters W and L stand for in WPARAM and LPARAM? - The Old New Thing
2,Stackoverflow
c# - What are the definitions for LPARAM and WPARAM? - Stack Overflow

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/782519.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何过得更幸福?我推荐你读这5本书

快乐不等于幸福。快乐是一种短暂的体验&#xff0c;随着多巴胺的消退而迅速减退。快乐是有捷径的&#xff0c;那就是戏弄相关的神经回路。 幸福是有意义、有目的和积极的生活的持久体验。 今天&#xff0c;为大家推荐一份“幸福书单”。 01 《幸福的勇气》 岸见一郎、古贺史…

【jenkins+cmake+svn管理c++项目】jenkins回传文件到svn(windows)

书接上文&#xff1a;创建一个项目 在经过cmakemsbuild顺利生成动态库之后&#xff0c;考虑到我一个项目可能会生成多个动态库&#xff0c;它们分散在build内的不同文件夹&#xff0c;我希望能将它们收拢到一个文件夹下&#xff0c;并将其回传到svn。 一、动态库移位—cmake实…

45 对接海康视频九宫格的实现

前言 这里主要是 来看一下 海康视频 的一个九宫格播放的需求 然后 在实际使用的过程中产生了一些问题, 比如 增加一个视频, 应该只增量请求这一个视频的服务, 而一些实现下是全量请求了 整个视频列表的服务 另外 就是全屏播放, 如果是 自己写样式来实现 全屏播放, 可能需要 …

使用vagrant快速创建linux虚拟机

1. 技术解释 vagrant&#xff1a;是一款用于管理虚拟机的命令行使用软件&#xff0c;用Ruby语言开发而成&#xff0c;可以通过 Vagrant 封装一个 Linux 的开发环境&#xff0c;是一款用来构建虚拟开发环境的工具。使用vagrant可以省去你使用虚拟机创建操作系统的所有操作&…

场效应管(MOS管)知识点总结

目录 一、场效应管(FET)基础知识 1.名称 2.电路符号 3.分类 4.应用场景 5.厂商介绍 二、MOS管G、S、D以及判定 三、耗尽型场效应管工作原理 (耗尽型&#xff1a;depletion mode) 四、NMOS与PMOS的区别 (区别&#xff1a;difference) (多晶硅&#xff1a;polysilicon) …

zookeeper 监控 与 JVM 设置

一、通过JMX监控 JVM 默认情况下&#xff0c;在 ./bin/zkServer.sh 脚本中是默认开启了JMX监控的&#xff0c;并且是不需要认证的&#xff0c;详情可见ZOOMAIN变量&#xff1b; ZOOMAIN"-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port$JMXPORT -D…

vue内置组件、特殊元素、组件api详解

vue3移动端项目搭建&#xff0c;vue3vantviteaxiospiniasass完整版代码下载&#xff1a; https://download.csdn.net/download/randy521520/88820174 vue3移动端项目构建TS&#xff0c;vue3vantviteaxiospiniasasstypescript完整版代码下载&#xff1a; https://download.csdn.…

java中的多态以及对象的类型转换

多态 多态指的就是同一事物在不同情况下表现出来的不同状态或者行为。在java中&#xff0c;当调用同一个方法时&#xff0c;由于对象存在差异&#xff0c;不同的对象之间可能存在不同的行为&#xff0c;当父类引用指向了子类对象&#xff0c;用这个父类引用调用子类中重写的方法…

深度学习十大算法之Diffusion扩散模型

1. 引言 扩散模型在近年来成为了热门话题&#xff0c;其火速蹿红主要归功于在图像生成领域的突破应用。尤其是一些从文本到图像的生成技术&#xff0c;它们成功地运用了扩散模型来创建令人惊叹的逼真图像。如果你听说过某个应用能够迅速且高质量地生成图像&#xff0c;那么很可…

【效率提升】Xinstall免填邀请码,让App注册更便捷

在移动互联网时代&#xff0c;App已经成为我们生活中不可或缺的一部分。然而&#xff0c;每当我们要尝试一个新的App时&#xff0c;繁琐的注册流程总是让人感到头疼。其中&#xff0c;填写邀请码这一环节更是让许多人望而却步。幸运的是&#xff0c;Xinstall作为国内专业的App全…

每日OJ题_栈⑤_力扣946. 验证栈序列

目录 力扣946. 验证栈序列 解析代码 力扣946. 验证栈序列 946. 验证栈序列 难度 中等 给定 pushed 和 popped 两个序列&#xff0c;每个序列中的 值都不重复&#xff0c;只有当它们可能是在最初空栈上进行的推入 push 和弹出 pop 操作序列的结果时&#xff0c;返回 true&a…

数据链路层之信道:数字通信的桥梁与守护者

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

C#/BS手麻系统源码 手术麻醉管理系统源码 商业项目源码

C#/BS手麻系统源码 手术麻醉管理系统源码 商业项目源码 手麻系统从麻醉医生实际工作环境和流程需求方面设计&#xff0c;与HIS&#xff0c;LIS&#xff0c;PACS&#xff0c;EMR无缝连接&#xff0c;方便查看患者的信息;实现术前、术中、术后手术麻醉信息全记录;减少麻醉医师在…

.NET Core教程:深入实践与实例解析

.NET Core教程&#xff1a;深入实践与实例解析 随着技术的发展&#xff0c;.NET Core作为微软推出的一个开源、跨平台的.NET实现&#xff0c;已经越来越受到开发者的青睐。本文将详细讲解.NET Core的基础知识&#xff0c;并通过实例来解析其关键特性和使用方法。 一、.NET Co…

AI程序员Devin的开源替代Devika

前天介绍了 AI软件工程师 微软AI 程序员AutoDev&#xff0c;自主执行工程任务生成代码-CSDN博客 今天介绍下另一款Devin替代品&#xff0c;开源的Devika (另外还有一个开源的 OpenDevin : https://github.com/OpenDevin/OpenDevin) Devika https://github.com/stitionai/dev…

Redis在多节点上如何实现分布式锁?

在多个 Redis 节点上实现分布式锁可以通过以下步骤来完成&#xff1a; 选择分布式锁的实现方式&#xff1a;有多种实现分布式锁的方式&#xff0c;如使用 Redis 的普通锁、RedLock 等。RedLock 是一种基于多个 Redis 节点的分布式锁实现&#xff0c;它通过在多个节点上获取锁来…

awesome-cheatsheets:超级速查表 - 编程语言、框架和开发工具的速查表

awesome-cheatsheets&#xff1a;超级速查表 - 编程语言、框架和开发工具的速查表&#xff0c;单个文件包含一切你需要知道的东西 官网&#xff1a;GitHub - skywind3000/awesome-cheatsheets: 超级速查表 - 编程语言、框架和开发工具的速查表&#xff0c;单个文件包含一切你需…

Python:魔法函数

注意&#xff1a;本文引用自专业人工智能社区Venus AI 更多AI知识请参考原站 &#xff08;[www.aideeplearning.cn]&#xff09; Python 的魔法函数&#xff0c;又称为特殊方法&#xff0c;是 Python 类中定义的一组特殊的方法&#xff0c;具有一些独特的特性和用途。这些方法…

今日总结2024/3/30

今日学习了基本数论内容,LCM,GCD以及筛素数 GCD-最大公约数 int gcd(int a,int b){//迭代法 while(b){//要保证a大于b int ta%b; ab; bt; } return a }//辗转相除法int gcd(int a,int b){//递归法return b?gcd(b,a%b):a;//一定要保证a大于b } LCM-最小公倍数 可以套公式LC…

解决WordPress文章的段落首行自动空两格的问题

写文章时&#xff0c;段落首行都会空两格&#xff0c;可是WordPress自带的编辑器却没有考虑到这一点&#xff0c;导致发布的文章首行都是顶格的&#xff0c;看起来很不习惯。 我们通常的解决方法都是在发布文章时把编辑器切换到“文本”模式&#xff0c;然后再在首行手动键入两…