窗口程序的运行过程
这是主程序的结构流程:
1.得到应用程序的句柄 GetModuleHandle
2.注册窗口类 RegisterClassEx 注册前先填写RegisterClassEx的参数WNDCLASSEX结构
3.建立窗口 CreateWindow
4.显示窗口 ShowWindow
5.刷新窗口客户区 UpdateWIndow
6.进入无限的消息获取和处理的循环。
首先获取消息GetMessgae 获得消息则分派到回调函数处理DispatchMessage 如果消息是WM_QUIT 则推出循环
取模块的句柄GetModuleHandle 他的参数是一个指向含有模块名称字符串的指针,如果想得到User32.dll的句柄则可以写:
szUserDll db 'User32.dll',0
...
invoke GetModuleHandle,addr szUserDll
.if eax
mov hUserDllHandle,eax
这里就获得了User32.dll的句柄,当参数为0的时候获取本模块的句柄:
invoke GetModuleHandle,NULL
mov hInstance,eax
注册窗口类的API函数式 RegisterClassEx,通过传送一个指向WNDcLASSES的指针。
注册窗口类的代码:
//-------------------------------------------------------------------------------------------------
local @stWndClass:WNDCLASSEX // 定义一个WNDCLASSES结构
local @stMsg:MSG
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass// 清零
;********************************************************************
; 注册窗口类
;********************************************************************
invoke LoadCursor,0,IDC_ARROW ;IDC_ARROW是Windows预定义的箭头光标
mov @stWndClass.hCursor,eax;赋予光标句柄句柄
push hInstance
pop @stWndClass.hInstance;赋予实例句柄
mov @stWndClass.cbSize,sizeof WNDCLASSEX;赋予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
//----------------------------------------------------------------------------------------------------
WNDCLASSEX STRUCT
cbsize dword ?;指定的NDCLASSEX长度
style dword ?;窗口风格
lpfnwndproc dword ?;基于这个类建立的窗口的窗口过程的地址
cbclsextra dword ?;下
cbwndextra dword ?;cbWndExtra,cbClsExtra 分别是Windows内部保存的窗口结构和类结构中给程序员预留的空间大小用来存放自定义数据 单位是字节
hinstance dword ?;指定注册的窗口类属于那个模块 模块句柄通过GetModuleHandle获得
hIcon dword ?;图标句柄
hcursor dword ?;光标句柄
hbrbackground dword ?;窗口客户区的背景色
lpszmenuname dword ?;指示窗口上显示的默认菜单
lpszclassname dword ?;程序员指定的要建立的类命名
hiconsm dword ?;
WNDCLASSEX ENDS
2.建立窗口 CreateWindowEx
method:
invoke CreateWIndowEx,dwExstyle,lpClassName,lpWindowName,dwStyle,x,y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam
dwExstyle,
lpClassName,建立窗口使用的类名字符串指针
lpWindowName指向窗口名称的字符串
dwStyle
,x,y,nWidth,nHeight,左上角位置及长度和宽度
hWndParent,窗口所属的父窗口
hMenu,窗口上要出现的菜单的句柄
hInstance,模块句柄
lpParam
3.消息循环
通常的消息循环为
.whle TRUE
invoke GetMessage,addr @stMsg,NULL,0,0
.break .if eax==0
invoke TranslateMessage,addr @stMsg
invoke DispatchMessage,addr @stMsg
.endw
Msg结构如下:
MSG STRUCT
hwnd DWORD ?;消息要发向的窗口句柄
message DWORD ?;消息标识符
wParam DWORD ?;消息参数1
lParam DWORD ?;消息参数2
time DWORD ?;消息放入队列的时间
pt POINT <>;一个指向POINT数据结构,表示消息放入消息队列时的鼠标坐标
MSG ENDS
窗口过程:
一般结构如下
WindowProc proc uses ebx edi esi hWnd,uMsg,wParam,lParam
mov eax,uMsg
.if eax==WM_XXX
<>..
.elseif eax==WM_YYY
<>...
.elseif eax== WMCLOSE
invoke DestroyWIndow,hWinMain
invoke PostQuitMessage,NULL
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
WindowProc endp
下面是FirstWindow源代码:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming 2nd Edition>
; by 罗云彬, http://asm.yeah.net
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; FirstWindow.asm
; 窗口程序的模板代码
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff FirstWindow.asm
; Link /subsystem:windows FirstWindow.obj
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.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 'My first Window !',0
szText db 'Win32 Assembly, Simple and powerful !',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 窗口过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcWinMain proc uses ebx edi esi hWnd,uMsg,wParam,lParam
local @stPs:PAINTSTRUCT
local @stRect:RECT
local @hDc
mov eax,uMsg
;********************************************************************
.if eax == WM_PAINT
invoke BeginPaint,hWnd,addr @stPs
mov @hDc,eax
invoke GetClientRect,hWnd,addr @stRect
invoke DrawText,@hDc,addr szText,-1,\
addr @stRect,\
DT_SINGLELINE or DT_CENTER or DT_VCENTER
invoke EndPaint,hWnd,addr @stPs
;********************************************************************
.elseif eax == WM_CLOSE
invoke DestroyWindow,hWinMain
invoke PostQuitMessage,NULL
;********************************************************************
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
;********************************************************************
xor eax,eax
ret
_ProcWinMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_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
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,600,400,\
NULL,NULL,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
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
call _WinMain
invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start