/*------------------------------------------------------------
HELLOWIN.C -- Displays "Hello, Windows 98!" in client area
(c) Charles Petzold, 1998
------------------------------------------------------------*/
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("HelloWin") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, // window class name
TEXT (" The Hello Program"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
//showwindow 第一个参数刚刚创建的窗体,第二个参数是从winmain函数中传入的,此处改成了SW_SHOWMAXIMIZED代表最大化显示
ShowWindow (hwnd,SW_SHOWMAXIMIZED) ;
UpdateWindow (hwnd) ;
/* msg变量是型态为 MSG 的结构,型态 MSG在 WINUSER.H中定义如下:
typedef struct tagMSG
{
HWND hwnd ;
UINT message ;
WPARAM wParam ;
LPARAM lParam ;
DWORD time ;
POINT pt ;
}
* POINT 数据型态也是一个结构,它在 WINDEF.H 中定义如下:
typedef struct tagPOINT
{
LONG x ;
LONG y ;
}*/
while (GetMessage (&msg, NULL, 0, 0))
/*GetMessage
GetMessage (&msg, NULL, 0, 0)
这一呼叫传给 Windows一个指标,指向名为 msg的MSG 结构。第二、第三和第四个参数设定为 NULL 或者 0,
表示程序接收它自己建立的所有窗口的所有消息。Windows用从消息队列中取出的下一个消息来填充消息结构
的各个字段,结构的各个字段包括:
hwnd 接收消息的窗口句柄。在 HELLOWIN程序中,这一参数与 CreateWindow 传回的 hwnd
值相同,因为这是该程序拥有的唯一窗口。
message 消息标识符。这是一个数值,用以标识消息。对于每个消息,均有一个对应的标识
符,这些标识符定义于 Windows表头文件(其中大多数在 WINUSER.H 中) ,以前缀 WM( 「window message」 ,
窗口消息)开头。例如,使用者将鼠标光标放在HELLOWIN显示区域之内,并按下鼠标左按钮,Windows就在
消息队列中放入一个消息,该消息的 message 字段等于 WM_LBUTTONDOWN。这是一个常数,其值为0x0201。
wParam 一个32位的「message parameter(消息参数) 」 ,其含义和数值根据消息的不同而不
同。
lParam 一个32 位的消息参数,其值与消息有关。
time 消息放入消息队列中的时间。
pt 消息放入消息队列时的鼠标坐标。
只要从消息队列中取出消息的 message 字段不为 WM_QUIT (其值为0x0012) , GetMessage 就传回一个非零值。
WM_QUIT消息将导致GetMessage 传回 0。*/
{
TranslateMessage (&msg) ;//将 msg结构传给 Windows,进行一些键盘转换
DispatchMessage (&msg) ;
/* DispatchMessage又将 msg结构回传给 Windows。然后,Windows将该消息发送给适当的窗口消息处理程序,让它进 行处理。这也就是说,Windows将呼叫窗口消息处理程序。在HELLOWIN 中,这个窗口消息处理程序就是 WndProe 函 数。处理完消息之后,WndProc 传回到 Windows。此时,Windows还停留在 DispatchMessage 呼叫中。在结束DispatchMessage 呼叫的处理之后,Windows回到HELLOWIN,并且接着从下一个 GetMessage呼叫开始消息循环。*/
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
/*窗口消息处理程序的四个参数与 MSG 结构的前四个字段是相同的。第一个参数 hwnd是接收消息的窗口
的句柄,它与 CreateWindow 函数的传回值相同。对于与HELLOWIN相似的程序(只建立一个窗口),这个参
数是程序所知道的唯一窗口句柄。如果程序是依据同一窗口类别(同时也是同一窗口消息处理程序)建立多个
窗口,则 hwnd标识接收消息的特定窗口。
第二个参数与 MSG 结构中的 message 字段相同,它是标识消息的数值。最后两个参数都是 32 位的消息参数,
提供关于消息的更多信息。这些参数包含每个消息型态的详细信息。有时消息参数是两个存放在一起的 16位
值,而有时消息参数又是一个指向字符串或数据结构的指针。
程序通常不直接呼叫窗口消息处理程序,窗口消息处理程序通常由 Windows本身呼叫。通过呼叫 SendMessage
函数,程序能够直接呼叫它自己的窗口消息处理程序。*/
{
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:
/* WndProc 处理的第二个消息为 WM_PAINT。这个消息在 Windows程序设计中是很重要的。当窗口显示区域的一
部分显示内容或者全部变为「无效」,以致于必须「更新画面」时,将由这个消息通知程序。
显示区域的显示内容怎么会变得无效呢?在最初建立窗口的时候,整个显示区域都是无效的,因为程序还没有
在窗口上画什么东西。第一条 WM_PAINT 消息(通常发生在 WinMain 中呼叫UpdateWindow 时)指示窗口消息
处理程序在显示区域上画一些东西。
在使用者改变HELLOWIN窗口的大小后,显示区域的显示内容重新变得无效。读者应该还记得,HELLOWIN 中
wndclass结构的 style字段设定为标志 CS_HREDRAW和 CS_VREDRAW,这样的格式设定指示 Windows,在窗口
大小改变后,就把整个窗口显示内容当成无效。然后,窗口消息处理程序将收到一条 WM_PAINT 消息。
当使用者将 HELLOWIN 最小化,然后再次将窗口恢复为以前的大小时,Windows 将不会保存显示区域的内容。
在图形环境下,窗口显示区域涉及的数据量很大。因此,Windows令窗口无效,窗口消息处理程序接收一条
WM_PAINT 消息,并自动恢复其窗口的内容。
在移动窗口以致其相互重迭时,Windows不保存一个窗口中被另一个窗口所遮盖的内容。在这一部分不再被遮
盖之后,它就被标志为无效。窗口消息处理程序接收到一条 WM_PAINT 消息,以更新窗口的内容。
对 WM_PAINT的处理几乎总是从一个 BeginPaint呼叫开始:
hdc = BeginPaint (hwnd, &ps) ;
而以一个 EndPaint呼叫结束:
EndPaint (hwnd, &ps) ;
在这两个呼叫中,第一个参数都是程序的窗口句柄,第二个参数是指向型态为 PAINTSTRUCT 的结构指针。
PAINTSTRUCT结构中包含一些窗口消息处理程序,可以用来更新显示区域的内容。我们将在下一章中讨论该结
构的各个字段。现在我们只在BeginPaint和 EndPaint函数中用到它。*/
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) ;//该函数在程序的消息队列中插入一个 WM_QUIT 消息。前面提到过,GetMessage 对于除了 WM_QUIT 之外的从消息队列中取出的所有消息都传回非 0值。而当GetMessage 得到一个 WM_QUIT 消息时,它传回 0。这将导 致WinMain 退出消息循环,并终止程序。然后程序执行下面的叙述:
return 0 ;
}
//有时候,DefWindowProc处理完消息后会产生其它的消息。例如,假设使用者执行 HELLOWIN,并且使用者最
//终单击了 Close按钮,或者假设用键盘或鼠标从系统菜单中选择了 Close, DefWindowProc 处理这一键盘或者
//鼠标输入, 在检测到使用者选择了 Close选项之后, 它给窗口消息处理程序发送一条 WM_SYSCOMMAND消息。WndProc这个消息传给DefWindowProc。DefWindowProc 给窗口消息处理程序发送一条 WM_CLOSE消息来响
//应之。WndProc 再次将它传给 DefWindowProc。DestroyWindow呼叫DestroyWindow 来响应这条 WM_CLOSE 消
//息。DestroyWindow导致Windows给窗口消息处理程序发送一条 WM_DESTROY 消息。WndProc 再呼叫
//PostQuitMessage,将一条WM_QUIT消息放入消息队列中,以此来响应此消息。这个消息导致 WinMain中的消
//息循环终止,然后程序结束。
return DefWindowProc (hwnd, message, wParam, lParam) ;
}