上一文中,我们介绍了windows系统三种窗口类——系统窗口类、全局窗口类和局部窗口类。每种窗口类在操作系统中的作用域不同,而且每个作用域内注册的窗口类名称是不能重复的。而创建窗口时往往会在系统、全局、局部范围按照窗口类名称进行寻找,寻找过程总结如下:
(1)操作系统根据传入的窗口类名称,现在局部窗口类中进行查找,如果找到执行第2步,如果未找到执行第3步。
(2)比较局部窗口类和创建窗口时传入的HINSTANCE变量。如果发现相等,说明创建和注册的窗口在同一个模块,创建窗口返回。如果不相等,继续执行第3步。
(3)在应用程序全局窗口类中进行查找,如果找到,执行第4步,如果未找到执行第5步。
(4)使用找到的窗口类的信息,创建窗口并返回。
(5)在系统窗口类中查找,如果找到就创建窗口,未找到就是创建窗口失败。
RegisterClass和RegisterClassEx都能用于注册窗口类,他们两个的原型分别如下:
ATOM WINAPI RegisterClass( _In_ const WNDCLASS *lpWndClass ); ATOM WINAPI RegisterClassEx( _In_ const WNDCLASSEX *lpwcx );
从API原型上看可以看出,二者的区别主要在于接收的参数上,这个参数就是我们需要注册的窗口类。这两个窗口类声明如下:
typedef struct tagWNDCLASS { UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; } WNDCLASS, *PWNDCLASS;
typedef struct tagWNDCLASSEX { UINT cbSize; UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; HICON hIconSm; } WNDCLASSEX, *PWNDCLASSEX;
从上面的代码可以看到,两个窗口类结构体的主要区别在于WNDCLASSEX含有cbSize窗口的结构体大小和hIconSm窗口的小图标句柄。其他参数的含义请自行参考MSDN。
GetClassInfo() API可以获取已经注册的窗口的信息,其函数原型如下:
BOOL WINAPI GetClassInfo( _In_opt_ HINSTANCE hInstance, _In_ LPCTSTR lpClassName, _Out_ LPWNDCLASS lpWndClass );
hInstance—— 是设置查找的作用域,如果设为NULL,会从系统、全局和局部三个作用域查找。
lpClassName —— 是要查找的窗口类名称。
lpWndClass —— 传入的WndClass结构体变量的地址,用于接收窗口类信息。
我们来查找上文创建的Button类的窗口信息:
WNDCLASS wc; if (GetClassInfo(NULL, "Button", &wc) == false) MessageBox(NULL,"GetClassInfo Faile",NULL,NULL);
我们来通过设置断点,查看获取的Button窗口类的信息:
我们可以通过UnregisterClass可以将已经注册的窗口类进行卸载,其原型如下:
BOOL WINAPI UnregisterClass( _In_ LPCTSTR lpClassName, _In_opt_ HINSTANCE hInstance );
lpClassName —— 是要卸载的窗口类名称。
hInstance —— 是设置查找的作用域,如果设为NULL,会从系统、全局和局部三个作用域查找。
以下代码,将注册的Button窗口类进行卸载:
if (UnregisterClass("Button",NULL) == false) MessageBox(NULL, "UnregisterClass Faile", NULL, NULL);
以上是Win32 SDK基础(六)之详解窗口类的查找过程和相关API的详细内容。更多信息请关注PHP中文网其他相关文章!