第一个windows窗口
1 #include <windows.h> 2 /* Displays "Hello, World!" in client area */ 3 4 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);//窗口过程函数 5 6 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 7 PSTR szCmdLine, int iCmdShow) 8 { 9 static TCHAR szAppName[] = TEXT("HelloWin");//窗口类名称 10 char string[] = "Hello World!"; 11 HWND hwnd;//窗口句柄 12 MSG msg;//消息结构 13 WNDCLASS wndclass;//定义窗口类结构体变量 14 /*下面代码填充窗口类信息*/ 15 wndclass.style = CS_HREDRAW | CS_VREDRAW;//窗口样式 16 wndclass.lpfnWndProc = WndProc;//过程函数 17 wndclass.cbClsExtra = 0;//扩展字段 18 wndclass.cbWndExtra = 0;//扩展字段 19 wndclass.hInstance = hInstance;//当前实例句柄 20 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);//设置程序图标 21 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);//设置鼠标 22 wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//用白色填充背景 23 wndclass.lpszMenuName = NULL;//菜单 24 wndclass.lpszClassName = szAppName;//类名 25 /*注册窗口类*/ 26 if (!RegisterClass(&wndclass)) 27 { 28 MessageBox(NULL, TEXT("This program requires Windows NT!"), 29 szAppName, MB_ICONERROR); 30 return 0; 31 } 32 //创建窗口create window 33 hwnd = CreateWindow(szAppName, // window class name类名 34 TEXT("The Hello Program"), // window caption标题 35 WS_OVERLAPPEDWINDOW, // window style样式 36 CW_USEDEFAULT,// initial x position 横坐标原点 37 CW_USEDEFAULT,// initial y position 纵坐标原点 38 CW_USEDEFAULT,// initial x size 39 CW_USEDEFAULT,// initial y size 40 NULL, // parent window handle父窗口句柄 41 NULL, // window menu handle菜单句柄 42 hInstance, // program instance handle当前实例句柄 43 NULL); // creation parameters 传递给窗口 WM_CREATE消息的值的指针 一般为NULL 44 ShowWindow(hwnd, iCmdShow); 45 UpdateWindow(hwnd); 46 //消息循环,一直停在这里,退出消息循环就表示程序结束了 47 while (GetMessage(&msg, NULL, 0, 0)) 48 { 49 TranslateMessage(&msg);//翻译 50 DispatchMessage(&msg);//分发 51 } 52 return msg.wParam; 53 } 54 /* 消息处理函数 */ 55 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 56 { 57 HDC hdc; 58 PAINTSTRUCT ps; 59 RECT rect; 60 switch (message) 61 { 62 case WM_PAINT: 63 hdc = BeginPaint(hwnd, &ps); 64 GetClientRect(hwnd, &rect); 65 DrawText(hdc, TEXT("Hello World!"), -1, &rect, 66 DT_SINGLELINE | DT_CENTER | DT_VCENTER); 67 EndPaint(hwnd, &ps); 68 return 0; 69 //发送结束请求,里面的参数为退出码 70 case WM_DESTROY: 71 PostQuitMessage(0); 72 return 0; 73 } 74 //调用默认的过程函数 75 return DefWindowProc(hwnd, message, wParam, lParam); 76 }
首先是通过WNDCLASS这个结构体来告诉系统我们要创建一个窗口。
1 ypedef struct tagWNDCLASSA { 2 UINT style; 3 WNDPROC lpfnWndProc; 4 int cbClsExtra; 5 int cbWndExtra; 6 HINSTANCE hInstance; 7 HICON hIcon; 8 HCURSOR hCursor; 9 HBRUSH hbrBackground; 10 LPCSTR lpszMenuName; 11 LPCSTR lpszClassName; 12 } WNDCLASSA, *PWNDCLASSA, NEAR *NPWNDCLASSA, FAR *LPWNDCLASSA;
设置结构内的不同的字段,调用RegisterClass函数来告诉系统,要注册一个这样的窗口类型。
接下来就是通过调用函数CreateWindow创建一个刚才注册的窗口类型。
1 #define CreateWindowA(lpClassName, lpWindowName, dwStyle, x, y, 2 nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) 3 CreateWindowExA(0L, lpClassName, lpWindowName, dwStyle, x, y, 4 nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) 5 #define CreateWindowW(lpClassName, lpWindowName, dwStyle, x, y, 6 nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) 7 CreateWindowExW(0L, lpClassName, lpWindowName, dwStyle, x, y, 8 nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) 9 #ifdef UNICODE 10 #define CreateWindow CreateWindowW 11 #else 12 #define CreateWindow CreateWindowA 13 #endif // !UNICODE
创建好的窗口还没有显示,这就要调用函数ShowWindow来显示,以及UpdateWindow来更新。
ShowWindow( _In_ HWND hWnd, _In_ int nCmdShow); UpdateWindow( _In_ HWND hWnd);
消息循环。GetMessage函数从消息队列中取得消息。TranslateMessage函数 转移某些键盘消息。DispatchMessage函数将消息发送给窗口消息处理程序。
再来看WndProc这个函数内部。BeginPaint 开始绘制窗口。GetClientRect 取得窗口显示区域的大小。DrawText 显示字符串。EndPaint 结束绘制窗口。PostQuitMessage 在消息队列中插入一个「退出程序」消息。DefWindowProc 执行内定的消息处理。
程序通常不直接呼叫窗口消息处理程序,窗口消息处理程序通常由Windows本身呼叫。通过呼叫SendMessage函数,程序能够直接呼叫它自己的窗口消息处理程序。
处理消息。
WndProc处理的第一个消息为WM_PAINT。当窗口显示区域的一部分显示内容或者全部变为「无效」,以致于必须「更新画面」时,将由这个消息通知程序。wndclass结构的style字段设定为标志CS_HREDRAW和CS_VREDRAW,这样的格式设定指示Windows,改变窗口的大小、窗口最小化以及移动窗口后,显示区域的显示内容重新变得无效。
GetClientRect (hwnd, &rect) ;
第一个参数是程序窗口的句柄。第二个参数是一个指标,指向一个RECT型态的rectangle结构。该结构有四个LONG字段,分别为left、top、right和bottom。GetClientRect将这四个字段设定为窗口显示区域的尺寸。left和top字段通常设定为0,right和bottom字段设定为显示区域的宽度和高度(像素点数)。
DrawText(hdc, TEXT("Hello World!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
DrawText可以输出文字(正如其名字所表明的一样)。由于该函数要输出文字,第一个参数是从BeginPaint传回的设备内容句柄,第二个参数是要输出的文字,第三个参数是 -1,指示字符串是以字节0终结的。
DrawText最后一个参数是一系列位旗标,它们均在WINUSER.H中定义(虽然由于其显示输出的效果,使得DrawText像一个GDI函数呼叫,但它确实因为相当高级的画图功能而成为User模块的一部分。此函数在/Platform SDK/Graphics and Multimedia Services/GDI/Fonts and Text中说明)。旗标指示了文字必须显示在一行上,水平方向和垂直方向都位于第四个参数指定的矩形中央。因此,这个函数呼叫将让字符串「Hello World!」显示在显示区域的中央。
一旦显示区域变得无效(正如在改变大小时所发生的情况一样),WndProc就接收到一个新的WM_PAINT消息。WndProc通过呼叫GetClientRect取得变化后的窗口大小,并在新窗口的中央显示文字。
case WM_DESTROY: PostQuitMessage(0);
WM_DESTROY消息指示,Windows正在根据使用者的指示关闭窗口。单击Close按钮或者在程序的系统菜单上选择 Close时发生的。
return DefWindowProc(hwnd, message, wParam, lParam);
结构的wParam字段是传递给PostQuitMessage函数的值(通常是0)。然后return叙述将退出WinMain并终止程序。