兰陵月 发表于 2018-3-13 22:43:45

琢石成器WIN32汇编程序设计学习(六)-WNDCLASSEX

本帖最后由 兰陵月 于 2018-3-13 23:17 编辑

第一段代码,变量定义
;------------------------------------------------------------------------
; 可读可写未初始化变量
;------------------------------------------------------------------------
                              .data?
;------------------------------------------------------------------------
hInstance                dd                ?
hWinMain                dd                ?
hMenu                        dd                ?
;------------------------------------------------------------------------
; 可读不可写初始化常量
;------------------------------------------------------------------------
                              .const
;------------------------------------------------------------------------
szClassName                db      "MyClass",0
szCaptionMain      db      "鱼C论坛-汇编语言交流-by 兰陵月",0
szText                        db      "鱼C论坛好!鱼C论坛妙!鱼C论坛呱呱叫!",0
szMainMenu                db      'MainMenu'
;------------------------------------------------------------------------

第二段代码,WNDCLASSEX结构(C++语法表示)
【C++】
typedef struct tagWNDCLASSEX {
UINT            cbSize;//ok
UINT            style;//ok
WNDPROC         lpfnWndProc;//ok
int       cbClsExtra;
int       cbWndExtra;
HINSTANCE         hInstance;//ok
HICON             hIcon;
HCURSOR         hCursor;//ok
HBRUSH            hbrBackground;//ok
LPCTSTR         lpszMenuName;
LPCTSTR         lpszClassName;//ok
HICON             hIconSm;
} WNDCLASSEX, *PWNDCLASSEX;

第三段代码,注册窗口类(WIN32汇编语言)
;------------------------------------------------------------------------
_WinMain                proc

                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
                invoke        LoadMenu,hInstance,offset szMainMenu
                mov                hMenu,eax
                mov                @stWndClass.lpszMenuName,offset szMainMenu
                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_MENU + 1
                mov                @stWndClass.lpszClassName,offset szClassName
                invoke        RegisterClassEx,addr @stWndClass
;********************************************************************
; 建立并显示窗口
;********************************************************************
                invoke        CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,offset szCaptionMain,\
                        WS_OVERLAPPEDWINDOW,\
                        100,100,600,400,\
                        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        TranslateMessage,addr @stMsg
                        invoke        DispatchMessage,addr @stMsg
                .endw
                ret
                       
_WinMain                endp


按照上图中红框内的意思,如果在注册类的时候定义了菜单选项,则第三段代码第32行处的参数“hMenu”改为NULL,窗口仍然会显示菜单。

再根据上图中标示处的内容,必须要得到菜单的句柄。
所以

然后将WNDCLASSEX结构的lpszMenuName字段变为菜单句柄值,即
mov                @stWndClass.lpszMenuName,eax
编译成功,但是运行程序发生了错误。如下图:

这说明,WNDCLASSEX结构中的字段填写方式是错误的,不能填写菜单句柄值。
经尝试,方法1:
在资源文件中,将菜单值更改为数值型的ID值,如下图:

然后在asm源程序中,同样等值定义好相关符号,如下图:

并在注册类填充WNDCLASSEX结构字段时,将菜单ID值填入,如下:
mov        @stWndClass.lpszMenuName,IDM_MAIN
程序可以正常运行,如下图:


方法2:在资源文件中和源程序中将菜单ID改为字符串形式,然后将字符串地址填入WNDCLASSEX相关字段,也同样可以通过。如下:
mov        @stWndClass.lpszMenuName,offset szMainMenu.

所以下图中的表述是不准确的,或者是不详细的!

会魔法的魔法 发表于 2018-3-14 08:53:39

可以666666

兰陵月 发表于 2018-3-14 09:02:15

会魔法的魔法 发表于 2018-3-14 08:53
可以666666

{:10_266:}{:10_266:}{:10_266:}
初学,喜欢各种情况都鼓捣一下!

会魔法的魔法 发表于 2018-3-14 22:37:26

WNDCLASSEX.lpfnWndProc offset _ProcWinMain

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

这段代码里的 uses ebx edi esi hWnd, uMsg, wParam, lParam 传值和顺序有些一知半解 能帮我讲解一下吗?

兰陵月 发表于 2018-3-16 14:29:55

uses ebx edi esi
是压入寄存器。相当于函数开始时PUSH,函数返回前POP这三个寄存器。
hWnd是指向窗口的指针,uMsg是指向消息的指针,wParam、lParam是MSG结构体里面的两个参数啊
传递顺序是stdcall形式,从右向左。
页: [1]
查看完整版本: 琢石成器WIN32汇编程序设计学习(六)-WNDCLASSEX