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之后
RegisterClassEx,Ipwcx
该函数为随后在调用Createwindow函数和CreatewindowEx函数中使用的窗口注册一个窗口类。
Ipwcx:WNDCLASSEX结构的起始地址,在传递给这个函数之前,必须在结构内填充适当的类的属性
CreateWindowEx,dwExStyle,lpClassName,lpWindowName,dwStyle,x,y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam
该函数创建一个具有扩展风格的层叠式窗口、弹出式窗口或子窗口
dwExStyle: 扩展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消息中可以被获取,
ShowWindow,hWnd,nCmdShow
显示窗口
hWnd:窗口句柄nCmdShow:显示参数
UpdateWindow,hWnd
绘制客户区
hWnd:窗口句柄
这时一个窗口就显示出来了。
然后是消息循环
GetMessage -> TranslateMessage -> DispatchMessage