太子爷小说网 > 杂集电子书 > windows环境下32位汇编语言程序设计 >

第16节

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

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

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




               nst

szCaption      db     'SendMessage';0

szStart        db     'Press OK to start SendMessage; param: %08x!';0

szReturn       db     'SendMessage returned!';0

szDestClass    db     'MyClass';0

szText         db     'Text send to other windows';0

szNotFound     db     'Receive Message Window not found!';0

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

               de

start:

               invoke FindWindow;addr szDestClass;NULL

               。if    eax

                      mov     hWnd;eax

                      invoke  wsprintf;addr szBuffer;addr szStart;addr szText

                      invoke  MessageBox;NULL;offset szBuffer;

                              offset szCaption;MB_OK

                      invoke  SendMessage;hWnd;WM_SETTEXT;0;addr szText

                      invoke  MessageBox;NULL;offset szReturn;

                              offset szCaption;MB_OK

               。else

                      invoke  MessageBox;NULL;offset szNotFound;

                      offset  szCaption;MB_OK

               。endif

               invoke ExitProcess;NULL

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

               end    start

在这个程序中首先用FindWindow函数找到接收窗口的窗口句柄,FindWindow函数的使用方法是:

    invoke  FindWindow;lpClassName;lpWindowName

    。if     eax

            mov hWin;eax

    。endif

两个参数都指向字符串,lpClassName指向需要寻找的窗口的窗口类,lpWindowName指向需要寻找窗口的窗口标题,如果目标窗口存在的话,函数的返回值是找到的窗口句柄,否则函数返回0。

用接收窗口的窗口类当做参数寻找窗口,如果没有找到则显示“Receive Message Window not found”,找到的话则把“Text send to other windows”字符串的地址当做WM_SETTEXT消息的参数用SendMessage发送给接收窗口。两个程序的源代码可以在所附带光盘的Chapter04SendMessage目录中找到。

好!现在发送开始,首先执行Receive。exe,窗口出来了,然后执行Send。exe,屏幕上出现一个对话框:Press OK to start SendMessage; param: 00402072,表示在Send程序中字符串的地址是00402072h,现在单击“确定”按钮执行SendMessage函数,单击后对话框消失,但接收程序显示出了一个对话框,内容为:

Receive WM_SETTEXT message

param: 0012ff1c

text: 〃Text send to other windows〃

可见字符串是正确地传了过来,但地址却不是发送程序的00402072h,这是怎么回事呢?答案是Windows做“红娘”做到底,它拷贝了WM_SETTEXT消息lParam指向的字符串,并在接收程序的地址空间中开了一块内存放上这个字符串,然后把新的地址值当做lParam传给接收程序,毕竟在WM_GETTEXT消息中,lParam的数值是多少并不重要,重要的是它指向的字符串是否正确。

最后,单击Receive 程序中的“确定”按钮,Send程序马上会弹出一个消息框并显示:SendMessage returned,这是SendMessage函数告诉我们:我回来了!

其实Windows在处理SendMessage和PostMessage的时候要检查消息的类型,并对不同的消息做不同的处理,当消息的参数是一个指针的时候,Windows要把指针指向的内容复制到缓冲区,以便在两个程序的地址空间中传递。

 在用户自定义的消息中(WM_USER等)不要在消息参数中传递指针,这只会引发非法访问内存,因为Windows不知道用户的意图,它只会把lParam和wParam当两个普通的数值传递,而不会帮用户把指针指向的内容复制到一个缓冲区中。



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


第4章 第一个窗口程序


4。4 实 验(1)

    
在这一节中,将通过不同的实验,进一步介绍窗口的运行。首先构造一个程序,在程序中将收到的消息查表翻译成文本以“WM_XXX”格式显示出来,并且将调用各个API函数的过程也显示出来,这样可以分析窗口的各种行为和消息之间的关系。

4。4。1  MsgWindow程序

为了把需要的内容显示出来,可以选择在客户区显示文本,但这样会引入新的消息,干扰实验,所以,这里选择了一种新的方法,就是先打开Windows附件中自带的Notepad记事本程序,然后在程序中将要显示的内容通过SendMessage发送到记事本中,可以通过查看记事本中的内容来了解MsgWindow的运行情况。

同样,先拷贝一份FirstWindow程序进行修改,共增加3个部分。第一部分是将消息查表转换为字符串,首先在 nst段中增加两个表:16进制的消息编号列表dwMsgTable和字符串列表szStringTable,两表中的项目一一对应,代码如下:

                 nst

dwMsgTable       dd       WM_NULL

                 dd       WM_CREATE

                 dd       WM_DESTROY

                 dd       WM_MOVE

                 …

                 dd       WM_EXITSIZEMOVE

MSG_TABLE_LEN    equ      ( … dwMsgTable)/sizeof dword

 

MSG_STRING_LEN   equ      sizeof szStringTable

szStringTable    db       'WM_NULL                ';0

                          db'WM_CREATE            ';0

                 db       'WM_DESTROY             ';0

                 db       'WM_MOVE                ';0

                 …

                 db       'WM_EXITSIZEMOVE        ';0

szFormat         db       'WndProc: '%04x'%s %08x %08x';0dh;0

MSG_TABLE_LEN定义了表的项数,MSG_STRING_LEN定义了字符串表中每一项的长度。sizeof操作符取的是szStringTable这一行中的数据长度,而非包括下面全部的字符串行。为了简化处理,全部字符串的长度保持相等。由于篇幅所限,这里没有列出全部的消息列表,完整的源代码可以在本书附带光盘的Chapter04MsgWindow01目录中找到。程序在窗口过程的入口处调用_ShowMessage子程序来翻译消息并传给记事本:

_ProcWinMain         proc    uses ebx edi esi;hWnd;uMsg;wParam;lParam

 

                     invoke  _ShowMessage;uMsg;wParam;lParam

                     mov     eax;uMsg

                     。if     eax   WM_XXX

                     …

_ShowMessage子程序用来将消息查表翻译成字符串,源程序如下:

_ShowMessage         proc       _uMsg;_wParam;_lParam

                     local   @szBuffer'128':byte

 

                     pushad

;********************************************************************

; 查找消息的说明字符串

;********************************************************************

                     mov        eax;_uMsg

                     mov        edi;offset dwMsgTable

                     mov        ecx;MSG_TABLE_LEN

                     cld

                     repnz   scasd

                     。if        ZERO?

                            sub     edi;offset dwMsgTable + sizeof dword

                            shr     edi;2

                            mov     eax;edi

                            mov     ecx;MSG_STRING_LEN

                            mul     ecx

                            add     eax;offset szStringTable

;********************************************************************

; 翻译格式并发送到 Notepad 窗口

;********************************************************************

                            invoke  wsprintf;addr @szBuffer;addr szFormat;

                                    _uMsg;eax;_wParam;_lParam

                            invoke _SendtoNotepad;addr @szBuffer

                     。endif

                     popad

                     ret

 

_ShowMessage         endp

在这里要用到repnz scasd指令,scasd指令是把eax中的值从'edi'开始的内存中按双字比较,同时将edi加4,如果相等,则ZR标志置位,否则为NZ,repnz表示如果标志为NZ,则以ecx为重复次数重复搜索,直到相等或ecx为零为止。

将ecx赋值为消息表的项数MSG_TABLE_LEN,将edi赋值为消息表的开始地址offset dwMsgTable,然后开始查找,停止后可以查看标志Zero位,如果是非ZERO,表示查完全部都没有找到,如果是ZERO,则表示找到表项。

当标志为ZERO时,edi指向找到项目的后一项,将edi减去一项的长度(sizeof dword)以及表的基址,再除以表项的长度(sizeof dword等于4,除以4等于右移两位,所以程序中用shr edi;2),就是消息在表中的索引了,接下来算出消息字符串的位置,位置等于:索引×字符串长+字符串表基址,代码如下:

    mov     ecx;MSG_STRING_LEN

    mul     ecx

    add     eax;offset szStringTable

这样,eax中就是字符串的地址了。最后将消息编号、名称和参数用wsprintf函数格式化成可以发送的字符串存放到@szBuffer中,并用_SendtoNotepad子程序将@szBuffer中的内容发送到记事本去。

程序增加的第二部分就是下面这个_SendtoNotepad子程序:

szDestClass      db        'Notepad';0

_SendtoNotepad   proc      _lpsz

                 local     @hWinNotepad

 

                 pushad

                 invoke    FindWindow;addr szDestClass;NULL

                 。if       eax

                           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 0

你可能喜欢的