友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
荣耀电子书 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

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

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




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

; 注册窗口类

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

                 invoke   RtlZeroMemory;addr @stWndClass;sizeof @stWndClass

                 invoke   LoadIcon;hInstance;ICO_MAIN

                 mov      @stWndClass。hIcon;eax

                 mov      @stWndClass。hIconSm;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   CreateWindowEx;WS_EX_CLIENTEDGE;

                          offset szClassName;offset szCaptionMain;

                          WS_OVERLAPPEDWINDOW;

                          100;100;400;300;

                          NULL;hMenu;hInstance;NULL

                 mov      hWinMain;eax

                 invoke   ShowWindow;hWinMain;SW_SHOWNORMAL

                 invoke   UpdateWindow;hWinMain

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

; 消息循环

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

                 。while   TRUE

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

                 。break   。if eax  0

                 invoke   TranslateAccelerator;hWinMain;

                          @hAccelerator;addr @stMsg

                 。if      eax  0

                          invoke  TranslateMessage;addr @stMsg

                          invoke  DispatchMessage;addr @stMsg

                      。endif

                 。endw

                 ret

 

_WinMain              endp

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

start:

                 call     _WinMain

                 invoke   ExitProcess;NULL

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

                 end      start



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


第5章 使用资源


5。1 菜单和加速键(5)

    
1。 加载菜单

在窗口中加载菜单的方法在第4章已经提及,方法有两个:一是在注册窗口类的时候指定类的默认菜单;二是在建立窗口的时候在参数中指定菜单句柄。Menu。asm程序中用的是第2种方法:

invoke   CreateWindowEx;WS_EX_CLIENTEDGE;

         offset szClassName;offset szCaptionMain;

         WS_OVERLAPPEDWINDOW;

         100;100;400;300;

         NULL;hMenu;hInstance;NULL

在参数中指出了hMenu。不管用哪种方法,首先都必须使用LoadMenu函数来获取菜单句柄hMenu,如下面的语句:

invoke  LoadMenu;hInstance;IDM_MAIN

mov hMenu;eax

这个函数的第1个参数是用GetModuleHandle获取的实例句柄,第2个参数指定需要装入的菜单资源ID,函数返回菜单句柄。在得到菜单句柄以后,我们先把它放入hMenu变量保存起来以便后用。

当资源文件中用字符串为名称定义菜单而不是用数值的时候,例如:

MainMenu        menu        //定义菜单名为字符串“MainMenu”

begin

。。。

end

那么在程序中就必须用字符串指针代替菜单ID做参数:

szMenu      〃MainMenu〃;0       ;在数据段中定义菜单名称字符串

            。。。

            invoke  LoadMenu;hInstance;addr szMenu  ;在程序中装载

            mov     hMenu;eax

 用字符串为名称定义资源,在资源装载函数LoadXXXX中用字符串指针做参数装入,这实际上是一个通用的方法,不仅适用于菜单资源,对于其他类别的资源也是适用的。在其他资源的介绍中就不再另外说明了。

2。 加载加速键

和菜单一样,加速键在使用前也要装入,参数同样是在资源脚本文件中定义的加速键ID,程序中对应的语句是:

invoke  LoadAccelerators;hInstance;IDA_MAIN

mov     @hAccelerator;eax

其实我们自己在程序中也可以很方便地实现加速键功能,方法是:在WM_KEYDOWN消息中判断键盘消息并按照自定义的逻辑进行处理,使用加速键实际上是让Windows替我们完成这个功能,Windows实现的方法正是在消息循环中检查WM_KEYDOWN和WM_SYSKEYDOWN消息。下面是使用加速键时消息循环的代码,请注意粗体字部分:

。while   TRUE

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

         。break   。if eax   0

         invoke   TranslateAccelerator;hWinMain;@hAccelerator;addr @stMsg

         。if      eax  0

                  invoke   TranslateMessage;addr @stMsg

                  invoke   DispatchMessage;addr @stMsg

         。endif

。endw

TranslateAccelerator函数是实现加速键功能的核心,它的参数为目标窗口、加速键句柄和GetMessage取得的消息结构。该函数检查消息结构中的消息,如果遇到WM_KEYDOWN和WM_SYSKEYDOWN消息则检测加速键资源,看按键是否符合某个加速键,符合的话则向目标窗口发送WM_MAND或WM_SYSMAND消息,并返回TRUE,不符合的话不进行任何处理并返回FALSE。

由于加速键的键码并不是用户真正想输入窗口的,比如用户在写字板中输入文字,按Ctrl+C键是为了“拷贝”,而并不是想把Ctrl+C键对应的字符输入文档,所以这个Ctrl+C的键码在完成加速键的使命后就应该丢弃,也就是说符合加速键的键盘消息不应该再发送给窗口,TranslateMessage和DispatchMessage函数前的逻辑判断就是这样的意图:只有TranslateAccelerator没有转换的消息(返回值eax为0)才继续处理。

另外,TranslateAccelerator的参数中有个“目标窗口”,例子中是程序的主窗口hWinMain,为什么要设置这样一个参数而不像DispatchMessage函数一样使用MSG结构中的hwnd呢?这是因为键盘消息可以产生于不同窗口中——既可能是主窗口,也可能是其他子窗口,如果用@stMsg。hwnd做目标窗口,就必须在所有子窗口的窗口过程中都设置处理加速键消息的代码,这显然是一种浪费,所以一般把所有的加速键消息都发送到主窗口,然后集中在主窗口的窗口过程中处理WM_MAND消息,这样有利于精简代码。

3。 菜单和加速键消息

当用户选择了一个菜单项的时候,Windows向菜单所属的窗口发送WM_MAND消息;而用户按下了一个加速键的时候,Windows向TranslateAccelerator函数指定的目标窗口发送WM_MAND消息。一般这两种情况对应的窗口都是主窗口,所以可以在主窗口中的窗口过程中集中处理WM_MAND消息,而不必考虑它究竟是菜单引发的还是加速键引发的。

WM_MAND消息的两个参数是这样定义的:

wParam的高位 = wNotifyCode  ;通知码 

wParam的低位 = wID          ;命令ID

lParam = hwndCtl            ;发送WM_MAND的子窗口句柄

除了菜单和加速键,WM_MAND消息也可以由其他子窗口引发,如主窗口中的按钮或工具栏等,lParam参数指定了引发消息的子窗口句柄,对于菜单和加速键引发的WM_MAND消息,lParam的值为零。wParam参数的低16位是命令ID,也就是资源脚本文件中菜单项的命令ID或加速键的命令ID,高16位是通知码,菜单消息的通知码是0,加速键消息的通知码为1。

在需要处理菜单和加速键消息的窗口过程中,一般需要增加一个WM_MAND分支来处理对应的消息,这个分支的一般结构为:

。elseif eax   WM_MAND  ;eax中为wMsg

        mov     eax;wParam

        movzx   eax;ax

        。if     eax   命令ID1

                 。。。

        。elseif eax   命令ID2

                 。。。

        。endif

其中movzx eax;ax指令将16位的ax扩展到32位的eax,相当于将eax的高16位填零,作用就是当消息由加速键引起时,将高16位中的1忽略,这样下面的分支就可以同时处理菜单
返回目录 上一页 下一页 回到顶部 0 0
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!