首页 > 代码库 > 创建Windows类

创建Windows类

Windows中窗口,控件,对话框实质上都是窗口,Windows类是一种Windows可以处理的窗口类型描述。在Windows中有大量预定义的Windows类,但是也可以方便的创建自己的Windows类。对于每个应用程序,至少需要创建一个Windows类。以Windows类为模版,生成窗口,处理消息。

有两种数据结构可用于保存Windows类消息:WNDCLASS和WNDCLASSEX。WNDCLASS、是一种较早的数据结构,已不再使用,现在使用新的扩展版本WNDCLASSEX。

WNDCLASSEX的结构为:
typedef struct tagWNDCLASSEXW {
    UINT        cbSize; //结构大小
    /* Win 3.x */
    UINT        style; //样式标记
    WNDPROC     lpfnWndProc;//指向事件处理程序的函数指针
    int         cbClsExtra;//额外的类信息
    int         cbWndExtra;//额外的窗口信息
    HINSTANCE   hInstance;//应用程序实例
    HICON       hIcon;//主图标
    HCURSOR     hCursor;//鼠标图像
    HBRUSH      hbrBackground;//用于绘制窗口的背景刷
    LPCWSTR     lpszMenuName;//菜单名称
    LPCWSTR     lpszClassName;//类名
    /* Win 4.0 */
    HICON       hIconSm;//小图标句柄
} WNDCLASSEXW

创建一个这样的数据结构,并对其每个字段赋值。
WNDCLASSEX wcex;
第一个字段 cbSzie ,为结构WNDCLASSEX自身的大小,是给其他函数使用的而不是给自己知道的。设置为 
wcex.cbSize = sizeof(WNDCLASSEX);
样式标记style ,描述窗口的常规属性。属性的组合依然使用OR 即 | 来进行组合。
CS_BYTEALIGNCLIENT: 在字节边界上(在x方向上)定位窗口的用户区域的位置
CS_BYTEALIGNWINDOW: 在字节边界上(在x方向上)定位窗口的位置
CS_CLASSDC: 该窗口类的所有窗口实例都共享一个窗口类DC
CS_DBLCLKS: 允许向窗口发送双击鼠标键的消息
CS_GLOBALCLASS: 当调用CreateWindow 或 CreateWindowEx 函数来创建窗口时允许它的hInstance参数和注册窗口类时传递给RegisterClass 的 hInstance参数不同。如果不指定该风格,则这两个 hInstance 必须相同。
CS_HREDRAW: 当水平长度改变或移动窗口时,重画整个窗口
CS_NOCLOSE: 禁止系统菜单的关闭选项
CS_OWNDC: 给予每个窗口实例它本身的DC。注意,尽管这样是很方便,但它必须慎重使用,因为每个DC大约要占800个字节的内存。
CS_PARENTDC: 将子窗口的裁剪区域设置到父窗口的DC中去,这样子窗口便可以在父窗口上绘制自身。注意,这是子窗口还是从系统缓存中获取DC,而不是使用父窗口的DC。使用该风格可以提高系统性能。
CS_SAVEBITS: 以位图形式保存被该窗口遮挡的屏幕部分,这样当给窗口移动以后,系统便可以用该保存的位图恢复屏幕移动的相应部分,从而系统不用向被该窗口遮挡的窗口发送 WM_PAINT 消息。该特性对于菜单类型的窗口比较合适,因为它通常是简短的显示一下之后便消失。设置该特性将增加显示该窗口的时间,因为它通常要先分配保存位图的内存。
CS_VREDRAW: 当垂直长度改变或移动窗口时,重画整个窗口
这里对CS_OWNDC和CS_CLASSDC要讨论一下:


首先,在没有这两个属性时,在调用GetDC或BeginPaint时,windows用默认值创建一个设备描述表,对设备描述表属性所做的一切改变在ReleaseDC或EndPaint使用后都会失效。如果不想使用默认属性,那么可以使用CS_OWNDC 和 CS_CLASSDC 自己定义设备描述表属性。 
使用CS_OWNDC,这个窗口类的每一个窗口都被创建了一个设备描述表,且一直存在直到窗口被删除。只需要初始化一次设备描述表(可以在WM_CREATE消息期间完成)当然可以在需要时改变,以后每次调用GetDC和BeginPaint函数时返回的的设备描述表就是用你刚刚设置的设备描述表了。CS_OWNDC风格只影响GetDC和BeginPaint获得的设备描述表,不影响其它函数(如GetWindowDC)获得设备描述表。
而使用CS_CLASSDC与CS_OWNDC不同的地方是,窗口类使用此风格时,只创建一个设备描述表为所有的窗口,所有的窗口共享这一个设备描述表(且是互斥的)。


然后是参数 lpfnWndProc ,为一个函数指针,指向事件处理程序,SDK中函数一般都为回调函数。回调函数,__stdcall被typedef为 CALLBACK,意思即为回调。回调的基本特征是被调用函数指针作为调用函数的参数,且使用__stdcall ,由被调用函数清除栈。回调函数的被调用函数只传递一个接口,而调用函数中实现被调用函数,并设置调用方式。


接下来两个字段 cbClsExtra 和 cbWndExtra ,最初设计用来指示Windows在Windows类中保留一些额外空间,以保存运行时信息。但是,现在基本都不使用这两个字段,都设置为0.


下一个字段为hInstance ,这个字段为程序驱动时传递给WinMain()函数的hinstance,即系统启动程序时生成的该进程的实例句柄。
hIcon 为应用程序的图标 句柄。使用函数LoadIcon()加载系统图标。
hCursor,为光标句柄。使用LoadCursor进行加载。
hbrBackground 为重新绘制或刷新窗口时,Windows至少会使用预定义的颜色重新绘制窗口客户区域的背景,即重刷的画刷。画刷,画笔,,颜色,图形为GDI的组成部分。一般使用函数GetStockObject()获得系统的一些画刷。另一种写法是直接(HBRUSH)(COLOR_WINDOW+1) 。
接下来字段为ipszMenuName,为一个以NULL结尾的字符串,包含加载到窗口上的菜单资源的名称。
ipszClassName中保存Windows类的名字,系统需要跟踪识别这些类,所以要有名字。一般为以NULL为结尾的字符串。
最后一个为小 图标,显示在win7的任务栏上的图标。
这样就完全定义了一个Windows类。

创建Windows类