1. 程式人生 > >(Windows程式設計)視窗的誕生

(Windows程式設計)視窗的誕生

    相對於DOS程式的main函式,Windows應用程式也有一個入口點函式--WinMain。當作業系統啟動一個程式時,它將呼叫程式的WinMain函式開始執行程式碼;當WinMain函式返回時,應用程式就結束了。

視窗的誕生

  • 設計視窗類:Windows是基於視窗的作業系統,下圖顯示了一個普通的Windows視窗:

             作業系統通過視窗資料結構來管理視窗,該資料結構包含了一個視窗的所有資訊,視窗資料結構定義如下:
typedef struct _WNDCLASS {
UINT style; 					// 視窗型別
WNDPROC lpfnWndProc; 		<span style="white-space:pre">		</span>//視窗處理函式
int cbClsExtra; 				//視窗擴充套件
int cbWndExtra; 				//視窗例項擴充套件
HINSTANCE hInstance; 		<span style="white-space:pre">		</span>//例項控制代碼
HICON hIcon; <span style="white-space:pre">					</span>//視窗的最小化圖示
HCURSOR hCursor; <span style="white-space:pre">				</span>//視窗滑鼠游標
HBRUSH hbrBackground; <span style="white-space:pre">				</span>//視窗背景色
LPCTSTR lpszMenuName; <span style="white-space:pre">				</span>//視窗選單
LPCTSTR lpszClassName;<span style="white-space:pre">				</span>// 視窗類名
} WNDCLASS


     引數說明:      style:指定類風格,這些風格可以通過按位或操作組合起來。(CS_HREDRAW、CS_VREDRAW、CS_BYTEALIGNCLIENT......)      lpfnWndProc:指向一個視窗函式。函式原型為: LRESULT CALLBACK WindowProc( HWNDhwnd, UINTuMsg,  WPARAM, LPARAM);//視窗函式由系統呼叫,響應不同的訊息,通常為一個        switch語句塊。      hbrBackground:背景畫刷,是HBRUSH型別。hbrBackground欄位必須是用於繪製背景的物理刷子的控制代碼,或者是一個顏色的值。
  • 註冊視窗類:定義了一個視窗類之後,並不能直接使用它通過CreateWindow函式來建立窗體,因為作業系統並不知道該視窗類的存在。需要通過RegisterClass函式註冊一個視窗類。該函式原型如下:
       ATOM RegisterClass(CONST WNDCLASS*lpWndClass);      //引數lpWndClass即為步驟一設計的視窗類的指標

  • 建立視窗:呼叫CreateWindow函式建立視窗。CreateWindow函式語法如下:
             
<span style="white-space:pre">	</span>HWND CreateWindow( 
 		LPCTSTR lpClassName,
		LPCTSTR lpWindowName,
		DWORD dwStyle, 
 		int x, 
         	int y,
 		int nWidth,
		int nHeight, 
   		HWND hWndParent,
 		HMENU hMenu, 
 		HINSTANCE hInstance,
 		LPVOID lpParam 
     <span style="white-space:pre">	</span>);

    引數說明:     lpClassName:跟設計視窗類步驟的引數lpszClassName相同,指定了視窗的類名。     dwStyle:指定建立視窗的風格。該引數可以是下列視窗風格的組合再加上說明部分的控制風格(WS_DISABLED、WS_ICONIC、WS_MAXIMIZE......)。這裡的                                             dwStyle表示每個具體視窗的風格,而視窗類風格指定的是該類視窗所具有的風格。
  • 顯示視窗:視窗在成功建立之後,還需要呼叫ShowWindow函式才能顯示出來
    //顯示視窗
    	ShowWindow(hWnd, SW_SHOW);
    	UpdateWindow(hWnd);

  • 進入訊息迴圈:不斷從訊息佇列取出訊息,存在引數lpMsg引數中。如果獲得訊息為WM_QUIT,返回值為0.如果函式執行過程中出現錯誤,返回值為-1,其他情況返回值為非零。
<span style="white-space:pre">	</span>//進入訊息迴圈
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
最後附上一個建立簡單視窗的Win32程式

#include "windows.h"

//視窗函式
LRESULT CALLBACK WNDFUN(HWND hWnd, UINT msg,
						WPARAM wparam, LPARAM lparam)
{
	switch (msg)
	{
	case WM_PAINT:
		{
			HDC hdc = GetDC(hWnd);
			SetBkMode(hdc, TRANSPARENT);
			TextOut(hdc, 20, 20, (LPCTSTR)"Hello,world!" , sizeof("Hello,world!")-1);
			DeleteDC(hdc);
			break;
		}
	case WM_CLOSE:
		{
			DestroyWindow(hWnd);
			break;
		}
	case WM_DESTROY:
		{
			PostQuitMessage(0);
			break;
		}
	default:
		return DefWindowProc(hWnd, msg, wparam, lparam);
	}
	
	return 0;
}

//程式的入口點
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine, int nCmdShow)
{
	//設計視窗類
	WNDCLASS wndcls;
	wndcls.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW;
	wndcls.lpszMenuName = NULL;
	wndcls.lpszClassName = (LPCTSTR)"CustomWnd";
	wndcls.lpfnWndProc = WNDFUN;
	wndcls.hInstance = GetModuleHandle(NULL);
	wndcls.hIcon = NULL;
	wndcls.hCursor = LoadCursor(hInstance,IDC_ARROW);
	wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndcls.cbClsExtra = 0;
	wndcls.cbWndExtra = 0;
	
	//註冊視窗類
	RegisterClass(&wndcls);
	
	//建立視窗
	HWND hWnd;
	hWnd = CreateWindow((LPCTSTR)"CustomWnd", (LPCTSTR)"Win32App", WS_CAPTION | WS_OVERLAPPEDWINDOW | WS_SYSMENU,
		50, 50, 500, 500, NULL, NULL, wndcls.hInstance, NULL);
	
	//顯示視窗
	ShowWindow(hWnd, SW_SHOW);
	UpdateWindow(hWnd);
	
	//進入訊息迴圈
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	
	return msg.wParam;
	
}