一、引言 在上一文中,我们从零开始创建了一个窗口。其中很重要的一个步骤,就是注册窗口类,如下面的代码:
//注册窗口类
bool register(lpstr lpclassname, wndproc wndproc)
{
wndclassex wce = { 0 };
wce.cbsize = sizeof(wce);
wce.cbclsextra = 0;
wce.cbwndextra = 0;
wce.hbrbackground = (hbrush)(color_window + 1);
wce.hcursor = null;
wce.hicon = null;
wce.hiconsm = null;
wce.hinstance = g_hinstance;
wce.lpfnwndproc = wndproc;
wce.lpszclassname = lpclassname;
wce.lpszmenuname = null;
wce.style = cs_hredraw | cs_vredraw;
atom natom = registerclassex(&wce);
if (natom == 0)
return false;
return true;
}
windows下的任何一个窗口,在创建之前都要在系统中已经明确的注册,我们在使用createwindowex进行窗口的创建时,第二个参数的名称就是窗口类名称,这个名称在我们代码可见的作用域内应该是唯一的。本文主要讨论下windows下,窗口类的问题。
二、窗口类分类 windows中所有可见的一切元素基本上都属于一个窗口,不管它的形状如何,是圆的、方的、甚至是无规则的。所有的这些窗口都属于某一个窗口类,大体上来说windows的窗口类共分为三种:
(1)系统窗口类
(2)全局窗口类
(3)局部窗口类
下面,我将就windows中窗口类的分类分别进行讨论。
2.1 系统窗口类 一个按钮、一个编辑框所有这些我们在windows操作系统中可见的控件其实都是一个窗口。当我们安装完操作系统之后,windows会在操作系统内部注册大量的系统级别的窗口类,我们在进行开发时,可以直接根据窗口类名称创建这些窗口。为了解释这个问题,在上一文中的代码之上,我们引入下面的代码。
hwnd createmain(lpstr lpclassname, lpstr lpwndname)
{
hwnd hwnd = createwindowex(0, lpclassname, lpwndname,
ws_overlappedwindow, cw_usedefault, cw_usedefault, cw_usedefault, cw_usedefault, null, null, g_hinstance, null);
return hwnd;
}
int apientry wwinmain(_in_ hinstance hinstance,
_in_opt_ hinstance hprevinstance,
_in_ lpwstr lpcmdline,
_in_ int ncmdshow)
{
// todo: place code here.
g_hinstance = hinstance;
hwnd hwnd = createmain("button", "window");
display(hwnd);
message();
return 0;
}
createmain是我们定义的一个创建窗口的函数。它接收两个参数,第一个时已经注册的窗口类名称,第二个是窗口的标题。与上一文中的代码不同,我们省去了注册自定义窗口的步骤。而是在winmain函数中,调用createmain创建了一个窗口类名称为“button”的窗口。我想你已经知道我们要做什么了吧?对,就是要生成一个button按钮。我们常用的所有控件都已经被操作系统注册成了系统窗口类,我们都可以直接使用。请看下面的程序运行结果:
你还可以尝试去创建诸如编辑框、下拉框等其他系统级别的窗口。
2.2 全局窗口类 全局窗口类指注册之后可以在应用程序全局范围内使用的窗口类。比如,我们可以在dll中对全局窗口类进行注册,那么引入该dll的所有程序都可以使用该类。注册全局使用的窗口类时,我们只需要在注册时对wec的结构体的style成员添加cs_globalclass属性,如下:
wce.style = cs_hredraw | cs_vredraw | cs_globalclass;
为了验证这个问题,我们新添加一个dll项目,然后定义一个如下的窗口注册函数registerwindow():
lresult callback wndproc(hwnd hwnd, uint umsg, wparam wparam, lparam lparam)
{
switch (umsg)
{
case wm_destroy:
postquitmessage(0);//可以使getmessage返回0
break;
default:
break;
}
return defwindowproc(hwnd, umsg, wparam, lparam);
}
bool registerwindow()
{
wndclassex wce = { 0 };
wce.cbsize = sizeof(wce);
wce.cbclsextra = 0;
wce.cbwndextra = 0;
wce.hbrbackground = (hbrush)(color_window + 1);
wce.hcursor = null;
wce.hicon = null;
wce.hiconsm = null;
wce.hinstance = null;
wce.lpfnwndproc = wndproc;
wce.lpszclassname = "dllmain";
wce.lpszmenuname = null;
wce.style = cs_hredraw | cs_vredraw | cs_globalclass;
atom natom = registerclassex(&wce);
if (natom == 0)
return false;
return true;
}
registerwindow()中注册的窗口类名称为"dllmain",我们在dll的主函数中调用该注册函数完成注册:
bool apientry dllmain( hmodule hmodule,
dword ul_reason_for_call,
lpvoid lpreserved
)
{
....
registerwindow();
return true;
}
}
在我们的主程序中使用该窗口类创建窗口:
int apientry wwinmain(_in_ hinstance hinstance,
_in_opt_ hinstance hprevinstance,
_in_ lpwstr lpcmdline,
_in_ int ncmdshow)
{
...
hwnd hwnd = createmain("dllmain", "我是一个dll注册的窗口");
display(hwnd);
message();
return 0;
}
运行程序你会发现我们也成功生产了这个窗口:
2.3 局部窗口类 局部窗口类从定义上来说,凡是未在wce的style中添加cs_globalclass,而注册的窗口类都是局部窗口类。
wce.style = cs_hredraw | cs_vredraw;//未添加cs_globalclass
我们在上一文中注册的窗口就是一个局部的窗口类,它的特点就是只能在注册的作用域内使用,由于它和全局窗口类只在注册的style和作用域上有分别,这里就不再详述,如要了解,请参照上一文。
以上就是win32 sdk基础(五)之关于窗口类的简单介绍的详细内容。