📄 g02.htm
字号:
<p> 下面两个字段,cbClsExtra和cbWndExtra原是为指示Windows将附加的运行时间信息保存到Windows类某些单元中而设计的。但是绝大多数人使用这些字段并简单地将其值设为0,如下所示:<br> winclass.cbClsExtra = 0;//extra class info space<br> winclass.cbWndExtra = 0;//extra window info space<br> 下一个是hInstance字段。这是一个简单的、在启动时传递给WinMain()函数的句柄实例,因此只需简单地从WinMain()中复制即可:<br> winclass.hInstance = hinstance;//assign the application instance<br> 剩下的字段和Windows类的图像方面有关,在讨论它们之前,先花一点时间回顾一下句柄。<br> 在Windows程序和类型中将一再看到句柄:位图句柄、光标句柄、任意事情的句柄。请记住,句柄只是一个基于内部Windows类型的标识符。其实它们都是整数。但是Microsoft可能改变这一点,因此安全使用Microsoft类型是个好主意。总之,你将会看到越来越多的“[...]句柄”,请记住,有前缀h的任何类型通常都是一个句柄。好,回到原来的地方继续吧。<br> 下一个字段是设定表示应用程序的图标的类型。你完全可以装载一下你自己定制的图标,但现在你使用系统图标,需要为它设置一个句柄。要为一个常用的系统图标检索一个句柄,可以使用LoadIcon()函数:<br> winclass.hIcon = loadIcon(NULL,IDI_APPLICATION);<br> 这行代码装载一个标准的应用程序图标——虽然烦人,但是简单。如果对LoadIcon()函数有兴趣的话,请看下面的它的原型,表2.7给出了几个图标选项:<br> HICON LoadIcon(HINSTANCE hInstance,//handle of application instance<br> LPCTSTR lpIconName;//icon-name string or icon resource identifier<br> hInstance是一个从应用程序装载图标资源的实例(后面将详细讨论)。现在将它设置为NULL来装载一个标准的图标。LpIconName是包含被装载图标资源名称的NULL终止字符串。当hInstance为NULL时,IpIconName的值如表2.7所示。<br> <b>LoadIcon()的图标标识符</b><br> ─────────┬───────────────────────<br> 值 │ 说明<br> ─────────┼───────────────────────<br> IDI_APPLICATION │默认应用程序图标<br> IDI_ASTERISK │星号<br> IDI_EXCLAMATION │惊叹号<br> IDI_HAND │手形图标<br> IDI_QUESTION │问号<br> IDI_WINLOGO │Windows徽标<br> ─────────┴───────────────────────<br> 好,现在我们已经介绍了一半的字段了。做个深呼吸休息一会,让我们进行下一个字段hCursor的介绍。和hIcon相似,它也是一个图像对象句柄。不同的是,hCursor是一个指针进入到窗口的用户区才显示的光标句柄。使用LoadCursor()函数可以得到资源或预定义的系统光标。我们将在后面讨论资源,简单而言资源就是像位图、光标、图标、声音等一样的数据段,它被编译到应用程序中并可以在运行时访问。Windows类的光标设定如下所示:<br> winclass.hCursor = LoadCursor(NULL,IDC_ARROW);<br> 下面是LoadCursor()函数的原型(表2.8列出了不同的系统光标标识符):<br> HCURSOR lpCursor(HINSTANCE hInstance,//handle of application instance<br> LPCTSTR lpCursorName);//icon_name string or icon resource identifier<br> hInstance是你的.EXE的应用程序实例。该.EXE应用程序包含订制光标名称来源的资源。但现在读者还不能使用该功能,仅将默认的系统光标值设定为NULL。<br> lpCursorName标识了资源名字符串或资源句柄(我们一般不使用),或者是一个常数,以标识如表2.8中所示的系统默认值。<br> <b>表2.8 LoadCursor()的值</b><br> ────────┬────────────────────────<br> 值 │ 说明<br> ────────┼────────────────────────<br> IDC_ARROW │标准箭头<br> IDC_APPSTARTING│标准箭头和小沙漏标<br> IDC_CROSS │横标线<br> IDC_IBEAM │文本I型标<br> IDC_NO │带正斜线的圆圈<br> IDC_SIZEALL │四向箭头<br> IDC_SIZENESW │指向东北-西南方向的双向箭头<br> IDC_SIZENS │指向南北方向的双向箭头<br> IDC_SIZENWSE │指向东南-西北方向的双向箭头<br> IDC_SIZEWE │指向东西方向的双向箭头<br> IDC_UPARROW │垂直方向的箭头<br> IDC_WAIT │沙漏<br> ────────┴────────────────────────<br> 现在我们就要解放了,因为我们几乎已经全部介绍完了——剩下的字段更有意义。让我们看一看hbrBackground。<br> 无论在什么时候绘制或刷新一个窗口,Windows都至少将以用户预定义的颜色或Windows内部设置的画笔颜色填充该窗口的背景。因此,hbrBrackground是一个用于窗口刷新的画笔句柄。画笔、笔、色彩和图形都时GDI(图形设备接口)的一部分,我们将在下一章中详细讨论。现在,介绍一下如何申请一个基本的系统画笔来填充窗口。该项功能由GetStockObject()来实现,如下面程序所示:<br> winclass.hbrBackground = GetStockObject(WHITE_BRUSH);<br> GetStockObject()是一个通用函数,用于获得Windows系统画笔、笔、调色板或字体的一个句柄。GetStockObject()只有一个参数,用来指示装载哪一项资源。表2.9仅列出了画笔和笔的可能库存对象。<br> 表2.9 GetStockObject()的库存对象标识符<br> ────────┬────────────────────────<br> 值 │ 说明<br> ────────┼────────────────────────<br> BLACK_BRUSH │黑色画笔<br> WHITE_BRUSH │白色画笔<br> GRAY_BRUSH │灰色画笔<br> LTGRAY_BRUSH │淡灰色画笔<br> DKGRAY_BRUSH │深灰色画笔<br> HOLLOW_BRUSH │空心画笔<br> NULL_BRUSH │无效(NULL)画笔 <br> BLACK_PEN │黑色笔<br> WHITE_PEN │白色笔<br> NULL_PEN │无效(NULL)笔<br> ────────┴────────────────────────<br> WNDCLASS 结构中的下一个字段是lpszMenuName。它是菜单资源名称的空终止ASCII字符串,用于加载和选用窗口。其工作原理将在第三章“高级Windows编程”中讨论。现在我们只需要将值设为NULL。<br> winclass.lpszmenuNume = NULL://the name of the menu to attach<br> 如我刚提及的那样,每个Windows类代表你的应用程序所创建的不同窗口类型。在某种程序上,类与模板相似,Windows需要一些途径来跟踪和识别它们。因此,下一个字段lpszClassName,就用于该目的。该字段被赋以包含相关类的文本标示符的空终止字符串。我个人喜欢用诸如“WINCLASS1”、“WINCLASS2”等标示符。读者以自己喜好而定,以简单明了为原则,如下所示:<br> Winclass.lpszClassName="WINCLASS1"//the name of the class itself<br> 这样赋值以后,你可以使用它的名字来引用这个新的Windows类——很酷,是吗?<br> 最后就是小应用程序图表。这是Windows类WINCLASSEX中新增加的功能,在老版本WNDCLASS中没有。首先,它是指向你的窗口标题栏和Windows桌面任务样的句柄。你经常需要装载一个自定义资源,但是现在只要通过LoadIcon()使用一个标准的Windows图标即可实现:<br> winclass.hIconSm = LoadIcon(NULL,IDI_APPLICATION);//小图标句柄<br> 下面让我们迅速回顾一下整个类的定义:<br> WNDCLASSEX winclass;//this will hole the class we create<br> //first fill in the window class structure<br> winclass.cbSize = sizeof(WNDCLASSEX);<br> winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;<br> winclass.lpfnWndProc = WindowProc;<br> winclass.cbClsExtra = 0;<br> winclass.cbWndExtra = 0;<br> winclass.hInstance = hinstance;<br> winclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);<br> winclass.hCursor = LoadCursor(NULL,IDC_ARROW);<br> winclass.hbrBacground = GetStockObject(BLACK_BRUSH);<br> winclass.lpszMenuName = NULL;<br> winclass.lpszClassName = "WINCLASS";<br> winclass.hIconSm = LoadIcon(NULL,IDI_APPLICATION);<br> 当然,如果想节省一些打字时间的话,可以像下面这样简单地初始化该结构:<br> WNDCLASSEX winclass = {<br> winclass.cbSize = sizeof(WNDCLASSEX);<br> CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW,<br> WindowProc,<br> 0,<br> 0,<br> hinstance,<br> LoadIcon(NULL,IDI_APPLICATION),<br> LoadCursor(NULL,IDC_ARROW),<br> GetStockObject(BLACK_BRUSH),<br> NULL,<br> "WINCLASS1",<br> LoadIcon(NULL,IDI_APPLICATION)};<br> 这样就省去了许多输入!</p> <p><b>注册Windows类</b></p> <p> 现在Windows类已经定义并且存放在winclass中,必须将新的类通知Windows。该功能通过RegisterClassEx()函数,使用一个指向新类定义的指针来完成,如下所示:<br> RegisterClassEx(&winclass);<br> 警告:注意我并没有使用我们例子中的“WINCLASS1”的类名,对于RegisterClassEx()来讲,必须使用保存该类的实际结构,因为在该类调用RegisterClassEx()函数之前,Windows并不知道该类的存在,明白了吧?<br> 此外还有一个旧版本的RegisterClass()函数,用于注册基于旧结构WINCLASS基础上的类。该类一旦注册,我们就可以任意创建它的窗口。请看下面如何进行这个工作,然后再详细看一下事件句柄和主事件循环,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -