下面先来看一个地地道道的Win32汇编窗口程序。
2。 FirstWindow源代码
读者可以在所带光盘的Chapter04FirstWindow目录中找到源代码,目录里面有两个文件,它们是汇编源文件FirstWindow。asm和nmake工具使用的makefile,汇编源程序如下:
。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 ?
nst
szClassName db 'MyClass';0
szCaptionMain db 'My first Window !';0
szText db 'Win32 Assembly; Simple and powerful !';0
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 代码段
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
de
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 窗口过程
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
_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
来源:电子工业出版社 作者:罗云彬 上一页 回书目 下一页
上一页 回书目 下一页
第4章 第一个窗口程序
4。1 开始了解窗口(3)
让我们打开一个DOS窗口,切换到FistWindow所在的目录,运行环境设置的批处理文件var。bat,再键入nmake编译出FirstWindow。exe,这个程序只有2 560字节,运行后窗口出来了,如图4。3所示。对于这个窗口,用户可以拖动边框去改变大小、按标题栏上的按钮来最大化和最小化,当光标移到边框的时候,会自动变成双箭头……总之,这个窗口包括了一个典型窗口的所有特征。
图4。3 FirstWindow的运行结果
接下来开始分析源代码,看了这三页多的源代码,第一个感觉是什么?是不是想撤退了?笔者刚开始编Win32程序的时候就是这种感觉,可能90%的人有同样的感觉,别急,过了这一关,Win32汇编的入门就成功了一半,所以千万要挺住!有个振奋人心的消息是,这个程序是大部分窗口程序的模板,以后要写一个新的程序,把它拷贝过来再往中间添砖加瓦就是了,功夫一点都不白费。
先静下心来分析一下程序的结构,还看得懂,很好!其实源程序的结构在第3章里已经了解过了,首先是注释……模式定义……include…… 。data数据段,都没有问题,这些已经占去了近40行了,好了,终于是关键的代码段了,统计一下,只剩80行代码了。
分析一下程序的结构,发现入口是start,然后执行了一个_WinMain子程序,完成后就是程序退出的函数ExitProcess,再看_WinMain的结构,前面是顺序下来的几个API:
GetModuleHandle → RtlZeroMemory → LoadCursor → RegisterClassEx
→ CreateWindowEx → ShowWindow → UpdateWindow
从名称上就能看出它们的用途,很明显,窗口是在CreateWindowEx处建立的,ShowWindow则是把窗口显示在屏幕上,这些代码是窗口的建立过程。
接下来,就是一个由3个API组成的循环了:
GetMessage → TranslateMessage → DispatchMessage
很明显,这是和消息有关的循环,因为API名称中都带有Message字样,如果退出这个循环,程序也就结束了,这个循环叫做消息循环。设置_WinMain子程序并不是必须的,可以把_WinMain的所有代码放到主程序中,没有任何影响,之所以这样只是为了将这里使用的变量定义成局部变量,这样可以方便移植。
看了程序的流程,似乎没有什么地方涉及窗口的行为,如改变大小和移动位置的处理等。再看源程序,除了_WinMain,还有一个子程序_ProcWinMain,但除了在WNDCLASSEX结构的赋值中提到过它,好像就没有什么地方要用到这个子程序,起码在自己编写的源代码中没有任何一个地方调用过它。
再看_ProcWinMain,它是一个分支结构处理的子程序,功能是把参数uMsg取出来,根据不同的uMsg执行不同的代码,完了以后就退出了,中间也没有任何东西和主程序有关联。
第一个窗口程序就是由这么两个似乎是风马牛不相及的部分组成的,但它确实能工作,对于写惯了DOS汇编的程序员来说,这似乎不可理解。下面来看看这么一个陌生而奇怪的程序是如何工作的。
3。 窗口程序的运行过程
在屏幕上显示一个窗口的过程一般有以下步骤,这就是主程序的结构流程:
(1)得到应用程序的句柄(GetModuleHandle)。
(2)注册窗口类(RegisterClassEx)。在注册之前,要先填写RegisterClassEx的参数WNDCLASSEX结构。
(3)建立窗口(
小提示:按 回车 [Enter] 键 返回书目,按 ← 键 返回上一页, 按 → 键 进入下一页。
赞一下
添加书签加入书架