窗口创建过程
GetModuleHandle->RtlZeroMemory->LoadCursor->RegisterClassEx->CreateWindowsEx->ShowWindow->UpdateWindow
获得模块句柄->结构体初始化(填0)->加载光标->注册窗体类->创建窗体->显示窗体->更新客户区
win32API函数定义
GetModuleHandle,lpModuleName
参数:lpModuleName参数是一个指向含有模块名称字符串的指针;
功能: 是返回指定模块名的句柄,如果为NULL,则返回本模块的句柄。
RtlZeroMemory,lpDestination,bLength
参数:
lpDestination指向一块准备用0来填充的内存区域的开始地址。
bLength准备用0来填充的内存区域的大小,按字节来计算。
RtlZeroMemory只是将指定的内存块清零。
功能:使用结构前清零,而不让结构的成员数值具有不确定性,是一个好的编程习惯。
LoadCursor,hlnstance,LpCursorName
参数:
hlnstance 标识一个模块事例,它的可执行文件包含要载入的光标。
LpCursorName
指向以NULL结束的字符串的指针,该字符串存有等载入的光标资源名。该参数低位字节和高位字节0组成资源标识器也可以由低位字为资源标识符和高位字为零组成。也可以用MAKEINTRESOURCE宏命令创建该值。要使用Win32预定义的一个光标,应用程序必须把hlnstance参数设为NULL。
功能:该函数从一个与应用事例相关的可执行文件(EXE文件)中载入指定的光标资源。该函数已被Loadlmage函数替代。
RegisterClassEx,Ipwcx
参数:
Ipwcx
指向一个WNDCLASSEX结构的指针。在传递给这个函数之前,必须在结构内填充适当的类的属性返回值:如果函数成功,返回这个窗口类型的标识号;如果函数失败,返回值为0。若想获得更多错误信息,请调用GetLastError函数。
功能:该函数为随后在调用Createwindow函数和CreatewindowEx函数中使用的窗口注册一个窗口类。
WNDCLASSEX STRUCT
cbSize DWORD ? ; 结构的字节数
style DWORD ? ; 类风格
lpfnWndProc DWORD ? ; 窗口过程的地址
cbClsExtra DWORD ?
cbWndExtra DWORD ?
hInstance DWORD ? ;所属的实例句柄
hIcon DWORD ? ;窗口图标
hCursor DWORD ? ; 窗口光标
hbrBackground DWORD ? ;背景色
lpszMenuName DWORD ? ;窗口菜单
lpszClassName DWORD ? ;类名字符串的地址
hIconSm DWORD ? ;小图标
WNDCLASSEX ENDS
CreateWindowsEx,DWORDdwExStyle,\ ;窗口的扩展风格
LPCTSTRlpClassName,\ ;指向注册类名的指针
LPCTSTRlpWindowName,\ ;指向窗口名称的指针
DWORDdwStyle,\ ;窗口风格
intx,\ ;窗口的水平位置
inty,\ ;窗口的垂直位置
intnWidth,\ ;窗口的宽度
intnHeight,\ ;窗口的高度
HWNDhWndParent,\ ;父窗口的句柄
HMENUhMenu,\ ;菜单的句柄或是子窗口的标识符
HINSTANCEhInstance,\ ;应用程序实例的句柄
LPVOIDlpParam ;指向窗口的创建数据
功能: 该函数创建一个具有扩展风格的层叠式窗口、弹出式窗口或子窗口,其他与CreateWindow函数相同。
ShowWindow,hWnd,nCmdShow
参数:
hWnd:指窗口句柄。
nCmdShow:指定窗口如何显示。如果发送应用程序的程序提供了STARTUPINFO结构,则应用程序第一次调用ShowWindow时该参数被忽略。否则,在第一次调用ShowWindow函数时,该值应为在函数WinMain中nCmdShow参数。
功能:该函数设置指定窗口的显示状态
如果窗口之前可见,则返回值为非零。如果窗口之前被隐藏,则返回值为零。
UpdateWindow,hWnd
参数:
hwnd 要更新的窗口句柄
功能:如果窗口更新的区域不为空,UpdateWindow函数通过发送一个WM_PAINT消息来更新指定窗口的客户区。函数绕过应用程序的消息队列,直接发送WM_PAINT消息给指定窗口的窗口过程,如果更新区域为空,则不发送消息。
如果函数调用成功,返回值为非零值。如果函数调用不成功,返回值为零。
消息循环 GetMessage->TranslateMessage->DispatchMessage
从消息队列中获得一条消息->根据键盘按键的扫描码转换为ASCLL值->分发消息给USER.DLL,USER.DLL调用窗体过程处理消息
GetMessage,lpMsg,hWnd,wMsgFilterMin,wMsgFilterMax
参数:
lpMsg:指向MSG结构的指针,该结构从线程的消息队列里接收消息。
hWnd:取得其消息的窗口的句柄。当其值取NULL时,GetMessage为任何属于调用线程的窗口检索消息,线程消息通过PostThreadMessage寄送给调用线程。
wMsgFilterMin:指定被检索的最小消息值的整数。
wMsgFilterMax:指定被检索的最大消息值的整数。
功能: 函数GetMessage是从调用线程的消息队列里取得一个消息并将其放于指定的结构。此函数可取得与指定窗口联系的消息和由PostThreadMesssge寄送的线程消息。此函数接收一定范围的消息值。GetMessage不接收属于其他线程或应用程序的消息。获取消息成功后,线程将从消息队列中删除该消息。函数会一直等待直到有消息到来才有返回值。
返回值:如果函数取得WM_QUIT之外的其他消息,返回非零值。如果函数取得WM_QUIT消息,返回值是零。如果出现了错误,返回值是-1。例如,当hWnd是无效的窗口句柄或lpMsg是无效的指针时。若想获得更多的错误信息,请调用GetLastError函数。
TranslateMessage,lpMsg
参数:IpMsg 指向含有消息的MSG结构的指针,该结构里含有用函数GetMessage或PeekMessage从调用线程的消息队列里取得的消息信息。
函数功能:该函数将虚拟键消息转换为字符消息。字符消息被寄送到调用线程的消息队列里,当下一次线程调用函数GetMessage或PeekMessage时被读出。
返回值:如果消息被转换(即,字符消息被寄送到调用线程的消息队列里),返回非零值。如果消息是WM_KEYDOWN,WM_KEYUP
WM_SYSKEYDOWN或WM_SYSKEYUP,返回非零值,不考虑转换。如果消息没被转换(即,字符消息没被寄送到调用线程的消息队列里),返回值是零。
DispatchMessage,lpmsg
参数:lpmsg 指向含有消息的MSG结构的指针。
功能: 该函数分发一个消息给窗口程序。通常消息从GetMessage函数获得。消息被分发到回调函数(过程函数),作用是消息传递给操作系统,然后操作系统去调用我们的回调函数,也就是说我们在窗体的过程函数中处理消息
返回值:返回值是窗口程序返回的值。尽管返回值的含义依赖于被调度的消息,但返回值通常被忽略。
窗口过程 BeginPaint->GetClientRect->DrawText->EndPaint
进行窗口绘制工作->获得窗体客户区->写入文本->结束绘制
BeginPaint,hwnd,lpPaint
hwnd:[输入]被重绘的窗口句柄
lpPaint:[输出]指向一个用来接收绘画信息的PAINTSTRUCT结构
功能:BeginPaint函数为指定窗口进行绘图工作的准备,并用将和绘图有关的信息填充到一个
PAINTSTRUCT结构中。
如果函数成功,返回值是指定窗口的“显示设备描述表”句柄。如果函数失败,返回值是NULL,表明没有得到显示设备的内容。
GetClientRect,hWnd,lpRect
参数:
hWnd:是程序窗口的句柄。
lpRect:是一个指针,指向一个RECT类型的rectangle结构。该结构有四个LONG字段,分别为left、top、right和bottom。
GetClientRect将这四个字段设定为窗口显示区域的尺寸。left和top字段通常设定为0。right和bottom字段设定为显示区域的宽度和高度(像素点数)。 也可以是一个CRect对象指针。CRect对象有多个参数,与RECT用法相同。
功能: 该函数获取窗口客户区的坐标。客户区坐标指定客户区的左上角和右下角。由于客户区坐标是相对窗口客户区的左上角而言的,因此左上角坐标为(0,0)。这里应该注意一下:坐标包含两种:屏幕坐标与客户区坐标。严格区分这两种坐标对于理解Windows编程是很重要的。
作用总的来说就是把客户区的大小写进第二个参数所指的Rect结构当中。
DrawText,hDC,lpString,nCount,lpRect,uFormat
hdc:[输入]设备环境句柄。
lpString:[输入]指向将被写入的字符串的指针,如果参数nCount是-1,则字符串必须是以\0结束的。 如果uFormat包含DT_MODIFYSTRING,则函数可为此字符串增加4个字符,存放字符串的缓冲区必须足够大,能容纳附加的字符。
nCount:[输入]指向字符串中的字符数。如果nCount为-1,则lpString指向的字符串被认为是以\0结束的,DrawText会自动计算字符数。
lpRect:[输入/输出]指向结构RECT的指针,其中包含文本将被置于其中的矩形的信息(按逻辑坐标)。
uFormat:[输入]指定格式化文本的方法。
功能:该函数的功能是在指定的矩形里写入格式化文本,根据指定的方法对文本格式化(扩展的制表符,字符对齐、折行等)
要指定额外的格式化选项,请使用DrawTextEx函数。
返回: 如果函数调用成功,返回值是正文的高度(逻辑单位)。如果指定了DT_VCENTER或DT_BOTTOM,返回值是lpRect->top到绘制的正文的底部的偏移值。如果函数调用失败,返回值是0
EndPaint,hWnd,lpPaint
hWnd:[输入]已经被重画的窗口的HANDLE
lpPaint:[输入]指向一个PAINTSTRUCT结构,该结构包含了绘画信息,是BeginPaint函数返回的返回值:
返回值:返回值始终是非0
功能:EndPaint函数标记指定窗口的绘画过程结束;这个函数在每次调用BeginPaint函数之后被请求,但仅仅在绘画完成以后。
PAINTSTRUCT 结构体包含了用于绘制窗口客户区的信息。
PAINTSTRUCT STRUCT
hdc DWORD ? ; 用于绘制的句柄
fErase DWORD ? ;如果为非零值则擦除背景,否则不擦除背景
rcPaint DWORD ? ;通过制定左上角和右下角的坐标确定一个要绘制的矩形范围,该矩形单位相对于客户区左上角。
fRestore DWORD ? ;后面三个参数都是系统预留的,编程一般用不到。
fIncUpdate DWORD ?
rgbReserved DWORD ?
PAINTSTRUCT ENDS
完整的程序Fwindow.asm
.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