1.窗口程序的运行模式:消息驱动
2.窗口程序实现大部分功能的代码应该呆在同一个模块中——“消息处理”模块,这个模块可以随时应付所有类型的消息,只有这样才能随时响应用户的各种操作。
3.窗口程序的运行过程:
4.窗口的回调函数,也叫窗口过程(由Windows自身调用)。窗口过程构造了一个分支结构,对应不同的消息执行不同的代码,一个应用程序几乎所用的功能代码都集中在窗口过程里面。
5.Windows在系统内部有一个系统消息队列;Windows为每个程序(严格来讲是每个线程)维护一个消息队列。
6.模块:一个模块代表的是一个运行中的exe文件或dll文件,用来代表这个文件中所用的代码和资源,磁盘上的文件不是模块,装入内存后运行时就叫模块。一个应用程序调用其他dll中的API是,这些dll文件被装入内存,就产生了不同的模块,为了区分地址空间中的不同模块,每一个模块都有一个唯一的模块句柄来标识。
在win32中,模块句柄在数值上等于程序在内存中装入的起始地址。可以使用GetModuleHandle 获取模块句柄。
7.句柄:句柄只是一个数值,无实际意义,被Windows用于表示各种资源的编号。
8.CreateWindowEx也可以用来创建子窗口,如按钮。
9.回调函数:所有应用程序提供给Windows的回调函数都必须注意保存 ebx,edi,esi,ebp寄存器,因为Windows内部将这四个寄存器当做指针使用。
9.1.定义用户消息的时候,一般使用WM_USER+x(x从1开始)的形式。
9.2.默认处理函数是DefWindowProc。
9.3.接收到WM_CLOSE消息时,应调用DestroyWindow 来摧毁窗口,并调用PostQuitMessage 向消息循环发送WM_QUIT消息来退出消息循环。
10.SendMessage直接调用其他窗口过程来处理某个消息,并等待处理完后返回。
PostMessage将消息放到消息队列,然后返回,此时消息可能还没有处理完。
另外,当消息参数中用到指针时,用PostMessage函数来发送消息是不会成功的。
窗口模板:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; FirstWindow.asm
; 窗口程序的模板代码
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff FirstWindow.asm
; Link /subsystem:windows FirstWindow.obj
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.386.model flat,stdcalloption 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,lParamlocal @stPs:PAINTSTRUCTlocal @stRect:RECTlocal @hDcmov eax,uMsg
;********************************************************************.if eax == WM_PAINTinvoke BeginPaint,hWnd,addr @stPsmov @hDc,eaxinvoke GetClientRect,hWnd,addr @stRectinvoke DrawText,@hDc,addr szText,-1,\addr @stRect,\DT_SINGLELINE or DT_CENTER or DT_VCENTERinvoke EndPaint,hWnd,addr @stPs
;********************************************************************.elseif eax == WM_CLOSEinvoke DestroyWindow,hWinMaininvoke PostQuitMessage,NULL
;********************************************************************.elseinvoke DefWindowProc,hWnd,uMsg,wParam,lParamret.endif
;********************************************************************xor eax,eaxret_ProcWinMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WinMain proclocal @stWndClass:WNDCLASSEXlocal @stMsg:MSGinvoke GetModuleHandle,NULLmov hInstance,eaxinvoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
;********************************************************************
; 注册窗口类
;********************************************************************invoke LoadCursor,0,IDC_ARROWmov @stWndClass.hCursor,eaxpush hInstancepop @stWndClass.hInstancemov @stWndClass.cbSize,sizeof WNDCLASSEXmov @stWndClass.style,CS_HREDRAW or CS_VREDRAWmov @stWndClass.lpfnWndProc,offset _ProcWinMainmov @stWndClass.hbrBackground,COLOR_WINDOW + 1mov @stWndClass.lpszClassName,offset szClassNameinvoke RegisterClassEx,addr @stWndClass
;********************************************************************
; 建立并显示窗口
;********************************************************************invoke CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,offset szCaptionMain,\WS_OVERLAPPEDWINDOW,\100,100,600,400,\NULL,NULL,hInstance,NULLmov hWinMain,eaxinvoke ShowWindow,hWinMain,SW_SHOWNORMALinvoke UpdateWindow,hWinMain
;********************************************************************
; 消息循环
;********************************************************************.while TRUEinvoke GetMessage,addr @stMsg,NULL,0,0.break .if eax == 0invoke TranslateMessage,addr @stMsginvoke DispatchMessage,addr @stMsg.endwret_WinMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:call _WinMaininvoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>end start