_WinMain结构

    start:
    		call	_WinMain
    		invoke	ExitProcess,NULL
    		end		start

一个窗口执行的过程就是调用_WinMain子程序,完成后调用ExitProcess函数退出。

** _WinMain的结构 **

    _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

_WinMain的结构就是前面是几个API按顺序调用

GetModuleHandle -> RtlZeroMemory -> LoadCursor -> RegisterClassEx -> CreateWindowEx -> ShowWindow -> UpdateWindow

执行完成之后一个窗口就创建完成了。然后是3个API组成的消息循环

GetMessage -> TranslateMessage -> DispatchMessage

几个函数的详细介绍

GetModuleHandle,lpModuleName

函数的作用是返回指定模块名的句柄,
返回的句柄值存放在寄存器eax中。
lpModuleName 是一个指向含有模块名称字符串的指针,如果为NULL,则返回本模块的句柄。上面的例子就是这样用的。

RtlZeroMemory,Destination,Length

内存管理函数,其作用是用0来填充一块内存区域(将一段内存空间清零),如果不清0,这段内存空间是不可掌控的数据,防止引起错误。
Destination :指向一块准备用0来填充的内存区域的开始地址。
Length :准备用0来填充的内存区域的大小,按字节来计算。

LoadCursor,hInstance,lpCursorName

从一个与应用事例相关的可执行文件中载入指定的光标资源
hInstance 标识一个模块句柄,它的可执行文件包含要载入的光标。
lpCursorName 指向以NULL结束的字符串的指针,该字符串存有等待载入的光标资源名
要使用Win32预定义的一个光标,应用程序必须把hlnstance参数设为NULL,并把IpCursorName设为如下值之一

参数值 含义
IDC_APPSTARTING 标准和小沙漏,圆圈,忙箭头
IDC_ARROW 标准的箭头
IDC_CROSS 十字
IDC_HAND 手型
IDC_HELP 箭头和问号
IDC_IBEAM I型光标
IDC_ICON 废弃的标记
IDC_NO 禁止圈
IDC_SIZE 废弃,现用IDC_SIZEALL
IDC_SIZEALL 四方向的十字箭头
IDC_SIZENESW 东北部和西南部的双尖箭头
IDC_SIZENS 北部和南部的双尖箭头
IDC_SIZENWSE 西北部和东南部的双尖箭
IDC_SIZEWE 东部和西部的双尖箭头
IDC_UPARROW 垂直向上的箭头
IDC_WAIT 沙漏,圆圈,忙箭头

下一个函数应该是RegisterClassEx了,在这之前,我们需要先填充适当的WNDCLASSEX结构的属性

WNDCLASSEX 结构
有密码就是还没写完,完成之后会去除密码的

已经了解WNDCLASSEX之后

RegisterClassExIpwcx

该函数为随后在调用Createwindow函数和CreatewindowEx函数中使用的窗口注册一个窗口类。
Ipwcx:WNDCLASSEX结构的起始地址,在传递给这个函数之前,必须在结构内填充适当的类的属性

CreateWindowEx,dwExStyle,lpClassName,lpWindowName,dwStyle,x,y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam

该函数创建一个具有扩展风格的层叠式窗口、弹出式窗口或子窗口
dwExStyle: 扩展Windows窗口的样式 具体请看windows扩展样式表
lpClassName: 建立窗口时使用的WNDCLASSEX类窗口指针或windows预定义的类名
lpWindowName: 标题栏字符,若为空,则标题栏为空白
dwStyle: 详见样式表
x,y,nWidth,nHeight:左上角的位置,x,y坐标(默认可指定为CW_USEDEFAULT), 窗口的宽、高(默认可指定为CW_USEDEFAULT)。
hWndParent:指向被创建窗口的父窗口或所有者窗口的句柄。若要创建一个子窗口或一个被属窗口,需提供一个有效的窗口句柄。这个参数对弹出式窗口是可选的。
hMenu:菜单句柄,或依据窗口风格指明一个子窗口标识。对于层叠或弹出式窗口,hMenu指定窗口使用的菜单:如果使用了菜单类,则hMenu可以为NULL。对于子窗口,hMenu指定了该子窗口标识(一个整型量),一个对话框使用这个整型值将事件通知父类。应用程序确定子窗口标识,这个值对于相同父窗口的所有子窗口必须是唯一的。
hInstance:模块句柄,和注册窗口类时一样,指定了窗口所属的程序模块。
lpParam: 指向一个欲传给窗口的参数,这个参数在WM_CREAT消息中可以被获取,

ShowWindowhWnd,nCmdShow

显示窗口
hWnd:窗口句柄
nCmdShow:显示参数

UpdateWindow,hWnd

绘制客户区
hWnd:窗口句柄

这时一个窗口就显示出来了。

然后是消息循环

GetMessage -> TranslateMessage -> DispatchMessage

原文地址:https://www.cnblogs.com/nightwindnw/p/winmain_structure.html