三:模块和句柄
1 . 程序结构模式分为两种,过程驱动方式和事件驱动方式
2. PostMessage 是把一个消息放到其他程序的消息队列中,而SendMessage 则越过消息队列直接调用目标程序的窗口过程。
3.一个应用程序为了区分地址空间中的不同模块,每个模块都有一个唯一的模块句柄来标识。取模块句柄使用的API函数是
GetModuleHandler 具体用法是:
invoke GetMoudleHandler,lpModuleName
lpModuleName 参数是一个指向含有模块名称字符串的指针,可以用这个函数取得各个模块的句柄。如果lpModuleName 是NULL ,得到的是调用本模块的句柄。
4.句柄只是Windows 用来表示各种资源的编号而已。
四:创建窗口
1.注册窗口API函数是RegisterClassEx ,最后的Ex是扩展的意思。WNDCLASSEX 是 WNDCLASS结构的扩展。
2.在头文件中以WM_ 开头的预定义值(意为Windows Message)
3.创建窗口划分为:注册窗口类---->>>建立窗口类--->>>显示窗口
下面的例程是win32窗口的demo ,按照自己的理解注释了一部分代码:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming 4th Edition>
; by 罗云彬, [email protected]
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 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
;szCaption1 db '恭喜',0
;szText1 db '当您看到这个信息的时候,您已经可以编译Win32汇编程序了!',0
;szClassName1 db 'MyClass1',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 窗口过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcWinMain proc uses ebx edi esi hWnd,uMsg,wParam,lParam
local @stPs:PAINTSTRUCT
local @stRect:RECT
local @hDc
mov eax,uMsg
;invoke MessageBox,NULL,offset szText1,offset szCaption1,MB_OK
;********************************************************************
.if eax == WM_PAINT
invoke BeginPaint,hWnd,addr @stPs ;hwnd 消息要发向的窗口句柄
mov @hDc,eax
invoke GetClientRect,hWnd,addr @stRect ;GetClientRect 获取客户区的大小,
invoke DrawText,@hDc,addr szText,-1,\ ;DrawText 函数将字符串按照取得的屏幕大小 居中写在窗口中
addr @stRect,\
DT_SINGLELINE or DT_CENTER or DT_VCENTER
invoke EndPaint,hWnd,addr @stPs ;beginpaint 和 endpaint 开始和结尾处是相同的
;********************************************************************
.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 ;此处定义呢,WNDCLASSEX 的是属于类,@stWndClass 是类名
local @stMsg:MSG ;此处同上
invoke GetModuleHandle,NULL ;这个是本模块的句柄
mov hInstance,eax ;制定要注册的窗口类属于那一个模块
invoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass ;目的是将利用RtlZeroMemory指令,将类stWndClass进行初始化
;********************************************************************
; 注册窗口类
;********************************************************************
invoke LoadCursor,0,IDC_ARROW
mov @stWndClass.hCursor,eax
push hInstance
pop @stWndClass.hInstance ;
mov @stWndClass.cbSize,sizeof WNDCLASSEX ;WNDCLASSEX 指定WNDCLASSEX长度
mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW ;style 窗口风格
mov @stWndClass.lpfnWndProc,offset _ProcWinMain ;指定呢基于这个类建立的窗口的窗口过程地址
mov @stWndClass.hbrBackground,COLOR_WINDOW + 1 ;windows 规定必须在颜色值上+1
mov @stWndClass.lpszClassName,offset szClassName ;制定程序员建立的类命名,,以后用这个名称来引用他,在程序里,它指向'Myclass'字符串
invoke RegisterClassEx,addr @stWndClass
;********************************************************************
; 建立并显示窗口
;********************************************************************
invoke CreateWindowEx,WS_EX_CLIENTEDGE, ;WS_EX_ACCEPTFILES,\ ;
offset szClassName,offset szCaptionMain,\ ;szCaptionMain表示窗口名称的字符串 ,szClassName 表示程序员建立的类名
WS_OVERLAPPEDWINDOW,\ ;窗口风格定义
100,100,800,400,\ ;(x,y,长度,宽度)
NULL,NULL,hInstance,NULL
mov hWinMain,eax ;hWinMain 是代表已经定义但是没有赋值的
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
在前一个win32窗口中建立子窗口:相比前一段代码主要是增加这部分代码:
;********************************************************************
; 建立一个按钮 重点关注这块代码
;********************************************************************
.elseif eax == WM_CREATE
invoke CreateWindowEx,NULL,\
offset szButton,offset szButtonText,\
WS_CHILD or WS_VISIBLE,\
10,10,65,42,\
hWnd,1,hInstance,NULL
具体的看所有的源代码:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming 4th Edition>
; by 罗云彬, [email protected]
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 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
szButton db 'button',0
szButtonText db '&OK',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_CREATE
invoke CreateWindowEx,NULL,\
offset szButton,offset szButtonText,\
WS_CHILD or WS_VISIBLE,\
10,10,65,42,\
hWnd,1,hInstance,NULL
;********************************************************************
.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