1、 LPVOID —指针
一个没有类型的指针,也就是说你可以将任意类型的指针赋值给LPVOID类型的变量(一般作为参数传递),然后在使用的时候再转换回来。可以将其理解为long型的指针,指向void型,没有函数返回值。
2、 PDWORD —短指针(LPDWORD也基本一样。)
windef.h中定义的数据类型,原文如下:
typedef DWORD near *PDWORD;
表示指向DWORD的短指针类型,是WINDOWS编程中常用的数据类型之一。
3、BOOL和bool
bool是布尔型变量,也就是逻辑型变量的定义符,类似于float,double等,只不过float定义浮点型,double定义双精度浮点型。
在objective-c中提供了相似的类型BOOL,它具有YES值和NO值。
1、类型不同
bool为布尔型用作逻辑判断
BOOL在<windef.h>typedef int BOOL;
在<wtypes.h>typedef long BOOL;
2、长度不同
bool只有1个字节
BOOL长度视实际环境来定,一般可认为是4个字节
3、取值不同
bool取值false和true,是0和1的区别;
false可以代表0,但true有很多种,并非只有1。
如果数个bool对象列在一起,可能会各占一个Byte,这取决于编译器。
BOOL是微软定义的typedef int BOOL(在windef.h中)。与bool不同,它是一个三值逻辑,
TRUE/FALSE/ERROR,返回值为大于0的整数时为TRUE,返回值为0时候,为FALSE,返回值为-1时为ERROR。
Win32 API中很多返回值为BOOL的函数都是三值逻辑。
bool布尔型变量的值只有
真 (true) 和假 (false)。
布尔型变量可用于逻辑表达式,也就是“或”“与”“非”之类的逻辑运算和大于小于之类的关系运算,逻辑表达式运算结果为真或为假。
bool可用于定义函数类型为布尔型,函数里可以有
return TRUE; return FALSE 之类的语句。
布尔型运算结果常用于条件语句,
if (逻辑表达式)
{
如果是 true 执行这里;
}
else
{
如果是 false 执行这里;
};
4、NEW分配内存
New:new/delete 是C++的运算符。可用于申请动态内存和释放内存。C++语言需要一个能完成动态内存分配和初始化工作的运算符new, 以一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。C++程序经常要调用C函数,而C程序只能用malloc /free管理动态内存。new 是个操作符,和什么"+","-","="...有一样的地位.
5、HWND
h 是类型描述,表示句柄(handle), Wnd 是变量对象描述,表示窗口,所以hWnd 表示窗口句柄,通俗地说,如果把一个到处跑的人当作指针的话,那么HWND就是该人的身份证----我想应该是身份证号码。
返回窗体或控件的句柄(注意
OLE 容器控件不支持该属性。句柄:是由操作环境定义的一个唯一的整数值,它被程序用来标识或者切换到对象,如窗体或控件等。)。
Microsoft Windows 运行环境,通过给应用程序中的每个窗体和控件分配一个句柄(或
hWnd)来标识它们。hWnd 属性用于Windows API调用。许多 Windows 运行环境函数需要活动窗口的
hWnd 作为参数。
注意 由于该属性值在程序运行时可以改变,绝对不要将 hWnd 存储在变量中。如果 User Control 的 Windowless 属性设为 True, 则
hWnd 属性将返回 0 。
6、UNIT
UINT类型在WINDOWS API中有定义,它对应于32位无符号整数。在C, C++中不存在UINT这个关键字,UINT类型是unsigned int派生出来的。
typedef unsigned int
UINT;
typedef unsigned int
UINT32;
typedef signed int
INT32;
typedef unsigned long
DWORD;
typedef unsigned short
WORD;
7、WPARAM
WPARAM,消息响应机制
wParam和lParam 这两个是Win16系统遗留下来的产物,在Win16API中WndProc有两个参数:
一个是WORD类型的16位整型变量;另一个是LONG类型的32位整型变量。因此根据匈牙利命名法,16位的变量就被命名为wParam,
32位的变量就被命名为lParam。
到了Win32API中,原来的16位变量也被扩展为32位,因此此时wParam和lParam的大小完全相同。
在Win32API的早期,为了保证和Win16API的代码可移植性MS定义了WPARAM和LPARAM两个宏。
当时保留了w前缀的原因一方面是由于WPARAM宏也以W开头,还有也因为要提醒程序员注意到可移植性,当然到了现在Win16早已退出历史舞台,这个前缀也就约定俗成的沿用下来了。
WPARAM 和 LPARAM 本质上没有什么区别:都是32位数,
但是区别也还是有的:除了关于16位的的历史问题外,MICROSOFT在使用时两种参数分别代表不同的含义和内容,WPARAM常常代表一些控件的ID或者高位底位组合起来分别表示鼠标的位置,如果消息的发送者需要将某种结构的指针或者是某种类型的句柄时,习惯上用LPARAM来传递,可以参考各种控件的通知消息:可以查看:EN_CHANGE
(EDIT控件的一个通知消息),CBEM_INSERTITEM(可扩展组合框的可接受消息)等等来加以领会。
理论上在使用自定义消息时,WPARAM LPARAM的含义可以程序员任意指定的,但是最好遵从MFC中的习惯。在调用SendMessage()函数时,第二个参数是WPARAM,第三个参数是这个消息的LPARAM,但是你在程序中某个类中写下ON_MESSAGE()宏来处理这个消息时,处理函数SomeHandler(WPARAM,LPRAM(默认是0))中解释这两个参数时必须按照SendMessage调用中的意义来进行。
8、__cdecl 、_stdcall、PASCAL 、_fastcall、_thiscall的区别与联系
__cdecl 是C Declaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数不会要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。
_stdcall 是StandardCall的缩写,是C++的标准调用方式:所有参数从右到左依次入栈,如果是调用类成员的话,最后一个入栈的是this指针。这些堆栈中的参数由被调用的函数在返回后清除,使用的指令是
retnX,X表示参数占用的字节数,CPU在ret之后自动弹出X个字节的堆栈空间。称为自动清栈。函数在编译的时候就必须确定参数个数,并且调用者必须严格的控制参数的生成,不能多,不能少,否则返回后会出错。
PASCAL 是Pascal语言的函数调用方式,也可以在C/C++中使用,参数压栈顺序与前两者相反。返回时的清栈方式与_stdcall相同。
_fastcall是编译器指定的快速调用方式。由于大多数的函数参数个数很少,使用堆栈传递比较费时。因此_fastcall通常规定将前两个(或若干个)参数由寄存器传递,其余参数还是通过堆栈传递。不同编译器编译的程序规定的寄存器不同。返回方式和_stdcall相当。
_thiscall 是为了解决类成员调用中this指针传递而规定的。_thiscall要求把this指针放在特定寄存器中,该寄存器由编译器决定。VC使用ecx,Borland的C++编译器使用eax。返回方式和_stdcall相当。
_fastcall 和 _thiscall涉及的寄存器由编译器决定,因此不能用作跨编译器的接口。所以Windows上的COM对象接口都定义为_stdcall调用方式。
C中不加说明默认函数为_cdecl方式(C中也只能用这种方式),C++也一样,但是默认的调用方式可以在IDE环境中设置。带有可变参数的函数必须且只能使用_cdecl方式。
9、typedef LONG_PTR LPARAM;typedef UINT_PTR WPARAM;
先告诉你,这2个数据类型很重要,不是危言耸听,以后你写SDK程序就知道了,看他们的定义如上,有些迷糊? 别,我们一步一步分析,我们分析LPARAM。首先定义LPARAM 为LONG_PTR也就是用LPARAM的地方也就可以写成LONG_PTR,LONG_PTR又是被定义成什么的呢?
typedef
long LONG_PTR;
看到了吗? 也就是long 所以归根结底,LPARAM 就是long型,所有LPARAM型的变量,你都可以直接使用long数据类型代替。不过不推荐这样,至于为什么,各位思考思考呢~~
以上这些数据类型是参考MSDN中的说明,或者可以查看WinDef.h这个头文件查看这些Windows数据类型的定义,那么也请各位自己推推看LARAM和WPARAM的真面目吧~
各位朋友在推导的过程中可能发现LONG_PTR的定义是这样写的
#if defined(_WIN64)
typedef __int64 LONG_PTR;
#else
typedef long LONG_PTR;
#endif
这是什么意思呢,能看懂英文都能知道这在定义些什么,如果定义了 _WIN64这个宏 那么就定义 LONG_PTR 为 __int64,否则定义LONG_PTR为long。 很简单吧 也就是说如果_WIN64这个宏在前面被定义了,那么这里的LONG_PTR就被定义为__int64这个在64位编程下的数据类型,否则就定义为long型,这样说应该比较好理解了吧。在这里,各位就不必深究__int64了,
在目前的主流32位编程下很少使用它啦。理解就ok了。这样定义是微软为了程序员编写的程序能在32位与64位下都能编译而采用的伎俩。
10、KillTimer
KillTimer:移除定时器函数的声明:移除先前用SetTimer设置的定时器。在定时器使用完毕后移除定时器时使用。
函数原型:
BOOL KillTimer(
HWND hwnd; //与定时器相关联的窗口句柄
UINT nIDEvent //定时器标识符
):
参数:
hwnd:与定时器相关联的窗口句柄
nIDEvent: 传递给SetTimer的定时器ID值。
说明:
销毁以前调用SetTimer创建的用nIDEvent标识的定时器事件。不能将此定时器有关的未处理的WM_TIMER消息都从消息队列中清除。
返回值
BOOL 如果函数成功,返回一个非0值,
如果失败,返回值为0
注意: 该函数并不移除WM_TIMER 先前发送到消息列队中的消息
补充:
如果使用.Net Framework 4.0版本的CWnd::KillTimer,可以这样调用:
KillTimer(IDT_TIMERID);//IDT_TIMERID 是 对应定时器的ID,可以这样定义:
#define IDT_TIMERID 1
11、消息响应机制
1、消息的组成:一个消息由一个消息名称(UINT),和两个参数(WPARAM,LPARAM)构成。当用户进行了输入或是窗口的状态发生改变时系统都会发送消息到某一个窗口。例如当菜单选中之后会有WM_COMMAND消息发送,WPARAM的低字中(LOWORD(wParam))是命令的ID号,对菜单来讲就是菜单ID。当然用户也可以定义自己的消息名称,也可以利用自定义消息来发送通知和传送数据。
2、谁将收到消息:一个消息必须由一个窗口接收。在窗口的过程(WNDPROC)中可以对消息进行分析,对自己感兴趣的消息进行处理。例如你希望对菜单选择进行处理那么你可以定义对WM_COMMAND进行处理的代码,如果希望在窗口中进行图形输出就必须对WM_PAINT进行处理。
3、未处理的消息到那里去了:M$为窗口编写了默认的窗口过程,这个窗口过程将负责处理那些你不处理消息。正因为有了这个默认窗口过程我们才可以利用Windows的窗口进行开发而不必过多关注窗口各种消息的处理。例如窗口在被拖动时会有很多消息发送,而我们都可以不予理睬让系统自己去处理。
4、窗口句柄:说到消息就不能不说窗口句柄,系统通过窗口句柄来在整个系统中唯一标识一个窗口,发送一个消息时必须指定一个窗口句柄表明该消息由那个窗口接收。而每个窗口都会有自己的窗口过程,所以用户的输入就会被正确的处理。例如有两个窗口共用一个窗口过程代码,你在窗口一上按下鼠标时消息就会通过窗口一的句柄被发送到窗口一而不是窗口二。
5、示例:下面有一段伪代码演示如何在窗口过程中处理消息
LONG yourWndProc(HWND hWnd,UINT uMessageType,WPARAM wP,LPARAM)
{
switch(uMessageType)
{//使用SWITCH语句将各种消息分开
case(WM_PAINT):
doYourWindow(...);//在窗口需要重新绘制时进行输出
break;
case(WM_LBUTTONDOWN):
doYourWork(...);//在鼠标左键被按下时进行处理
break;
default:
callDefaultWndProc(...);//对于其它情况就让系统自己处理
break;
}
}
接下来谈谈什么是消息机制:系统将会维护一个或多个消息队列,所有产生的消息都会被放入或是插入队列中。系统会在队列中取出每一条消息,根据消息的接收句柄而将该消息发送给拥有该窗口的程序的消息循环。每一个运行的程序都有自己的消息循环,在循环中得到属于自己的消息并根据接收窗口的句柄调用相应的窗口过程。而在没有消息时消息循环就将控制权交给系统所以Windows可以同时进行多个任务。下面的伪代码演示了消息循环的用法:
while(1)
{
id=getMessage(...);
if(id == quit)
break;
translateMessage(...);
}
当该程序没有消息通知时getMessage就不会返回,也就不会占用系统的CPU时间。
12、sendmessage
实现sendmessage发送消息的接收,在消息的接收方,覆写DefWindowProc(),在该方法中即可接收到sendmessage方法发送来的消息。因为sendmessage发送的消息,不再经过消息队列,而是直接发送给指定对象。所以一般的消息响应,包括PreTranslateMessage方法都无法接收到该信息,只能通过覆写DefWindowProc方法,来接收信息。
sendmessage将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。而和函数PostMessage不同,PostMessage是将一个消息寄送到一个线程的消息队列后就立即返回。
LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam)
参数
hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
Msg:指定被发送的消息。
wParam:指定附加的消息特定信息。
IParam:指定附加的消息特定信息。
返回值:返回值指定消息处理的结果,依赖于所发送的消息。
13、WaitForSingleObject
当等待仍在挂起状态时,句柄被关闭,那么函数行为是未定义的。该句柄必须具有 SYNCHRONIZE 访问权限。
DWORD WINAPI WaitForSingleObject(
__in HANDLE hHandle,
__in DWORD dwMilliseconds
);
参数
hHandle[in]对象句柄。可以指定一系列的对象,如Event、Job、Memory resource notification、Mutex、Process、Semaphore、Thread、Waitable timer等。
当等待仍在挂起状态时,句柄被关闭,那么函数行为是未定义的。该句柄必须具有 SYNCHRONIZE 访问权限。
dwMilliseconds[in]定时时间间隔,单位为milliseconds(毫秒).如果指定一个非零值,函数处于等待状态直到hHandle标记的对象被触发,或者时间到了。如果dwMilliseconds为0,对象没有被触发信号,函数不会进入一个等待状态,它总是立即返回。如果dwMilliseconds为INFINITE,对象被触发信号后,函数才会返回。
返回值
执行成功,返回值指示出引发函数返回的事件。
WaitForSingleObject函数用来检测hHandle事件的信号状态,在某一线程中调用该函数时,线程暂时挂起,如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。
strcpy是拷贝字符串,以\0为标志结束(即一旦遇到数据值为0的内存地址拷贝过程即停止)strcpy的原型为char
*strcpy(char *dest, const char *src)而memcpy是给定来源和目标后,拷贝指定大小n的内存数据,而不管拷贝的内容是什么(不仅限于字符)memcpy的原型为void
*memcpy(void *dest, const void *src,
size_tn);
驱动代码内部相关关键字等