书中示例代码如下:
1 #include <windows.h>
2
3 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
4
5 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
6 PSTR szCmdLine, int iCmdShow)
7 {
8 static TCHAR szAppName[] = TEXT ("HelloWin") ;
9 HWND hwnd ;
10 MSG msg ;
11 WNDCLASS wndclass ;
12
13 wndclass.style = CS_HREDRAW | CS_VREDRAW ;
14 wndclass.lpfnWndProc = WndProc ;
15 wndclass.cbClsExtra = 0 ;
16 wndclass.cbWndExtra = 0 ;
17 wndclass.hInstance = hInstance ;
18 wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
19 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
20 wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
21 wndclass.lpszMenuName = NULL ;
22 wndclass.lpszClassName = szAppName ;
23
24 if (!RegisterClass (&wndclass))
25 {
26 MessageBox (NULL, TEXT ("This program requires Windows NT!"),
27 szAppName, MB_ICONERROR) ;
28 return 0 ;
29 }
30
31 hwnd = CreateWindow (szAppName, // window class name
32 TEXT ("The Hello Program"), // window caption
33 WS_OVERLAPPEDWINDOW, // window style
34 CW_USEDEFAULT, // initial x position
35 CW_USEDEFAULT, // initial y position
36 CW_USEDEFAULT, // initial x size
37 CW_USEDEFAULT, // initial y size
38 NULL, // parent window handle
39 NULL, // window menu handle
40 hInstance, // program instance handle
41 NULL) ; // creation parameters
42
43 ShowWindow (hwnd, iCmdShow) ;
44 UpdateWindow (hwnd) ;
45
46 while (GetMessage (&msg, NULL, 0, 0))
47 {
48 TranslateMessage (&msg) ;
49 DispatchMessage (&msg) ;
50 }
51 return msg.wParam ;
52 }
53
54 LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
55 {
56 HDC hdc ;
57 PAINTSTRUCT ps ;
58 RECT rect ;
59
60 switch (message)
61 {
62 case WM_CREATE:
63 PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
64 return 0 ;
65
66 case WM_PAINT:
67 hdc = BeginPaint (hwnd, &ps) ;
68
69 GetClientRect (hwnd, &rect) ;
70
71 DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect,
72 DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
73
74 EndPaint (hwnd, &ps) ;
75 return 0 ;
76
77 case WM_DESTROY:
78 PostQuitMessage (0) ;
79 return 0 ;
80 }
81 return DefWindowProc (hwnd, message, wParam, lParam) ;
82 }
在WNDCLASS结构中最重要的两个字段是第二个和最后一个,第二个字段(lpfnWndProc) 是依据这个类别来建立的所有窗口所使用的窗口消息处理程序的地址。
1.wndclass.style = CS_HREDRAW | CS_VREDRAW ;
窗口类别样式,,每当窗口的水平方向大小(CS_HREDRAW)或者垂直方向大小(CS_VREDRAW)改变之后,窗口要完全重画。CS_HREDRAW ,CS_VREDRAW等在WINUSER.H中定义。
2.wndclass.lpfnWndProc = WndProc ;
将这个窗口类别的窗口消息处理程序设定为WndProc。
3.wndclass.cbClsExtra = 0 ;4.wndclass.cbWndExtra = 0 ;3,4 参数用于在窗口类别结构和Windows内部保存的窗口结构中预留一些额外空间,程序可以根据需要来使用预留的空间,将值设定为0。
否则,将被当成「预留的字节数」。5.wndclass.hInstance = hInstance
程序的执行实体句柄。
6.wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION)
加载图标。。图标是一个小的位图图像,它对使用者代表程序,将出现在Windows工作列中和窗口的标题列的左端。
LoadIcon的第一个参数为NULL,表示取得预先定义图示的句柄。在加载自定义的图标时,图标应该存放在磁盘上.exe程序文件中,第一个参数就应
该被设定为程序的执行实体句柄hInstance。
第二个参数代表图示。图示ID在WINUSER。H中定义。例如: IDI_APPLICATION。
7.wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
加载光标。
使用方法与LoadIcon类似。
8.wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
设定窗口背景颜色
GetStockObject 检索预定义的备用笔、刷子、字体或者调色板的句柄。
9 wndclass.lpszMenuName = NULL ;
指定窗口类别菜单。
为NULL,表示没有应用程序菜单。
10 wndclass.lpszClassName = szAppName
给出窗口类别的文字名称
注册窗口
RegisterClass(&wndclass)
需要配置内存,以保存窗口类别的信息。
建立窗口CreateWindow ( szAppName,
TEXT ("The Hello Program"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL)
「window class name」的参数是szAppName,它含有字符串「HelloWin」-这是程序注册的窗口类别名称。这就是我们建立的窗口联结窗口类别的方式。
「window caption」 标题显示的内容。
「window style」 窗口的风格。WS_OVERLAPPEDWINDOW 可以在WinUser.h 中查看到它的定义。描述了窗口包含的元素等信息。还有其他几种。例如WS_POPUPWINDOW,WS_CHILDWINDOW等。
「initial x position」 「initial y position」「initial x size」「initial y size」 用于描述窗口相对于屏幕左上角的位置,以及窗口的大小。参数都是CW_USEDEFAULT,表明希望Windows使用内定尺寸
「parent window handle」 父窗口句柄。通常,如果窗口之间存在有父子关系,则子窗口总是出现在父窗口的上面。
「window menu handle」 窗口菜单句柄。
「program instance handle」 程序执行实体句柄
「creation parameters」 建立参数,用这个参数存取稍后程序中可能引用到的数据。
显示窗口
ShowWindow(hwnd, iCmdShow)
在CreateWindow呼叫传回之后,Windows内部已经建立了这个窗口。这就是说,Windows已经配置了一块内存,用来保存在CreateWindow呼叫中指定窗口的全部信息跟一些其它信息,而Windows稍后就是依据窗口句柄找到这些信息的。然而,光是这样子,窗口并不会出现在视讯显示器上,需要调用函数ShowWindow。
第一个参数是刚刚用CreateWindow建立的窗口句柄。
第二个参数是作为参数传给WinMain的iCmdShow。它确定最初如何在屏幕上显示窗口,是一般大小、最小化还是最大化。
指示窗口自我更新 UpdateWindow(hwnd)它经由发送给窗口消息处理程序(即HELLOWIN.C中的WndProc函数)一个WM_PAINT消息做到这一点。
Windows为当前执行的每个Windows程序维护一个「消息队列」。在发生输入事件之后,Windows将事件转换为一个「消息」并将消息放入程序的消息队列中。
while (
GetMessage (&msg, NULL, 0, 0)) //只要从消息队列中取出消息的message字段不为WM_QUIT(其值为0x0012),GetMessage就传回一个非零值。
//WM_QUIT消息将导致GetMessage传回0。
{
TranslateMessage (&msg) ;//将msg结构传给Windows,进行一些键盘转换
DispatchMessage (&msg) ;//Windows该消息发送给适当的窗口消息处理程序,让它进行处理
}
typedef struct tagMSG
{
HWND hwnd ; //接受消息的窗口句柄
UINT message ; //消息。是一些数值。在WinUser.h中定义。如 WM_LBUTTONDOWN,其值为0x0201。。
WPARAM wParam ; //一个32位的「message parameter(消息参数)」,其含义和数值根据消息的不同而不同。
LPARAM lParam ; //一个32位的消息参数,其值与消息有关
DWORD time ; //消息放入消息队列中的时间。
POINT pt ; //消息放入消息队列时的鼠标坐标。
}MSG, * PMSG ;
typedef struct tagPOINT
{
LONG x ;
LONG y ;
}
窗口消息处理程序总是定义为如下形式:
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
第一个参数hwnd是接收消息的窗口的句柄
第二个参数与MSG结构中的message字段相同
最后两个参数都是32位的消息参数,提供关于消息的更多信息。这些参数包含每个消息型态的详细信息。有时消息参数是两个存放在一起的16位值,而有时消息参数又是一个指向字符串或数据结构的指针。
PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) 播放声音文件
第一个参数是声音文件的名称。第二个参数只有当声音文件是一种资源时才被使用。第三个参数指定一些选项,指定第一个参数是一个文件名,并且异步地播放声音。
WM_PAINT的处理几乎总是从一个BeginPaint呼叫开始:而以一个EndPaint呼叫结束:
hdc =
BeginPaint (hwnd, &ps) ; // 第一个参数都是程序的窗口句柄,第二个参数是指向型态为PAINTSTRUCT的结构指针。
// PAINTSTRUCT结构中包含一些窗口消息处理程序,可以用来更新显示区域的内容
EndPaint (hwnd, &ps) ; // EndPaint释放设备内容句柄,使之不再有效。
GetClientRect (hwnd, &rect) ;
第一个参数是程序窗口的句柄。第二个参数是一个指标,指向一个RECT型态的rectangle结构。该结构有四个LONG字段,分别为left、top、right和bottom。
DrawText ( hdc, TEXT ("Hello, Windows 98!"), -1, &rect,DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
DrawText可以输出文字(正如其名字所表明的一样)。由于该函数要输出文字,第一个参数是从BeginPaint传回的设备内容句柄,第二个参数是要输出的文字,第三个参数是 -1,指示字符串是以字节0终结的。DrawText最后一个参数是一系列位旗标,它们均在WINUSER.H中定义(虽然由于其显示输出的效果,使得DrawText像一个GDI函数呼叫,但它确实因为相当高级的画图功能而成为User模块的一部分。旗标指示了文字必须显示在一行上,水平方向和垂直方向都位于第四个参数指定的矩形中央。
PostQuitMessage (0) ;
该函数在程序的消息队列中插入一个WM_QUIT消息。
Windows编程
#include <windows.h>
WINDOWS.H是主要的含入文件,它包含了其它Windows表头文件,这些表头文件的某些也包含了其它表头文件。这些表头文件中最重要的和最基本的是:
WINDEF.H 基本型态定义。
WINNT.H 支持Unicode的型态定义。
WINBASE.H Kernel函数。
WINUSER.H 使用者接口函数。
WINGDI.H 图形设备接口函数。
WINDEF.H 本身就包含WINNT.H。
WINNT.H定义了新的数据型态,称作CHAR和WCHAR:
typedef char CHAR ;
typedef wchar_t WCHAR ;
在WINNT.H文件中定义了可用做8位字符串指针的六种数据型态和四个可用做const 8位字符串指针的数据型态
typedef CHAR * PCHAR, * LPCH, * PCH, * NPSTR, * LPSTR, * PSTR ;
typedef CONST CHAR * LPCCH, * PCCH, * LPCSTR, * PCSTR ;
前缀N和L表示「near」和「long」,指的是16位Windows中两种大小不同的指标。在Win32中near和long指标没有区别。
类似地,WINNT.H定义了六种可作为16位字符串指针的数据型态和四种可作为const 16位字符串指针的数据型态:
typedef WCHAR * PWCHAR, * LPWCH, * PWCH, * NWPSTR, * LPWSTR, * PWSTR ;
typedef CONST WCHAR * LPCWCH, * PCWCH, * LPCWSTR, * PCWSTR ;
WINNT.H表头文件还定义了一个宏,该宏将L添加到字符串的第一个引号前。如果定义了UNICODE标识符,则一个称作 __TEXT的宏定义如下:
#define __TEXT(quote) L##quote
如果没有定义标识符UNICODE,则像这样定义__TEXT宏:
#define __TEXT(quote) quote
此外, TEXT宏可这样定义:
#define TEXT(quote) __TEXT(quote)
Microsoft Visual C++包含的TCHAR.H头文件
如果定义了名为_UNICODE的标识符,并且程序中包含了TCHAR.H表头文件,那么_tcslen就定义为wcslen:
#define _tcslen wcslen
如果没有定义UNICODE,则_tcslen定义为strlen:
#define _tcslen strlen
如果定义了_UNICODE标识符;
#define __T(x) L##x
如果没有定义_UNICODE标识符;
#define __T(x) x
此外,还有两个宏与__T定义相同:
#define _T(x) __T(x)
#define _TEXT(x) __T(x)
在Windows程序中不能使用printf,在Windows程序中可使用fprintf,而不是printf。
可以使用sprintf及sprintf系列中的其它函数来显示文字。这些函数除了将内容格式化输出到函数第一个参数所提供的字符串缓冲区以外,其功能与printfI相同。