爱爱小说网 > 其他电子书 > windows环境下32位汇编语言程序设计 >

第11章

windows环境下32位汇编语言程序设计-第11章

小说: windows环境下32位汇编语言程序设计 字数: 每页3500字

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!



方都没有定义菜单句柄,则窗口上没有菜单。另外,当建立的窗口是子窗口时(dwStyle中指定了WS_CHILD),这个参数是另一个含义,这时hMenu参数指定的是子窗口的ID号,这样可以节省一个参数的位置,因为反正子窗口不会有菜单。

●   lpParam——这是一个指针,指向一个欲传给窗口的参数,这个参数在WM_CREATE消息中可以被获取,一般情况下用不到这个字段。

●   hInstance——模块句柄,和注册窗口类时一样,指定了窗口所属的程序模块。

●   hWndParent——窗口所属的父窗口,对于普通窗口(相对于子窗口),这里的“父子”关系只是从属关系,主要用来在父窗口销毁时一同将其“子”窗口销毁,并不会把窗口位置限制在父窗口的客户区范围内,但如果要建立的是真正的子窗口(dwStyle中指定了WS_CHILD的时候),这时窗口位置会被限制在父窗口的客户区范围内,同时窗口的坐标(x,y)也是以父窗口的左上角为基准的。

●   x,y——指定窗口左上角位置,单位是像素。默认时可指定为 CW_USEDEFAULT,这样Windows会自动为窗口指定最合适的位置,当建立子窗口时,位置是以父窗口的左上角为基准的,否则,以屏幕左上角为基准。

●   nWidth,nHeight—窗口的宽度和高度,也就是窗口的大小,同样是以像素为单位的。默认时可指定为 CW_USEDEFAULT,这样Windows会自动为窗口指定最合适的大小。

窗口的两个参数dwStyle和dwExStyle决定了窗口的外形和行为,dwStyle是从Win16开始就有的属性,表4。2列出了一些常见的dwStyle定义,它们是一些以WS(Windows Style的缩写)为开头的预定义值。



 
来源:电子工业出版社 作者:罗云彬 上一页         回书目         下一页          
上一页         回书目         下一页          
  


第4章 第一个窗口程序


4。2 分析窗口程序(3)

    
表4。2  窗口风格的预定义值

预定义值
 16进制值
 含    义
 
WS_OVERLAPPED
 00000000h
 普通的重叠式窗口
 
WS_POPUP
 80000000h
 弹出式窗口(没有标题栏)
 
WS_CHILD
 40000000h
 子窗口
 
WS_MINIMIZE
 20000000h
 初始状态是最小化的
 
WS_VISIBLE
 10000000h
 初始状态是可见的
 
WS_DISABLED
 08000000h
 初始状态是被禁止的
 
WS_MAXIMIZE
 01000000h
 初始状态是最大化的
 
WS_BORDER
 00800000h
 单线条边框
 
WS_DLGFRAME
 00400000h
 对话框类型的边框
 
WS_VSCROLL
 00200000h
 带垂直滚动条
 
WS_HSCROLL
 00100000h
 带水平滚动条
 
WS_SYSMENU
 00080000h
 带系统菜单(即带标题栏左上角的图标)
 
WS_THICKFRAME
 00040000h
 可以拖动调整大小的边框
 
WS_MINIMIZEBOX
 00020000h
 有最小化按钮
 
WS_MAXIMIZEBOX
 00010000h
 有最大化按钮
 

为了容易理解,Windows也为一些定义取了一些别名,同时,由于窗口的风格往往是几种风格的组合,所以Windows也预定义了一些组合值,如表4。3所示。

表4。3  等效的窗口风格预定义值

预定义值
 等  效  值
 
WS_CHILDWINDOW
 WS_CHILD
 
WS_TILED
 WS_OVERLAPPED
 
WS_ICONIC
 WS_MINIMIZE
 
WS_SIZEBOX
 WS_THICKFRAME
 
WS_OVERLAPPEDWINDOW
 WS_OVERLAPPED or WS_CAPTION or WS_SYSMENU or WS_THICKFRAME or WS_MINIMIZEBOX or WS_MAXIMIZEBOX
 
WS_TILEDWINDOW
 WS_OVERLAPPEDWINDOW
 
WS_POPUPWINDOW
 WS_POPUP or WS_BORDER or WS_SYSMENU
 

dwExStyle是Win32中扩展的,它们是一些以WS_EX_开头的预定义值,主要定义了一些特殊的风格,表4。4给出了一些最常用的特殊风格。

表4。4  窗口扩展风格的预定义值

预定义值
 16进制值
 含    义
 
WS_EX_TOPMOST
 00000008h
 总在顶层的窗口
 
WS_EX_ACCEPTFILES
 00000010h
 允许窗口进行鼠标拖放操作
 
WS_EX_TOOLWINDOW
 00000080h
 工具窗口(很窄的标题栏)
 
WS_EX_WINDOWEDGE
 00000100h
 立体感的边框
 
WS_EX_CLIENTEDGE
 00000200h
 客户区立体边框
 

 

预定义值
 16进制值
 含    义
 
WS_EX_OVERLAPPEDWINDOW
  
 WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGE
 
WS_EX_PALETTEWINDOW
  
 WS_EX_WINDOWEDGE or WS_EX_TOOLWINDOW or WS_EX_TOPMOST
 

用预定义的组合值WS_EX_PALETTEWINDOW可以很方便地构成浮在其他窗口前面的工具栏。

下面看几种不同的窗口外形,如图4。5所示,窗口1是WS_OVERLAPPED类型的窗口,只有一个边框,没有控制按钮和图标;窗口2同时指定WS_MAXIMIZEBOX,WS_MINIMIZEBOX和WS_SYSMENU,在窗口1的基础上多了控制按钮和图标;窗口3是WS_POPUPWINDOW风格的,这是一个没有标题和控制按钮的弹出式窗口,常见的软件装入时的版权窗口就是这种风格;前面3个窗口都不能通过拖动边框改变大小,而窗口4指定了WS_THICKFRAME风格,可以改变大小,它的边框显得厚了一点;窗口5的风格是WS_OVERLAPPEDWINDOW,是最常见的属性组合;窗口6在窗口5的基础上指定了WS_EX_CLIENTEDGE,它的客户区显得有立体感;窗口7是个工具栏,指定的是WS_EX_TOOLWINDOW风格,可以看到它的标题栏要小得多;窗口8指定了WS_HSCROLL和WS_VSCROLL风格,窗口中多了垂直和水平滚动条。


图4。5  不同风格的窗口

FirstWindow程序中建立窗口的相关代码是这样的:

            invoke  CreateWindowEx;WS_EX_CLIENTEDGE;

                    offset szClassName;offset szCaptionMain;

                    WS_OVERLAPPEDWINDOW;

                    100;100;600;400;

                    NULL;NULL;hInstance;NULL

            mov     hWinMain;eax

            invoke  ShowWindow;hWinMain;SW_SHOWNORMAL

            invoke  UpdateWindow;hWinMain

            …

建立窗口以后,eax中传回来的是窗口句柄,要把它先保存起来,这时候,窗口虽已建立,但还没有在屏幕上显示出来,要用ShowWindow把它显示出来,ShowWindow也可以用在别的地方,主要用来控制窗口的显示状态(显示或隐藏),大小控制(最大化、最小化或原始大小)和是否激活(当前窗口还是背后的窗口),它用窗口句柄做第一个参数,第二个参数则是显示的方式。表4。5给出了显示方式预定义值。

表4。5  ShowWindow函数显示方式的定义

预定义值
 等  效  值
 
SW_HIDE
 隐藏窗口,大小不变,激活状态不变
 
SW_MAXIMIZE
 最大化窗口,显示状态不变,激活状态不变
 
SW_MINIMIZE
 最小化窗口,显示状态不变,激活状态不变
 
SW_RESTORE
 从最大化或最小化恢复正常大小,显示状态不变,激活状态不变
 
SW_SHOW
 显示并激活窗口,大小状态不变
 
SW_SHOWMAXIMIZED
 显示并激活窗口,以最大化显示
 
SW_SHOWMINIMIZED
 显示并激活窗口,以最小化显示
 
SW_SHOWMINNOACTIVE
 显示窗口并最小化,激活状态不变
 
SW_SHOWNA
 显示窗口,大小状态不变,激活状态不变
 
SW_SHOWNOACTIVATE
 显示并从最大化或最小化恢复正常大小,激活状态不变
 
SW_SHOWNORMAL
 显示并激活窗口,恢复正常大小(初始化时用这个参数)
 

窗口显示以后,用UpdateWindow绘制客户区,它实际上就是向窗口发送了一条WM_PAINT消息。到此为止,一个顶层窗口就正常建立并显示了。

CreateWindowEx也可以用来建立子窗口,Windows中有很多预定义的子窗口类,如按钮和文本框的类名分别是“Button”和“Edit”。要建立一个按钮,只要把lpClassName指向 “Button”字符串就可以了。下面举例说明建立一个按钮的方法,代码如下:

                                  。data

szButton         db           'button';0

szButtonText     db           '&OK';0

                                  …

                 invoke       CreateWindowEx;NULL;

                              offset szButton;offset szButtonText;

                              WS_CHILD or WS_VISIBLE;

                              10;10;65;22;

                                 hWnd;1;hInstance;NULL

在FirstWindow的源程序中加入按钮类的定义字符串szButton和按钮文字字符串szButtonText,然后在窗口过程的WM_CREATE消息中加入建立按钮的代码,执行一下,窗口中就出现了一个按钮,如图4。6所示。建立按钮的时候,lpWindowName参数就是按钮上的文字,风格则一定要指定WS_CHILD,建立的按钮才会在我们的主窗口上,WS_VISIBLE也要同时指定,否则按钮不会显示出来,hMenu参数在这里用做表示子窗口ID,将它设置为1,在建立多个子窗口的时候,ID应该有所区别。源程序可以在所附带光盘的Chapter04FirstWindow…1目录中找到。


图4。6  用CreateWindowEx建立的按钮



 
来源:电子工业出版社 作者:罗云彬 上一页         回书目         下一页          
v上一页         回书目         下一页          
  


第4章 第一个窗口程序


4。2 分析窗口程序(4) 

    
4。2。3  消息循环

1。 消息循环的一般形式

程序中的以下代码就是通常的消息循环:

    。while  TRUE

        invoke  GetMessage;addr @stMsg;NULL;0;0

            。break  。if eax  0

            invoke  TranslateMessage;addr @stMsg

            invoke  DispatchMessage;addr @stMsg

    。endw

消息循环中的几个函数要用到一个MSG结构,用来做消息传递:

MSG STRUCT

  Hwnd      DWORD      ?

  Message   DWORD      ?

  WParam    DWORD      ?

  LParam    DWORD      ?

  Time      DWORD      ?

  Pt        POINT      

MSG ENDS

它的各个字段的含义是:

●   hwnd——消息要发向的窗口句柄。

●   message——消息标识符,在头文件中以WM_开头的预定义值(意思为Windows Message)。

●   wParam——消息的参数之一。

●   lParam——消息的参数之二。

●   time——消息放入消息队列的时间。

●   pt——这是一个POINT数据结构,表示消息放入消息队列时的鼠标坐标。

这个结构定义了消息的所有属性,GetMessage函数就是从消息队列中取出这样一条消息来的:

        invoke  GetMessage;lpMsg;hWnd;wMsgFilterMin;wMsgFilterMax

函数的lpMsg指向一个MSG结构,函数会在这里返回取到的消息,hWnd参数指定要获取哪个窗口的消息,例子中指定为NULL,表示获取的是所有本程序所属窗口的消息,wMsgFilterMin和wMsgFilterMax为0表示获取所有编号的消息。

GetMessage函数从消息队列里取得消息,填写好MSG结构并返回,如果获取的消息是WM_QUIT消息,那么eax中的返回值是0,否则eax返回非零值,所以用 。break 。if eax  0来检查返回值,如果消息队列中有WM_QUIT则退出消息循环。

TranslateMessage将MSG结构传给Windows进行一些键盘消息的转换,当有键盘按下和放开时,Windows产生WM_KEYDOWN和WM_KEYUP或WM_SYSKEYDOWN和WM_SYSKEYUP消息,但这些消息的参数中包含的是按键的扫描码,转换成常用的ASCII码要经过查表,很不方便,TranslateMessage遇到键盘消息则将扫描码转换成ASCII码并在消息队列中插入WM_CHAR或WM_SYSCHAR消息,参数就是转换好的ASCII码,如此一来,要处理键盘消息的话只要处理WM_CHAR消息就好了。遇到别的消息则TranslateMessage不做处理。

最后,由DispatchMessage将消息发送到窗口对应的窗口过程去处理。窗口过程返回后DispatchMessage函数才返回,然后开始新一轮消息循环。

2。 其他形式的消息循环

GetMessage函数是程序空闲的时候主动将控制权交还给Windows的一种方式,Windows是一个抢占式的多任务系统,任务之间每20 ms切换一次,试想一下,如果窗口程序在主窗口中采用死循环等待,消息由Windows直接发送到窗口过程,那么程序会是下列这种样子:

    invoke  CreateWindow,…

    invoke  ShowWindow,…

    invoke  UpdateWindow,…

    。while  dwQuitFlag  0    ;要退出时在窗口过程中设置dwQuitFlag

    。endw

    invoke  ExitProcess,…

但这样一来,即使程序在空闲状态,轮到自己的20 ms时间片的时候,CPU时间就会全部消耗在 。while循环中,使用GetMessage的时候,轮到应用程序时间片的时候,如果消息队列里还没有消息,那么程序还是停留在GetMessage内部,这时就可以由Windows当家做主没收这20 ms的时间片,如此保证了CPU资源的合理应用。

如果应用程序想把所有时间充分用回来,消息队列里没有消息的时候不让GetMessage在Windows内部等待,拱手交出属于自己的CPU时间,那么消息循环可以是下列这种样子:

    。while  TRUE

        invoke  PeekMessage;addr @stMsg;NULL;0;0;PM_REMOVE

        。if     eax

。break 。if @stMsg。message  WM_QUIT

invoke TranslateMessage;addr @stMsg

invoke DispatchMessage;addr @stMsg

        。else

                

        。endif

    。endw

PeekMessage是一个类似于GetMessage的函数,区别在于当消息队列里有消息的时候,PeekMessage取回消息,并在eax中返回非零值,没有消息的时候它会直接返回,并在eax中返回零。所以在返回非零值的时候,程序检查消息是否是WM_QUIT,是则结束消息循环,不是则用标准流程处理消息;返回零的时候,表示是空闲时间,程序就可以做其他工作了,但插入做其他工作的代码执行时间不能过长,以不超过10 ms为好,否则会影响正常的消息处理,使窗口的反应看起来很迟钝。如果必须处理很长时间的工作,那么应该将它分成很多小部分处理,以便有足够的频率来用PeekMessage来检查消息。PeekMessage的前面4个参数和GetMessage是相同的,增加了最后一个参数,PM_REMOVE表示取回消息的同时从消息队列里删除,否则用PM_NOREMOVE。

4。2。4  窗口过程

窗口过程是给Windows回调用的,它必须遵循规定的格式。对窗口过程的子程序名并没有规定,对Windows来说,窗口过程的地址才是惟一

返回目录 上一页 下一页 回到顶部 2 2

你可能喜欢的