📄 lion-tut-c03.htm
字号:
hInstance DWORD
? <br>
hIcon
DWORD ? <br>
hCursor DWORD
? <br>
hbrBackground DWORD
? <br>
lpszMenuName DWORD
? <br>
lpszClassName DWORD
? <br>
hIconSm DWORD
? <br>
WNDCLASSEX ENDS </p>
<ul>
<li>cbSize:WNDCLASSEX 的大小。我们可以用sizeof(WNDCLASSEX)来获得准确的值。</li>
<li> style:从这个窗口类派生的窗口具有的风格。您可以用“or”操作符来把几个风格或到一起。 </li>
<li>lpfnWndProc:窗口处理函数的指针。 </li>
<li>cbClsExtra:指定紧跟在窗口类结构后的附加字节数。</li>
<li> cbWndExtra:指定紧跟在窗口事例后的附加字节数。如果一个应用程序在资源中用CLASS伪指令注册一个对话框类时,则必须把这个成员设成DLGWINDOWEXTRA。
</li>
<li>hInstance:本模块的事例句柄。 </li>
<li>hIcon:图标的句柄。</li>
<li> hCursor:光标的句柄。 </li>
<li>hbrBackground:背景画刷的句柄。 </li>
<li>lpszMenuName:指向菜单的指针。 </li>
<li>lpszClassName:指向类名称的指针。</li>
<li> hIconSm:和窗口类关联的小图标。如果该值为NULL。则把hCursor中的图标转换成大小合适的小图标。</li>
</ul>
<p> invoke CreateWindowEx, NULL,\<br>
ADDR ClassName,\<br>
ADDR AppName,\<br>
WS_OVERLAPPEDWINDOW,\<br>
CW_USEDEFAULT,\<br>
CW_USEDEFAULT,\<br>
CW_USEDEFAULT,\<br>
CW_USEDEFAULT,\ <br>
NULL,\ <br>
NULL,\<br>
hInst,\<br>
NULL </p>
<p>注册窗口类后,我们将调用CreateWindowEx来产生实际的窗口。请注意该函数有12个参数。 </p>
<p>CreateWindowExA proto dwExStyle:DWORD,\<br>
lpClassName:DWORD,\<br>
lpWindowName:DWORD,\ <br>
dwStyle:DWORD,\<br>
X:DWORD,\<br>
Y:DWORD,\<br>
nWidth:DWORD,\<br>
nHeight:DWORD,\<br>
hWndParent:DWORD ,\<br>
hMenu:DWORD,\ <br>
hInstance:DWORD,\<br>
lpParam:DWORD</p>
<p> 我们来仔细看一看这些的参数:</p>
<ul>
<li> dwExStyle:附加的窗口风格。相对于旧的CreateWindow这是一个新的参数。在9X/NT中您可以使用新的窗口风格。您可以在Style中指定一般的窗口风格,但是一些特殊的窗口风格,如顶层窗口则必须在此参数中指定。如果您不想指定任何特别的风格,则把此参数设为NULL。</li>
<li> lpClassName:(必须)。ASCIIZ形式的窗口类名称的地址。可以是您自定义的类,也可以是预定义的类名。像上面所说,每一个应用程序必须有一个窗口类。
</li>
<li>lpWindowName:ASCIIZ形式的窗口名称的地址。该名称会显示在标题条上。如果该参数空白,则标题条上什么都没有。</li>
<li> dwStyle:窗口的风格。在此您可以指定窗口的外观。可以指定该参数为零,但那样该窗口就没有系统菜单,也没有最大化和最小化按钮,也没有关闭按钮,那样您不得不按Alt+F4
来关闭它。最为普遍的窗口类风格是 WS_OVERLAPPEDWINDOW。 一种窗口风格是一种按位的掩码,这样您可以用“or”把您希望的窗口风格或起来。像
WS_OVERLAPPEDWINDOW 就是由几种最为不便普遍的风格或起来的。 </li>
<li>X,Y: 指定窗口左上角的以像素为单位的屏幕坐标位置。缺省地可指定为 CW_USEDEFAULT,这样 Windows 会自动为窗口指定最合适的位置。
</li>
<li>nWidth, nHeight: 以像素为单位的窗口大小。缺省地可指定为 CW_USEDEFAULT,这样 Windows 会自动为窗口指定最合适的大小。</li>
<li> hWndParent: 父窗口的句柄(如果有的话)。这个参数告诉 Windows 这是一个子窗口和他的父窗口是谁。这和 MDI(多文档结构)不同,此处的子窗口并不会局限在父窗口的客户区内。他只是用来告诉
Windows 各个窗口之间的父子关系,以便在父窗口销毁是一同把其子窗口销毁。在我们的例子程序中因为只有一个窗口,故把该参数设为 NULL。</li>
<li> hMenu: WINDOWS菜单的句柄。如果只用系统菜单则指定该参数为NULL。回头看一看WNDCLASSEX 结构中的 lpszMenuName
参数,它也指定一个菜单,这是一个缺省菜单,任何从该窗口类派生的窗口若想用其他的菜单需在该参数中重新指定。其实该参数有双重意义:一方面若这是一个自定义窗口时该参数代表菜单句柄,另一方面,若这是一个预定义窗口时,该参数代表是该窗口的
ID 号。Windows 是根据lpClassName 参数来区分是自定义窗口还是预定义窗口的。 </li>
<li>hInstance: 产生该窗口的应用程序的实例句柄。 </li>
<li>lpParam: (可选)指向欲传给窗口的结构体数据类型参数的指针。如在MDI中在产生窗口时传递 CLIENTCREATESTRUCT 结构的参数。一般情况下,该值总为零,这表示没有参数传递给窗口。可以通过GetWindowLong
函数检索该值。</li>
</ul>
<p> </p>
<p> mov hwnd,eax<br>
invoke ShowWindow, hwnd,CmdShow<br>
invoke UpdateWindow, hwnd<br>
<br>
调用CreateWindowEx成功后,窗口句柄在eax中。我们必须保存该值以备后用。我们刚刚产生的窗口不会自动显示,所以必须调用 ShowWindow
来按照我们希望的方式来显示该窗口。接下来调用 UpdateWindow 来更新客户区。 </p>
<p>.WHILE TRUE<br>
invoke GetMessage, ADDR msg,NULL,0,0<br>
.BREAK .IF (!eax)<br>
invoke TranslateMessage, ADDR msg <br>
invoke DispatchMessage, ADDR msg<br>
.ENDW </p>
<p>这时候我们的窗口已显示在屏幕上了。但是它还不能从外界接收消息。所以我们必须给它提供相关的消息。我们是通过一个消息循环来完成该项工作的。每一个模块仅有一个消息循环,我们不断地调用
GetMessage 从 Windows 中获得消息。GetMessage 传递一个 MSG 结构体给 Windows ,然后 Windows 在该函数中填充有关的消息,一直到
Windows 找到并填充好消息后 GetMessage 才会返回。在这段时间内系统控制权可能会转移给其他的应用程序。这样就构成了Win16 下的多任务结构。如果
GetMessage 接收到 WM_QUIT 消息后就会返回 FALSE,使循环结束并退出应用程序。TranslateMessage 函数是一个是实用函数,它从键盘接受原始按键消息,然后解释成
WM_CHAR,在把 WM_CHAR 放入消息队列,由于经过解释后的消息中含有按键的 ASCII 码,这比原始的扫描码好理解得多。如果您的应用程序不处理按键消息的话,可以不调用该函数。DispatchMessage
会把消息发送给负责该窗口过程的函数。</p>
<p> mov eax,msg.wParam<br>
ret<br>
WinMain endp</p>
<p> 如果消息循环结束了,退出码存放在 MSG 中的 wParam中,您可以通过把它放到 eax 寄存器中传给 Windows目前 Windows 没有利用到这个结束码,但我们最好还是遵从
Windows 规范已防意外。</p>
<p> WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM</p>
<p> 是我们的窗口处理函数。您可以随便给该函数命名。其中第一个参数 hWnd 是接收消息的窗口的句柄。uMsg 是接收的消息。注意 uMsg 不是一个 MSG
结构,其实上只是一个 DWORD 类型数。Windows 定义了成百上千个消息,大多数您的应用程序不会处理到。当有该窗口的消息发生时,Windows 会发送一个相关消息给该窗口。其窗口过程处理函数会智能的处理这些消息。wParam
和 lParam 只是附加参数,以方便传递更多的和该消息有关的数据。</p>
<p> .IF uMsg==WM_DESTROY<br>
invoke PostQuitMessage,NULL<br>
.ELSE <br>
invoke DefWindowProc,hWnd,uMsg,wParam,lParam<br>
ret<br>
.ENDIF<br>
xor eax,eax <br>
ret<br>
WndProc endp</p>
<p> 上面可以说是关键部分。这也是我们写 Windows 程序时需要改写的主要部分。此处您的程序检查 Windows 传递过来的消息,如果是我们感兴趣的消息则加以处理,处理完后,在
eax 寄存器中传递 0,否则必须调用 DefWindowProc,把该窗口过程接收到的参数传递给缺省的窗口处理函数。所有消息中您必须处理的是 WM_DESTROY,当您的应用程序结束时
Windows 把这个消息传递进来,当您的应用程序解说到该消息时它已经在屏幕上消失了,这仅是通知您的应用程序窗口已销毁,您必须自己准备返回 Windows
。在此消息中您可以做一些清理工作,但无法阻止退出应用程序。如果您要那样做的话,可以处理 WM_CLOSE 消息。在处理完清理工作后,您必须调用 PostQuitMessage,该函数会把
WM_QUIT 消息传回您的应用程序,而该消息会使得 GetMessage 返回,并在 eax 寄存器中放入 0,然后会结束消息循环并退回 WINDOWS。您可以在您的程序中调用
DestroyWindow 函数,它会发送一个 WM_DESTROY 消息给您自己的应用程序,从而迫使它退出。</p>
<hr size="1">
<div align="center">
<script language="JavaScript1.1" src=http://ad.t2t2.com/textclick.asp?user=bigluo&style=4&bkcolor=no></script>
<br>
</div>
<!-- 10:1 文本广告交换 -->
<div align="center">
<script language="JavaScript1.1" src=http://coolsite21.com:90/c21.dll?Type=PT&id=1047&col=6&ReferID=1047&v=0></script>
<!-- 10:1 文本广告交换 --> </div>
<hr size="1">
<br>
<div align="center"> 翻译:Lxx,校对:LuoYunBin's Win32 ASM Page,<a href="http://asm.yeah.net">http://asm.yeah.net</a></div>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -