窗口过程函数举例
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_CREATE:
PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
消息一:WM_CREATE
窗口过程接收的第一个消息——也是WndProc(窗口过程函数)选择处理的第一个消息——是VM_CREATE,当Windows在WinMain中处理CreateWindow函数时,WndProc接收这个消息。即当调用CreateWindow时,Windows将做一些它必须做的工作。在这些工作中,Windows调用WndProc,将第一个参数设置为窗口句柄,第二个参数设置为WM_CREATE。WndProc处理WM_CREATE消息,并将控制返回给Windows。然后返回到WinMain中进行下一步处理。
消息二:WM_PAINT
WndProc处理的第二个消息,这个消息在Windows程序设计中是很重要的。当窗口客户区域的一部分或者全部变为“无效”,以致于必须“刷新”时,将由这个消息通知程序。
客户区域怎么会变得无效呢?在最初创建窗口的时候,整个客户区域都是无效的,因为程序还没有在窗口止画什么东西。第一个WM_PAINT消息(通常发生在WinMain中调用UpdateWindow时)指示窗口过程在客户区域上画一些东西。
对WM_PAINT的处理几乎总是从一个BeginPant调用开始:
hdc=BeginPaint(hwnd,&ps);而以一个EndPaint调用结束:EndPaint(hwnd,&ps);
在这两个调用中,第一个参数都是程序的窗口句柄,第二个参数是指向类型为PAINTSTRUCT的结构指针。PAINTSTRUCT结构中包含一些窗口过程,可以用来刷新客户区域的内容。(以后讨论)
在调用完BeginPaint后,WndProc接着调用GetClientRect(hwnd,&rect),第一个参数是程序窗口的句柄,第二个参数是一个 指针,指向一个RECT类型的rectangle结构,该结构有4个LONG域,分别为left,top,right和bottom。GetClientRect将这4个域设置为窗口客户区域尺寸。left和top域通常设置为0,right和bottom域设置为客户区域的宽度和高度(像素点数)
(注:如果窗口过程不处理WM_PAINT消息(这是非常少见的情况),它们必须被传送给DefWindowProc。DefWindowProc只是依次调用BeginPaint和EndPaint,以使客户区域有效。)
DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect,DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
其中DrawText可以输出文本,由于该函数要输出文本,第一个参数是从BeginPaint返回的设备描述表句柄,第二个参数是要输出的文本,第三个参数是-1,指示文本串是以字节0终结的。最后一个参数是一系列位标志,它们均在WINUSER.H中定义,如下所示
/*
* DrawText() Format Flags
*/
#define DT_TOP 0x00000000
#define DT_LEFT 0x00000000
#define DT_CENTER 0x00000001
#define DT_RIGHT 0x00000002
#define DT_VCENTER 0x00000004
#define DT_BOTTOM 0x00000008
#define DT_WORDBREAK 0x00000010
#define DT_SINGLELINE 0x00000020
#define DT_EXPANDTABS 0x00000040
#define DT_TABSTOP 0x00000080
#define DT_NOCLIP 0x00000100
#define DT_EXTERNALLEADING 0x00000200
#define DT_CALCRECT 0x00000400
#define DT_NOPREFIX 0x00000800
#define DT_INTERNAL 0x00001000
#if(WINVER >= 0x0400)
#define DT_EDITCONTROL 0x00002000
#define DT_PATH_ELLIPSIS 0x00004000
#define DT_END_ELLIPSIS 0x00008000
#define DT_MODIFYSTRING 0x00010000
#define DT_RTLREADING 0x00020000
#define DT_WORD_ELLIPSIS 0x00040000
typedef struct tagDRAWTEXTPARAMS
{
UINT cbSize;
int iTabLength;
int iLeftMargin;
int iRightMargin;
UINT uiLengthDrawn;
} DRAWTEXTPARAMS, FAR *LPDRAWTEXTPARAMS;
#endif /* WINVER >= 0x0400 */
消息三:WM_DESTROY消息
是另一个重要消息,它指示,Windows正在根据用户输入的命令来清除窗口。该消息是用户单击Close按钮或者在程序的系统菜单上选择Close时发生的。本例通过调用PostQuitMessage (0) ;以标准方式响应WM_DESTORY消息,该函数在程序的消息队列中插入一个WM_QUIT消息。而GetMessage取到一个WM_QUIT消息时,它返回0,这导致WinMain退出消息循环,并终止程序,然后(指WinMain函数)程序执行 return msg.wParam ;其中结构的wParam域是传递给PostQuitMessage函数的值(通常是0).然后返回语句将退出WinMain并终止程序。