invoke translatemessage, addr msg
invoke dispatchmessage, addr msg
.endw
mov eax,msg.wparam
ret
winmain endp
wndproc proc hwnd:hwnd, umsg:uint, wparam:wparam, lparam:lparam
local hdc:hdc
local ps:paintstruct
local rect:rect
.if umsg==wm_destroy
invoke postquitmessage,null
.elseif umsg==wm_paint
invoke beginpaint,hwnd, addr ps
mov hdc,eax
invoke getclientrect,hwnd, addr rect
invoke drawtext, hdc,addr ourtext,-1, addr rect, \
dt_singleline or dt_center or dt_vcenter
invoke endpaint,hwnd, addr ps
.else
invoke defwindowproc,hwnd,umsg,wparam,lparam
ret
.endif
xor eax, eax
ret
wndproc endp
end start
分析:
这里的大多数代码和第三课中的一样。我只解释其中一些不相同的地方。
local hdc:hdc
local ps:paintstruct
local rect:rect
这些局部变量由处理 wm_paint 消息中的 gdi 函数调用。hdc 用来存放调用 beginpaint 返回的“设备环境”句柄。ps 是一个 paintstruct 数据类型的变量。通常您不会用到其中的许多值,它由 windows 传递给 beginpaint,在结束绘制后再原封不动的传递给 endpaint。rect 是一个 rect 结构体类型参数,它的定义如下:
rect struct left long ?
top long ?
right long ?
bottom long ?
rect ends
left 和 top 是正方形左上角的坐标。right 和 bottom 是正方形右下角的坐标。客户区的左上角的坐标是 x=0,y=0,这样对于 x=0,y=10 的坐标点就在它的下面。
invoke beginpaint,hwnd, addr ps
mov hdc,eax
invoke getclientrect,hwnd, addr rect
invoke drawtext, hdc,addr ourtext,-1, addr rect, \
dt_singleline or dt_center or dt_vcenter
invoke endpaint,hwnd, addr ps
在处理 wm_paint 消息时,您调用beginpaint函数,传给它一个窗口句柄和未初始化的 paintstruct 型参数。调用成功后在 eax 中返回“设备环境”的句柄。下一次,调用 getclientrect 以得到客户区的大小,大小放在 rect 中,然后把它传给 drawtext。drawtext 的语法如下:
drawtext proto hdc:hdc, lpstring:dword, ncount:dword, lprect:dword, uformat:dword
drawtext是一个高层的调用函数。它能自动处理像换行、把文本放到客户区中间等这些杂事。所以您只管集中精力“绘制”字符串就可以了。我们会在下一课中讲解低一层的函数 textout,该函数在一个正方形区域中格式化一个文本串。它用当前选择的字体、颜色和背景色。它处理换行以适应正方形区域。它会返回以设备逻辑单位度量的文本的高度,我们这里的度量单位是像素点。让我们来看一看该函数的参数:
- hdc: “设备环境”的句柄。
- lpstring:要显示的文本串,该文本串要么以null结尾,要么在ncount中指出它的长短。
- ncount:要输出的文本的长度。若以null结尾,该参数必须是-1。
- lprect: 指向要输出文本串的正方形区域的指针,该方形必须是一个裁剪区,也就是说超过该区域的字符将不能显示。
- uformat:指定如何显示。我们可以用 or 把以下标志或到一块:
- dt_singleline:是否单行显示。
- dt_center:是否水平居中。
- dt_vcenter :是否垂直居中。
结束绘制后,必须调用 endpaint 释放“设备环境”的句柄。 好了,现在我们把“绘制”文本串的要点总结如下:
- 必须在开始和结束处分别调用 beginpaint 和 endpaint;
- 在 beginpaint 和 endpaint 之间调用所有的绘制函数;
- 如果在其它的消息处理中重新绘制客户区,您可以有两种选择:
(1)用getdc和releasedc代替beginpaint和endpaint;