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

第14章

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

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

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




                           mov      ecx;eax

                           invoke   ChildWindowFromPoint;ecx;20;20

                 。endif

                 。if       eax

                           mov      @hWinNotepad;eax

                           mov      esi;_lpsz

                           @@:

                           lodsb

                           or       al;al

                           jz       @F

                           movzx    eax;al

                           invoke   PostMessage;@hWinNotepad;WM_CHAR;eax;1

                           jmp      @B

                           @@:

                 。endif

                 popad

                 ret

 

_SendtoNotepad   endp



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


第4章 第一个窗口程序


4。4 实 验(2)

    
该子程序中首先用FindWindow函数来查找记事本程序是否已经运行,记事本程序的窗口类名称为“Notepad”,FindWindow可以用窗口类当做第一个参数来查找,如果找到,返回的是记事本程序的主窗口句柄,否则返回0。

要发送的是模拟键盘按键的消息WM_CHAR,这样就好像在记事本中人工键入字符,但直接向记事本主窗口发送WM_CHAR消息是不行的,要向记事本窗口客户区中的编辑子窗口发送消息才行,所以程序中又用从位置获取子窗口句柄的函数ChildWindowFromPoint来获得编辑子窗口的句柄。

锁定了最后的目标即记事本中的编辑子窗口后,程序用PostMessage向它发送消息,根据字符串的长度,用一个循环每次发送一个WM_CHAR消息,WM_CHAR消息的wParam和lParam的含义是:

wParam = chCharCode    // wParam是键值

lParam = lKeyData      // lParam是键数据(重复次数)

程序中用mov eax;al将键值扩展到参数所需的32位,当做wParam参数发送,lParam为1,表示键的重复次数为1次,这样一来,记事本中就源源不断地显示出MsgWindow程序的运行轨迹了。

MsgWindow程序增加的第三部分是在每个函数的前后增加了显示状态的语句,它们只是简单地把一个字符串发送到记事本中去:

;定义一些字符串

szCreateWindow1    db       'Creating Window。。。';0dh;0

szCreateWindow2    db       'CreateWindow end';0dh;0

szShowWindow1      db       'Showing Window。。。';0dh;0

szShowWindow2      db       'ShowWindow end';0dh;0

szUpdateWindow1    db       'Updating Window。。。';0dh;0

szUpdateWindow2    db       'UpdateWindow end';0dh;0

szGetMsg1          db       'Getting Message。。。';0dh;0

szGetMsg2          db       ''%04x'Message gotten';0dh;0

szDispatchMsg1     db       'Dispatching Message。。。';0dh;0

szDispatchMsg2     db       'DispatchMessage end';0dh;0

                                …

                       invoke   _SendtoNotepad;addr szCreateWindow1

                       invoke   CreateWindowEx;…

                       invoke   _SendtoNotepad;addr szCreateWindow2

                       invoke   _SendtoNotepad;addr szShowWindow1

                       invoke   ShowWindow;hWinMain;SW_SHOWNORMAL

                       invoke   _SendtoNotepad;addr szShowWindow2

                       invoke   _SendtoNotepad;addr szUpdateWindow1

                       invoke   UpdateWindow;hWinMain

                       invoke   _SendtoNotepad;addr szUpdateWindow2

                       …

上面代码中的粗体部分就是相对于FirstWindow程序增加的内容,好了,现在DOS控制台上键入nmake将MsgWindow程序编译出来,然后打开记事本,再运行MsgWindow。exe,如果记事本上出现一大堆的东西,就说明实验可以开始了!

4。4。2  开始实验

实验1。 验证收到消息的顺序

打开记事本,然后运行MsgWindow程序,记事本上出现的内容为:

Creating Window。。。

WndProc: '0024'WM_GETMINMAXINFO       00000000 0012fda4

WndProc: '0081'WM_NCCREATE            00000000 0012fd8c

WndProc: '0083'WM_NCCALCSIZE          00000000 0012fdc4

WndProc: '0001'WM_CREATE              00000000 0012fd68

CreateWindow end

Showing Window。。。

WndProc: '0018'WM_SHOWWINDOW          00000001 00000000

WndProc: '0046'WM_WINDOWPOSCHANGING   00000000 0012fec0

WndProc: '0046'WM_WINDOWPOSCHANGING   00000000 0012fec0

WndProc: '001c'WM_ACTIVATEAPP         00000001 00000450

WndProc: '0086'WM_NCACTIVATE          00000001 00000000

WndProc: '000d'WM_GETTEXT             000001fe 0012f52c

WndProc: '0006'WM_ACTIVATE            00000001 00000000

WndProc: '0007'WM_SETFOCUS            00000000 00000000

WndProc: '0085'WM_NCPAINT             00000001 00000000

WndProc: '000d'WM_GETTEXT             000001fe 0012f52c

WndProc: '0014'WM_ERASEBKGND          e3010449 00000000

WndProc: '0047'WM_WINDOWPOSCHANGED    00000000 0012fec0

WndProc: '0005'WM_SIZE                00000000 00450064

WndProc: '0003'WM_MOVE                00000000 004b0038

ShowWindow end

Updating Window。。。

WndProc: '000f'WM_PAINT               00000000 00000000

UpdateWindow end

Getting Message。。。

以WndProc带头的是在窗口过程中收到的消息,显然,和4。2。4节中讲述的是一致的,在调用CreateWindowEx的时候,窗口过程就开始接收消息,里面有重要的WM_CREATE,然后在ShowWindow的时候,Windows向窗口过程发送了很多的消息,而UpdateWindow只给窗口过程发送了一条WM_PAINT消息,接下来就进入了消息循环。

可以看到,GetMessage函数是程序主动上交空闲时间的办法之一,因为显示出Getting Message。…以后,程序就等着那里了,这表示程序的空闲时间并不浪费在消息循环中,而是在GetMessage函数内部由Windows自己分配了。

接下来把鼠标移过MsgWindow窗口,在记事本上看到了什么?用户一个小小的动作就够窗口过程忙的——我们看到了多次重复的下列内容:

WndProc: '0084'WM_NCHITTEST           00000000 00830096

WndProc: '0020'WM_SETCURSOR           001b0304 02000001

'0200'Message gotten

Dispatching Message。。。

WndProc: '0200'WM_MOUSEMOVE           00000000 0038005e

DispatchMessage end

Getting Message。。。

首先,Windows在GetMessage没有返回的时候就调用了两次窗口过程,分别是处理WM_NCHITTEST和WM_SETCURSOR,它们并不经过消息循环;然后,GetMessage取到'0200'消息并返回,0200是WM_MOUSEMOVE消息的编号;接下来,DispatchMessage函数开始工作,在这个函数的内部,消息被Windows发送给窗口过程处理,最后DispatchMessage返回,然后开始新的GetMessage。

最后在MsgWindow上单击“关闭”按钮,看发生了什么:

'00a1'Message gotten

Dispatching Message。。。

WndProc: '00a1'WM_NCLBUTTONDOWN          00000014 003d0097

WndProc: '0215'WM_CAPTURECHANGED         00000000 00000000

WndProc: '0112'WM_SYSMAND             0000f060 003d0097

WndProc: '0010'WM_CLOSE                  00000000 00000000

WndProc: '0046'WM_WINDOWPOSCHANGING      00000000 0012fad8

WndProc: '0047'WM_WINDOWPOSCHANGED       00000000 0012fad8

WndProc: '0086'WM_NCACTIVATE             00000000 00000000

WndProc: '0006'WM_ACTIVATE               00000000 00000000

WndProc: '001c'WM_ACTIVATEAPP            00000000 00000450

WndProc: '0008'WM_KILLFOCUS              00000000 00000000

WndProc: '0002'WM_DESTROY                00000000 00000000

WndProc: '0082'WM_NCDESTROY              00000000 00000000

DispatchMessage end

Getting Message。。。

'0012'Message gotten

GetMessage收到的是按下鼠标的WM_NCLBUTTONDOWN的消息,由DispatchMessage转给窗口过程处理后,窗口过程将它转手给了DefWindowProc,DefWindowProc根据鼠标的位置得出结论:用户按的是“关闭”按钮,放开鼠标后,它就给窗口过程发送WM_CLOSE消息,当窗口过程调用DestroyWindow后,窗口被摧毁,窗口过程最后收到的是WM_DESTROY消息和WM_NCDESTROY消息,而消息循环中GetMessage最后收到的是0012号WM_QUIT消息,消息循环结束。



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


第4章 第一个窗口程序


4。4 实 验(3)

    
实验2。 全部消息都经过消息循环吗

在做这个实验之前,读者已经知道并不是所有的消息都是经过消息循环的,它们中的有些是Windows直接发送到窗口过程的,上一个实验中就已经可以看到GetMessage返回的次数明显地比调用窗口过程的次数少,这意味着窗口过程有很多次是由Windows直接调用的。

这次,我们用极端的方式来验证,先把消息循环中的DispatchMessage去掉,这样GetMessage得到的消息将不会再被送到窗口过程了,窗口过程收到的就是由Windows直接调用的了。改变后的源代码见所附光盘中的Chapter04MsgWindow02目录。

编译后,同样先打开记事本,再执行MsgWindow,然后将鼠标移过MsgWindow窗口,并尝试着单击“关闭”按钮和双击等各种动作;结果是窗口过程还是在被调用:

WndProc: '0084'WM_NCHITTEST           00000000 007e0088

WndProc: '0020'WM_SETCURSOR           0026030c 02000001

WndProc: '0084'WM_NCHITTEST           00000000 006c0070

WndProc: '0020'WM_SETCURSOR           0026030c 02000001



由于没有了DispatchMessage,大部分消息被忽略了,窗口就停在了屏幕上,不能进行移动、缩放或关闭等操作,但还是有一部分消息直接由Windows发送给窗口过程,它们是鼠标位置测试的WM_NCHITTEST消息和要求设置光标的WM_SETCURSOR消息,所以在鼠标移动到边框的时候,鼠标光标还是会变成双箭头的样子。

另外,尝试着单击别的窗口来切换焦点,然后再单击标题栏来重新激活窗口,可以发现WM_MOUSEACTIVATE,WM_ACTIVATE和WM_KILLFOCUS等消息也是不经过消息循环的。接下来,把一个窗口移动到MsgWindow窗口前覆盖它的位置,再移开,可以发现WM_SYNCPAINT和WM_ERASEBKGND等消息也是由Windows直接发给窗口过程的。

最后,关闭窗口,当然这个窗口只能用Ctrl+Alt+Del键在任务管理器中关闭了!

实验3。 TranslateMessage有什么用

首先执行实验1的MsgWindow,在窗口上敲几个键,每次敲一个键,得到的消息是:WM_KEYDOWN,WM_CHAR和WM_KEYUP。如果按下键盘不放,则首先得到一个WM_KEYDOWN,接下来就是重复的WM_CHAR和WM_KEYUP消息,直到放开键盘为止,最后才会看到一个WM_KEYUP。显示如下:

WndProc: '0100'WM_KEYDOWN               00000041 001e0001

WndProc: '0102'WM_CHAR                  00000061 001e0001

WndProc: '0101'WM_KEYUP                 00000041 c01e0001

在WM_KEYDOWN和WM_KEYUP消息中,wParam中是按键的扫描码,上面的数据是按下了键“A”得到的,00000041h是“A”的扫描码,到了WM_CHAR消息中,wParam中就是已经转换过的ASCII码61了,代表输入的是小写的字母“a”。

好!现在从程序中去掉TranslateMessage语句(修改以后的源代码放在Chapter04MsgWindow03目录中),然后看这个程序的运行结果,同样,按几次键以及按下键盘不放,我们发现:这中间的区别就是少了WM_CHAR,所以只有在处理键盘输入要用到转换后的ASCII码的时候,TranslateMessage函数才是有用的,在别的时候完全可以省略这个语句。这个函数的功能就是看到WM_KEYDOWN的时候把消息检查一下,然后根据键值将一条新的WM_CHAR或WM_SYSCHAR消息放入消息循环中。

实验4。 DefWindowProc做了什么工作

现在把DefWindowProc语句去掉(源代码详见Chapter04MsgWindow04目录),然后再以同样的方法运行,窗口根本就没有出现!看记事本中出现了什么:

Creating Window。。。

WndProc: '0024'WM_GETMINMAXINFO       00000000 0012fda4

WndProc: '0081'WM_NCCREATE            00000000 0012fd8c

WndProc: '0082'WM_NCDESTROY           00000000 00000000

CreateWindow end

Showing Window。。。

ShowWindow end

Updating Window。。。

UpdateWindow end

Getting Message。。。

原来在建立窗口的时候执行到WM_NCCREATE消息后窗口就摧毁掉了,看WM_NCCREATE的说明:The DefWindowProc function returns TRUE,原来需要返回1来表示执行成功,所以需要处理WM_NCCREATE并返回1,现在在窗口过程中加上下列分支:

。elseif eax   WM_NCCREATE

        mov     eax;1

        ret

接着编译后执行,怎么编译不成功了?不能写exe文件?原来上次的程序还停留在消息循环中没有退出来,让我们在任务管理器中将它终止再编译,成功了!

好!现在继续执行,窗口成功建立了,但似乎陷入了死循环,因为记事本上不停地有消息冒出来,而且只是冒出WM_PAINT消息来,为什么呢?原来WM_PAINT消息是不能不处理的,也不能丢弃,只要Windows认为窗口的客户区需要绘画(或者说是无效的),它就会不停地向窗口发送WM_PAINT消息,一般WM_PAINT消息的处理中用BeginPaint和EndPaint会隐含地让客户区有效,如果不用Be

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

你可能喜欢的