luqingfei@C++

为中华之崛起而崛起!
兼听则明,偏听则暗。

Win32汇编--窗口程序实验--行为与消息之间的关系

 

窗口程序实验--行为与消息之间的关系

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

 

一、MsgWindow程序

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

 

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

                            .const

       dwMsgTable                 dd           WM_NULL

                                          dd           WM_CREATE

                                          dd           WM_DESTROY

                                          dd           WM_MOVE

 

                                          dd           WM_EXITSIZEMOVE

       MSG_TABLE_LEN       equ         ($ - dwMsgTable) / sizeof dword

       ;注释:equ伪指令,是宏汇编特有的,是一种宏定义,而非高级语言中常量的概念。

       ;不会为符号分配空间。

       ;在汇编器编译的时候,直接将标识符MSG_TABLE_LEN替换为后面的值。

 

       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这一行中的数据长度,而非包括下面全部的字符串行。为了简化处理,全部字符串的长度保持相等。由于篇幅所限,这里没有列出全部的消息列表。程序在窗口过程的入口处调用_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        @suBuffer[128]:byte

 

                                   pushad

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

       ; 查找消息的说明字符串

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

                                   mov        eax, _uMsg

                                   mov        edi, offset dwMsgTable

                                   mov        ecx, MSG_TABLE_LEN

                                   cld

                                   repnz      scads

                                   .if           ZERO?

                                                 sub         edi, offset dwMsgTable + sizeof dword

                                                 shr          edi, 2

                                                 mov        eax, edi

                                                 ;eax寄存器中存放的是当前消息的索引号

                                                 mov        ecx, MSG_STRING_LEN

                                                 mul         ecx

                                                 add         eax, offset szStringTable

                                                 ; 索引号乘以项长度再加上消息字符串基址,就得到

                                                 ;当前消息字符串的地址

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

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

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

                                                 invoke     wsprintf, addr @szBuffer, addr szFormat, \

                                                               _uMsg, eax, _wParam, _lParam

                                                 invoke     _SendNotepad, addr @szBuffer

                                   .endif

                                   popad

                                   ret

       _ShowMessage      endp

在这里要用到repnz scasd指令,scasd指令是把eax中的值从[edi]开始的内存中按双字比较,同时将edi4,如果相等,则ZR标志置位,否则为NZrepnz表示如果标志为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

 

                                   pushed

                                   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

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

 

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

 

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

       wParam = chCharCode                //wParam的键值

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

 

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

 

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

       ;定义一些字符串

       szCreateWindow1          db           ‘Creating Window…’,0dh,0

       szCreateWindow2          db           ‘CreateWindow end’,0dh,0

       szShowWindow1          db           ‘Showing Window…’,0dh,0

       szShowWindow2          db           ‘ShowWindown 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’,odh,0

       szDispatchMsg1            db           ‘Dispatching Message…’,0dh,0

       szDispatchMsg2            db           ‘DispatchMessge 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

 

实验一:验证收到消息的顺序

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

Creating Window...

WndProc: [0024] WM_GETMINMAXINFO          00000000 0012f900

WndProc: [0081] WM_NCCREATE               00000000 0012f8e8

WndProc: [0083] WM_NCCALCSIZE             00000000 0012f920

WndProc: [0001] WM_CREATE                 00000000 0012f8c4

CreateWindow end

Showing Window...

WndProc: [0018] WM_SHOWWINDOW             00000001 00000000

WndProc: [0046] WM_WINDOWPOSCHANGING      00000000 0012febc

WndProc: [0046] WM_WINDOWPOSCHANGING      00000000 0012febc

WndProc: [001c] WM_ACTIVATEAPP            00000001 000006d4

WndProc: [0086] WM_NCACTIVATE             00000001 00000000

WndProc: [000d] WM_GETTEXT                000001fe 0012f484

WndProc: [0006] WM_ACTIVATE               00000001 00000000

WndProc: [0007] WM_SETFOCUS               00000000 00000000

WndProc: [0085] WM_NCPAINT                00000001 00000000

WndProc: [000d] WM_GETTEXT                000001fe 0012f484

WndProc: [0014] WM_ERASEBKGND             01010058 00000000

WndProc: [0047] WM_WINDOWPOSCHANGED       00000000 0012febc

WndProc: [0005] WM_SIZE                   00000000 0171024c

WndProc: [0003] WM_MOVE                   00000000 007d006a

ShowWindow end

Updating Window...

WndProc: [000f] WM_PAINT                  00000000 00000000

UpdateWindow end

Getting Message...

 

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

 

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

 

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

WndProc: [0084] WM_NCHITTEST              00000000 0125024a

WndProc: [0020] WM_SETCURSOR              001305e2 02000001

[0200]Message gotten

Dispatching Message...

WndProc: [0200] WM_MOUSEMOVE              00000000 00a801e0

DispatchMessage end

Getting Message...

 

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

 

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

[00a1]Message gotten

Dispatching Message...

WndProc: [00a1] WM_NCLBUTTONDOWN          00000014 007302b5

WndProc: [0215] WM_CAPTURECHANGED         00000000 00000000

WndProc: [0112] WM_SYSCOMMAND             0000f060 007302b5

WndProc: [0010] WM_CLOSE                  00000000 00000000

WndProc: [0046] WM_WINDOWPOSCHANGING      00000000 0012f984

WndProc: [0047] WM_WINDOWPOSCHANGED       00000000 0012f984

WndProc: [0086] WM_NCACTIVATE             00000000 00000000

WndProc: [0006] WM_ACTIVATE               00000000 00000000

WndProc: [001c] WM_ACTIVATEAPP            00000000 000006d4

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转给窗口过程处理后,窗口过程将它转手给了DefWindowProcDefWindowProc根据鼠标的位置得出结论:用户按的是“关闭”按钮,放到鼠标后,它就给窗口过程发送WM_CLOSE消息,当窗口过程调用DestroyWindow后,窗口被摧毁,窗口过程最后收到的是WM_DESTROY消息和WM_NCDESTROY消息,而消息循球中GetMessage最后收到的是0012WM_QUIT消息,消息循环结束。

 

 

实验二:全部消息都经过消息循环吗?

上一实验中可以看到GetMessage返回的次数明显地比调用窗口过程的次数次,这意味着窗口过程有很多次是由Windows直接调用的。

 

这次,我们用极端的方式来验证,先把消息循环中的DispatchMessage去掉,这样,GetMessage得到的消息将不会再被送到窗口过程了,窗口过程收到的就是由Windows直接调用的了。

WndProc: [0084] WM_NCHITTEST              00000000 00c20076

WndProc: [0020] WM_SETCURSOR              000c03e6 02000001

 

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

 

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

 

最后,关闭窗口,当然这个窗口只能在任务管理器中以结束进程的方法关闭了!

 

 

实验三:TranslateMessage有什么用

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

WndProc: [0100] WM_KEYDOWN               00000041 001e0001

WndProc: [0102] WM_CHAR                  00000061 001e0001

WndProc: [0101] WM_KEYUP                  00000041 c01e0001

 

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

 

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

 

 

实验四:DefWindowProc做了什么工作

现在把DefWindowProc语句去掉,然后再以同样的方法运行,窗口根本就没有出现!看记事本中出现了什么:

Creating Window...

WndProc: [0024] WM_GETMINMAXINFO          00000000 0012f900

WndProc: [0081] WM_NCCREATE               00000000 0012f8e8

WndProc: [0083] WM_NCCALCSIZE             00000000 0012f920

WndProc: [0001] WM_CREATE                 00000000 0012f8e8

CreateWindow end

Showing Window...

WndProc: [0018] WM_SHOWWINDOW             00000001 00000000

WndProc: [0046] WM_WINDOWPOSCHANGING      00000000 0012febc

WndProc: [0046] WM_WINDOWPOSCHANGING      00000000 0012febc

WndProc: [001c] WM_ACTIVATEAPP            00000001 000006d4

WndProc: [0086] WM_NCACTIVATE             00000001 00000000

WndProc: [0006] WM_ACTIVATE               00000001 00000000

WndProc: [0007] WM_SETFOCUS               00000000 00000000

WndProc: [0085] WM_NCPAINT                00000001 00000000

WndProc: [0014] WM_ERASEBKGND             01010055 00000000

WndProc: [0047] WM_WINDOWPOSCHANGED       00000000 0012febc

WndProc: [0005] WM_SIZE                   00000000 01900258

WndProc: [0003] WM_MOVE                   00000000 00640064

ShowWindow end

Updating Window...

WndProc: [000f] WM_PAINT                  00000000 00000000

UpdateWindow end

Getting Message...

[c0aa]Message gotten

Dispatching Message...

DispatchMessage end

Getting Message...

[000f]Message gotten

Dispatching Message...

WndProc: [000f] WM_PAINT                  00000000 00000000

DispatchMessage end

Getting Message...

[000f]Message gotten

Dispatching Message...

WndProc: [000f] WM_PAINT                  00000000 00000000

DispatchMessage end

Getting Message...

[000f]Message gotten

Dispatching Message...

WndProc: [000f] WM_PAINT                  00000000 00000000

DispatchMessage end

Getting Message...

[000f]Message gotten

Dispatching Message...

WndProc: [000f] WM_PAINT                  00000000 00000000

 

似乎陷入了死循环,因为记事本上不停地有消息冒出来,而且只是冒出WM_PAINT消息来,为什么呢?原来WM_PAINT消息是不能不处理的,也不能丢弃,只要Windows认为窗口的客户区需要绘画(或者说是无效的),它就会不停地向窗口发送WM_PAINT消息,一般WM_PAINT消息的处理中用BeginPaintEndPaint会隐含地让客户区有效,如果不用BeginPaint/EndPaint,程序必须显式地把客户区设置为有效,Windows才不会再发送WM_PAINT消息。这个函数是ValidateRect,现在在分支中再加上处理WM_PAINT的代码:

.elseif eax == WM_PAINT

     invoke ValidateRect, hWnd, NULL

再编译执行,现在记事本出现的信息显示程序停留在了GetMessage处,一切正常。但是,窗口在哪里呢,屏幕上什么都没有,隐身了?把鼠标移动窗口原来应该出现的地方,记事本中熟悉的WM_NCHITTESTWM_SETCURSOR消息出现了,原来窗口还在那里,只不过没有了DefWindowProc的处理,窗口的绘画等所有工作都没有做,窗口的边框与与客户区等所有的东西连画都没有画上去,所以窗口是存在的,但我们看不到它!

是不是再加上WM_NCPAINT消息自己画边框呢,这就不是这个实验的内容了,我们已经知道,DefWindowProc做的工作太多了,缺了它我们要补上的代码可不是一两个分支的问题,而是上百个分支了!

 

实验的程序的完整代码如下:

                .386

                .model flat,stdcall

                option casemap:none

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; Include 文件定义

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

include         windows.inc

include         gdi32.inc

includelib      gdi32.lib

include         user32.inc

includelib      user32.lib

include         kernel32.inc

includelib      kernel32.lib

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; 数据段

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                .data?

hInstance       dd      ?

hWinMain        dd      ?

 

                .const

szClassName     db      'MyClass',0

szCaptionMain   db      'Message Tester',0

 

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

; 消息ID列表

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

dwMsgTable      dd WM_NULL

                dd    WM_CREATE

                dd    WM_DESTROY

                dd    WM_MOVE

                dd    WM_SIZE

                dd    WM_ACTIVATE

                dd    WM_SETFOCUS

                dd    WM_KILLFOCUS

                dd    WM_ENABLE

                dd    WM_SETREDRAW

                dd    WM_SETTEXT

                dd    WM_GETTEXT

                dd    WM_GETTEXTLENGTH

                dd    WM_PAINT

                dd    WM_CLOSE

                dd    WM_QUERYENDSESSION

                dd    WM_QUIT

                dd    WM_QUERYOPEN

                dd    WM_ERASEBKGND

                dd    WM_SYSCOLORCHANGE

                dd    WM_ENDSESSION

                dd    WM_SHOWWINDOW

                dd    WM_WININICHANGE

                dd    WM_DEVMODECHANGE

                dd    WM_ACTIVATEAPP

                dd    WM_FONTCHANGE

                dd    WM_TIMECHANGE

                dd    WM_CANCELMODE

                dd    WM_SETCURSOR

                dd    WM_MOUSEACTIVATE

                dd    WM_CHILDACTIVATE

                dd    WM_QUEUESYNC

                dd    WM_GETMINMAXINFO

                dd    WM_PAINTICON

                dd    WM_ICONERASEBKGND

                dd    WM_NEXTDLGCTL

                dd    WM_SPOOLERSTATUS

                dd    WM_DRAWITEM

                dd    WM_MEASUREITEM

                dd    WM_DELETEITEM

                dd    WM_VKEYTOITEM

                dd    WM_CHARTOITEM

                dd    WM_SETFONT

                dd    WM_GETFONT

                dd    WM_SETHOTKEY

                dd    WM_GETHOTKEY

                dd    WM_QUERYDRAGICON

                dd    WM_COMPAREITEM

                dd    WM_GETOBJECT

                dd    WM_COMPACTING

                dd    WM_OTHERWINDOWCREATED

                dd    WM_OTHERWINDOWDESTROYED

                dd    WM_COMMNOTIFY

                dd    WM_WINDOWPOSCHANGING

                dd    WM_WINDOWPOSCHANGED

                dd    WM_POWER

                dd    WM_COPYDATA

                dd    WM_CANCELJOURNAL

                dd    WM_NOTIFY

                dd    WM_INPUTLANGCHANGEREQUEST

                dd    WM_INPUTLANGCHANGE

                dd    WM_TCARD

                dd    WM_HELP

                dd    WM_USERCHANGED

                dd    WM_NOTIFYFORMAT

                dd    WM_CONTEXTMENU

                dd    WM_STYLECHANGING

                dd    WM_STYLECHANGED

                dd    WM_DISPLAYCHANGE

                dd    WM_GETICON

                dd    WM_SETICON

                dd    WM_NCCREATE

                dd    WM_NCDESTROY

                dd    WM_NCCALCSIZE

                dd    WM_NCHITTEST

                dd    WM_NCPAINT

                dd    WM_NCACTIVATE

                dd    WM_GETDLGCODE

                dd    WM_SYNCPAINT

                dd    WM_NCMOUSEMOVE

                dd    WM_NCLBUTTONDOWN

                dd    WM_NCLBUTTONUP

                dd    WM_NCLBUTTONDBLCLK

                dd    WM_NCRBUTTONDOWN

                dd    WM_NCRBUTTONUP

                dd    WM_NCRBUTTONDBLCLK

                dd    WM_NCMBUTTONDOWN

                dd    WM_NCMBUTTONUP

                dd    WM_NCMBUTTONDBLCLK

                dd    WM_KEYDOWN

                dd    WM_KEYUP

                dd    WM_CHAR

                dd    WM_DEADCHAR

                dd    WM_SYSKEYDOWN

                dd    WM_SYSKEYUP

                dd    WM_SYSCHAR

                dd    WM_SYSDEADCHAR

                dd    WM_KEYLAST

                dd    WM_INITDIALOG

                dd    WM_COMMAND

                dd    WM_SYSCOMMAND

                dd    WM_TIMER

                dd    WM_HSCROLL

                dd    WM_VSCROLL

                dd    WM_INITMENU

                dd    WM_INITMENUPOPUP

                dd    WM_MENUSELECT

                dd    WM_MENUCHAR

                dd    WM_ENTERIDLE

                dd    WM_CTLCOLORMSGBOX

                dd    WM_CTLCOLOREDIT

                dd    WM_CTLCOLORLISTBOX

                dd    WM_CTLCOLORBTN

                dd    WM_CTLCOLORDLG

                dd    WM_CTLCOLORSCROLLBAR

                dd    WM_CTLCOLORSTATIC

                dd    WM_MOUSEMOVE

                dd    WM_LBUTTONDOWN

                dd    WM_LBUTTONUP

                dd    WM_LBUTTONDBLCLK

                dd    WM_RBUTTONDOWN

                dd    WM_RBUTTONUP

                dd    WM_RBUTTONDBLCLK

                dd    WM_MBUTTONDOWN

                dd    WM_MBUTTONUP

                dd    WM_MBUTTONDBLCLK

                dd    WM_MOUSELAST

                dd    WM_PARENTNOTIFY

                dd    WM_ENTERMENULOOP

                dd    WM_EXITMENULOOP

                dd    WM_MDICREATE

                dd    WM_MDIDESTROY

                dd    WM_MDIACTIVATE

                dd    WM_MDIRESTORE

                dd    WM_MDINEXT

                dd    WM_MDIMAXIMIZE

                dd    WM_MDITILE

                dd    WM_MDICASCADE

                dd    WM_MDIICONARRANGE

                dd    WM_MDIGETACTIVE

                dd    WM_MDISETMENU

                dd    WM_DROPFILES

                dd    WM_MDIREFRESHMENU

                dd    WM_CUT

                dd    WM_COPY

                dd    WM_PASTE

                dd    WM_CLEAR

                dd    WM_UNDO

                dd    WM_RENDERFORMAT

                dd    WM_RENDERALLFORMATS

                dd    WM_DESTROYCLIPBOARD

                dd    WM_DRAWCLIPBOARD

                dd    WM_PAINTCLIPBOARD

                dd    WM_VSCROLLCLIPBOARD

                dd    WM_SIZECLIPBOARD

                dd    WM_ASKCBFORMATNAME

                dd    WM_CHANGECBCHAIN

                dd    WM_HSCROLLCLIPBOARD

                dd    WM_QUERYNEWPALETTE

                dd    WM_PALETTEISCHANGING

                dd    WM_PALETTECHANGED

                dd    WM_HOTKEY

                dd    WM_PRINT

                dd    WM_PRINTCLIENT

                dd    WM_PENWINFIRST

                dd    WM_PENWINLAST

                dd    WM_MENURBUTTONUP

                dd    WM_MENUDRAG

                dd    WM_MENUGETOBJECT

                dd    WM_UNINITMENUPOPUP

                dd    WM_MENUCOMMAND

                dd    WM_NEXTMENU

                dd    WM_SIZING

                dd    WM_CAPTURECHANGED

                dd    WM_MOVING

                dd    WM_POWERBROADCAST

                dd    WM_DEVICECHANGE

                dd    WM_ENTERSIZEMOVE

                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_SIZE                  ',0

                db    'WM_ACTIVATE              ',0

                db    'WM_SETFOCUS              ',0

                db    'WM_KILLFOCUS             ',0

                db    'WM_ENABLE                ',0

                db    'WM_SETREDRAW             ',0

                db    'WM_SETTEXT               ',0

                db    'WM_GETTEXT               ',0

                db    'WM_GETTEXTLENGTH         ',0

                db    'WM_PAINT                 ',0

                db    'WM_CLOSE                 ',0

                db    'WM_QUERYENDSESSION       ',0

                db    'WM_QUIT                  ',0

                db    'WM_QUERYOPEN             ',0

                db    'WM_ERASEBKGND            ',0

                db    'WM_SYSCOLORCHANGE        ',0

                db    'WM_ENDSESSION            ',0

                db    'WM_SHOWWINDOW            ',0

                db    'WM_WININICHANGE          ',0

                db    'WM_DEVMODECHANGE         ',0

                db    'WM_ACTIVATEAPP           ',0

                db    'WM_FONTCHANGE            ',0

                db    'WM_TIMECHANGE            ',0

                db    'WM_CANCELMODE            ',0

                db    'WM_SETCURSOR             ',0

                db    'WM_MOUSEACTIVATE         ',0

                db    'WM_CHILDACTIVATE         ',0

                db    'WM_QUEUESYNC             ',0

                db    'WM_GETMINMAXINFO         ',0

                db    'WM_PAINTICON             ',0

               db    'WM_ICONERASEBKGND        ',0

                db    'WM_NEXTDLGCTL            ',0

                db    'WM_SPOOLERSTATUS         ',0

                db    'WM_DRAWITEM              ',0

                db    'WM_MEASUREITEM           ',0

                db    'WM_DELETEITEM            ',0

                db    'WM_VKEYTOITEM            ',0

                db    'WM_CHARTOITEM            ',0

                db    'WM_SETFONT               ',0

                db    'WM_GETFONT               ',0

                db    'WM_SETHOTKEY             ',0

                db    'WM_GETHOTKEY             ',0

                db    'WM_QUERYDRAGICON         ',0

                db    'WM_COMPAREITEM           ',0

                db    'WM_GETOBJECT             ',0

                db    'WM_COMPACTING           ',0

                db    'WM_OTHERWINDOWCREATED    ',0

                db    'WM_OTHERWINDOWDESTROYED ',0

                db    'WM_COMMNOTIFY            ',0

                db    'WM_WINDOWPOSCHANGING     ',0

                db    'WM_WINDOWPOSCHANGED      ',0

                db    'WM_POWER                 ',0

                db    'WM_COPYDATA              ',0

                db    'WM_CANCELJOURNAL         ',0

                db    'WM_NOTIFY                ',0

                db    'WM_INPUTLANGCHANGEREQUEST',0

                db    'WM_INPUTLANGCHANGE       ',0

                db    'WM_TCARD                 ',0

                db    'WM_HELP                  ',0

                db    'WM_USERCHANGED           ',0

                db    'WM_NOTIFYFORMAT          ',0

                db    'WM_CONTEXTMENU           ',0

                db    'WM_STYLECHANGING         ',0

                db    'WM_STYLECHANGED          ',0

                db    'WM_DISPLAYCHANGE         ',0

                db    'WM_GETICON               ',0

                db    'WM_SETICON               ',0

                db    'WM_NCCREATE              ',0

                db    'WM_NCDESTROY             ',0

                db    'WM_NCCALCSIZE            ',0

                db    'WM_NCHITTEST             ',0

                db    'WM_NCPAINT               ',0

                db    'WM_NCACTIVATE            ',0

                db    'WM_GETDLGCODE            ',0

                db    'WM_SYNCPAINT             ',0

                db    'WM_NCMOUSEMOVE           ',0

                db    'WM_NCLBUTTONDOWN         ',0

                db    'WM_NCLBUTTONUP           ',0

                db    'WM_NCLBUTTONDBLCLK       ',0

                db    'WM_NCRBUTTONDOWN         ',0

                db    'WM_NCRBUTTONUP           ',0

                db    'WM_NCRBUTTONDBLCLK       ',0

                db    'WM_NCMBUTTONDOWN         ',0

                db    'WM_NCMBUTTONUP           ',0

                db    'WM_NCMBUTTONDBLCLK       ',0

                db    'WM_KEYDOWN               ',0

                db    'WM_KEYUP                 ',0

                db    'WM_CHAR                  ',0

                db    'WM_DEADCHAR              ',0

                db    'WM_SYSKEYDOWN            ',0

                db    'WM_SYSKEYUP              ',0

                db    'WM_SYSCHAR               ',0

                db    'WM_SYSDEADCHAR          ',0

                db    'WM_KEYLAST               ',0

                db    'WM_INITDIALOG            ',0

                db    'WM_COMMAND               ',0

                db    'WM_SYSCOMMAND            ',0

                db    'WM_TIMER                 ',0

                db    'WM_HSCROLL               ',0

                db    'WM_VSCROLL               ',0

                db    'WM_INITMENU              ',0

                db    'WM_INITMENUPOPUP         ',0

                db    'WM_MENUSELECT            ',0

                db    'WM_MENUCHAR              ',0

                db    'WM_ENTERIDLE             ',0

                db    'WM_CTLCOLORMSGBOX        ',0

                db    'WM_CTLCOLOREDIT          ',0

                db    'WM_CTLCOLORLISTBOX       ',0

                db    'WM_CTLCOLORBTN           ',0

                db    'WM_CTLCOLORDLG           ',0

                db    'WM_CTLCOLORSCROLLBAR     ',0

                db    'WM_CTLCOLORSTATIC        ',0

                db    'WM_MOUSEMOVE             ',0

                db    'WM_LBUTTONDOWN           ',0

                db    'WM_LBUTTONUP             ',0

                db    'WM_LBUTTONDBLCLK         ',0

                db    'WM_RBUTTONDOWN           ',0

                db    'WM_RBUTTONUP             ',0

                db    'WM_RBUTTONDBLCLK         ',0

                db    'WM_MBUTTONDOWN           ',0

                db    'WM_MBUTTONUP             ',0

                db    'WM_MBUTTONDBLCLK         ',0

                db    'WM_MOUSELAST             ',0

                db    'WM_PARENTNOTIFY          ',0

                db    'WM_ENTERMENULOOP         ',0

                db    'WM_EXITMENULOOP          ',0

                db    'WM_MDICREATE             ',0

                db    'WM_MDIDESTROY            ',0

                db    'WM_MDIACTIVATE           ',0

                db    'WM_MDIRESTORE            ',0

                db    'WM_MDINEXT               ',0

                db    'WM_MDIMAXIMIZE           ',0

                db    'WM_MDITILE               ',0

                db    'WM_MDICASCADE            ',0

                db    'WM_MDIICONARRANGE        ',0

                db    'WM_MDIGETACTIVE          ',0

                db    'WM_MDISETMENU            ',0

                db    'WM_DROPFILES             ',0

                db    'WM_MDIREFRESHMENU        ',0

                db    'WM_CUT                   ',0

                db    'WM_COPY                  ',0

                db    'WM_PASTE                 ',0

                db    'WM_CLEAR                 ',0

                db    'WM_UNDO                  ',0

                db    'WM_RENDERFORMAT          ',0

                db    'WM_RENDERALLFORMATS      ',0

                db    'WM_DESTROYCLIPBOARD      ',0

                db    'WM_DRAWCLIPBOARD         ',0

                db    'WM_PAINTCLIPBOARD        ',0

                db    'WM_VSCROLLCLIPBOARD      ',0

                db    'WM_SIZECLIPBOARD         ',0

                db    'WM_ASKCBFORMATNAME       ',0

                db    'WM_CHANGECBCHAIN         ',0

                db    'WM_HSCROLLCLIPBOARD      ',0

                db    'WM_QUERYNEWPALETTE       ',0

                db    'WM_PALETTEISCHANGING     ',0

                db    'WM_PALETTECHANGED        ',0

                db    'WM_HOTKEY                ',0

                db    'WM_PRINT                 ',0

                db    'WM_PRINTCLIENT           ',0

                db    'WM_PENWINFIRST           ',0

                db    'WM_PENWINLAST            ',0

                db    'WM_MENURBUTTONUP         ',0

                db    'WM_MENUDRAG              ',0

                db    'WM_MENUGETOBJECT         ',0

                db    'WM_UNINITMENUPOPUP       ',0

                db    'WM_MENUCOMMAND           ',0

                db    'WM_NEXTMENU              ',0

                db    'WM_SIZING                ',0

                db    'WM_CAPTURECHANGED        ',0

                db    'WM_MOVING                ',0

                db    'WM_POWERBROADCAST        ',0

                db    'WM_DEVICECHANGE          ',0

                db    'WM_ENTERSIZEMOVE         ',0

                db    'WM_EXITSIZEMOVE          ',0

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

szDestClass     db      'Notepad',0

szFormat        db      'WndProc: [%04x] %s %08x %08x',0dh,0

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

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; 代码段

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                .code

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

_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

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

_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

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; 窗口过程

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

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

               

                invoke _ShowMessage, uMsg, wParam, lParam

 

                mov eax,uMsg

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

                .if     eax == WM_CLOSE

                       invoke     DestroyWindow,hWinMain

                        invoke     PostQuitMessage,NULL

                .elseif eax == WM_NCCREATE

                        mov eax,1

                        ret

                .elseif eax == WM_PAINT

                        invoke ValidateRect, hWnd, NULL

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

                .else

                        ;invoke    DefWindowProc,hWnd,uMsg,wParam,lParam

                        ret

                .endif

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

                xor     eax,eax

                ret

_ProcWinMain    endp

 

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

_WinMain        proc

                local   @szBuffer[128]:byte

                local   @stWndClass:WNDCLASSEX

                local   @stMsg:MSG

 

                invoke     GetModuleHandle,NULL

                mov     hInstance,eax

                invoke     RtlZeroMemory,addr @stWndClass,sizeof @stWndClass

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

; 注册窗口类

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

                invoke     LoadCursor,0,IDC_ARROW

                mov     @stWndClass.hCursor,eax

                push    hInstance

                pop     @stWndClass.hInstance

                mov     @stWndClass.cbSize, sizeof WNDCLASSEX

                mov     @stWndClass.style, CS_HREDRAW or CS_VREDRAW

                mov     @stWndClass.lpfnWndProc, offset _ProcWinMain

                mov     @stWndClass.hbrBackground,COLOR_WINDOW + 1

                mov     @stWndClass.lpszClassName, offset szClassName

                invoke     RegisterClassEx, addr @stWndClass

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

; 建立并显示窗口

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

                invoke _SendtoNotepad, addr szCreateWindow1

                invoke     CreateWindowEx, WS_EX_CLIENTEDGE, \

                        offset szClassName, offset szCaptionMain, \

                        WS_OVERLAPPEDWINDOW, \

                        100, 100, 600, 400, \

                        NULL, NULL, hInstance, NULL

                mov     hWinMain,eax

                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

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

; 消息循环

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

                .while TRUE

                        invoke _SendtoNotepad, addr szGetMsg1

                        invoke     GetMessage, addr @stMsg, NULL, 0, 0

                       

                       push eax

                        invoke wsprintf, addr @szBuffer, addr szGetMsg2, @stMsg.message

                        invoke _SendtoNotepad, addr @szBuffer

                        pop eax

                       

                        .break     .if eax == 0

                       

                        invoke     TranslateMessage, addr @stMsg

                       

                        invoke _SendtoNotepad, addr szDispatchMsg1

                        invoke     DispatchMessage, addr @stMsg

                        invoke _SendtoNotepad, addr szDispatchMsg2

                .endw

                ret

_WinMain        endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

start:

                call    _WinMain

                invoke ExitProcess, NULL

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                end start

posted on 2010-08-23 13:11 luqingfei 阅读(1194) 评论(0)  编辑 收藏 引用 所属分类: Win32汇编程语言序设计


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

<2009年4月>
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

统计

留言簿(6)

随笔分类(109)

随笔档案(105)

Blogers

Game

Life

NodeJs

Python

Useful Webs

大牛

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜