Win32API標準模板

#include<Windows.h>

LRESULT CALLBACK WndProc //處理髮送到窗口的消息的應用程序定義的函數。wndproc類型定義指向此回調函數的指針。
						 //WindowProc是應用程序定義函數名的佔位符。
						 //參考:https://msdn.microsoft.com/en-us/library/ms633573(v=VS.85).aspx
(
	HWND, //hwnd 窗口的句柄
	UINT, //uMsg 消息。 有關係統提供的消息的列表,請參閱系統定義的消息。
	WPARAM, //wParam 其餘消息信息。 此參數的內容取決於uMsg參數的值。
	LPARAM //lParam 其餘消息信息。 此參數的內容取決於uMsg參數的值。
);

int WINAPI WinMain//用戶提供的基於Windows的圖形應用程序的入口點。
				  //WinMain是用於應用程序入口點的常規名稱。 有關更多信息,請參閱備註。
				  //參考:https://docs.microsoft.com/zh-cn/windows/desktop/api/winbase/nf-winbase-winmain
(
	HINSTANCE hInstance, //應用程序當前實例的句柄。
	HINSTANCE hPrevInstance, //上一個應用程序實例的句柄。 
							 //此參數始終爲NULL。 
							 //若是須要檢測是否已存在其餘實例,請使用CreateMutex函數建立惟一命名的互斥鎖。 
							 //即便互斥鎖已經存在,CreateMutex也會成功,但該函數將返回ERROR_ALREADY_EXISTS。 
							 //這表示您的應用程序的另外一個實例存在,由於它首先建立了互斥鎖。 
							 //可是,惡意用戶能夠在執行此操做以前建立此互斥鎖,並阻止您的應用程序啓動。 
							 //要防止出現這種狀況,請建立一個隨機命名的互斥鎖並存儲該名稱,以便只能由受權用戶獲取。 
							 //或者,您可使用文件來實現此目的。 
							 //要將應用程序限制爲每一個用戶一個實例,請在用戶的配置文件目錄中建立一個鎖定文件。
	PSTR szCmdLine, //應用程序的命令行,不包括程序名稱。 要檢索整個命令行,請使用GetCommandLine函數。
	int iCmdshow //TBD
)
{
	static TCHAR szAppName[] = TEXT("MyWindows");
	HWND hwnd;
	MSG msg;
	WNDCLASS wndclass;//包含RegisterClass函數註冊的窗口類屬性。
					  //參考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagwndclassa

	wndclass.style = CS_HREDRAW| CS_VREDRAW;//調整窗口高度或寬度則重繪。
											//參考:https://docs.microsoft.com/zh-cn/windows/desktop/winmsg/window-class-styles
	wndclass.lpfnWndProc = WndProc;//指向窗口過程的指針。
	wndclass.cbClsExtra = 0;//在窗口類結構以後分配的額外字節數。 系統將字節初始化爲零。
	wndclass.cbWndExtra = 0;//窗口實例後要分配的額外字節數。 系統將字節初始化爲零。
							//若是應用程序使用WNDCLASS註冊在資源文件中使用CLASS指令建立的對話框,則必須將此成員設置爲DLGWINDOWEXTRA。
	wndclass.hInstance = hInstance;//包含該類的窗口過程的實例的句柄。
	wndclass.hIcon = //類圖標的句柄。 該成員必須是圖標資源的句柄。 
					 //若是此成員爲NULL,則系統提供默認圖標。
		LoadIcon(NULL, IDI_APPLICATION);//從與應用程序實例關聯的可執行(.exe)文件加載指定的圖標資源。
										//參考:https://docs.microsoft.com/en-us/windows/desktop/api/Winuser/nf-winuser-loadicona
	wndclass.hCursor = //類遊標的句柄。 該成員必須是遊標資源的句柄。
					   //若是此成員爲NULL,則只要鼠標移動到應用程序窗口,應用程序就必須顯式設置光標形狀。
		LoadCursor(NULL, IDC_ARROW);//從與應用程序實例關聯的可執行文件(.EXE)加載指定的遊標資源。
									//參考:https://docs.microsoft.com/en-us/windows/desktop/api/Winuser/nf-winuser-loadcursora
	wndclass.hbrBackground = //類背景畫筆的句柄。
							 //該成員能夠是用於繪製背景的物理畫筆的句柄,也能夠是顏色值。 
		(HBRUSH)GetStockObject(WHITE_BRUSH);//getstockobject函數檢索庫存筆、畫筆、字體或調色板之一的句柄。
											//參考:https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-getstockobject
	wndclass.lpszMenuName = NULL;//類菜單的資源名稱,名稱顯示在資源文件中。 
								 //若是使用整數來標識菜單,請使用MAKEINTRESOURCE宏。 
								 //若是此成員爲NULL,則屬於此類的窗口沒有默認菜單。
	wndclass.lpszClassName = szAppName; //指向以null結尾的字符串或是atom的指針。

	if (!RegisterClass(&wndclass))//註冊一個窗口類,以便在調用CreateWindow或CreateWindowEx函數時使用。
	{
		MessageBox(NULL, TEXT("This program needs to be executed on Windows NT."), szAppName, MB_OK| MB_ICONERROR);
		//顯示模式對話框,其中包含系統圖標,一組按鈕和簡要的特定於應用程序的消息,例如狀態或錯誤信息。 
		//消息框返回一個整數值,指示用戶單擊的按鈕。
		//參考:https://docs.microsoft.com/en-us/windows/desktop/api/Winuser/nf-winuser-messagebox
		return 0;
	}
	else
	{
		hwnd = CreateWindow//建立重疊、彈出或子窗口。它指定窗口類、窗口標題、窗口樣式和(可選)窗口的初始位置和大小。
						   //該函數還指定窗口的父級或全部者(若是有)以及窗口的菜單。
						   //參考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-createwindowa
		(
			szAppName,//由之前調用RegisterClass或RegisterClassEx函數建立的以null結尾的字符串或類原子。 
									  //原子必須在lpClassName的低位字中; 高階詞必須爲零。 
									  //若是lpClassName是字符串,則它指定窗口類名稱。 
									  //類名能夠是使用RegisterClass或RegisterClassEx註冊的任何名稱,前提是註冊該類的模塊也是建立窗口的模塊。 
									  //類名也能夠是任何預約義的系統類名。 有關係統類名稱的列表,請參閱「備註」部分。
			TEXT("My Window"),	//窗口名稱。 若是窗口樣式指定標題欄,則lpWindowName指向的窗口標題將顯示在標題欄中。 
								//使用CreateWindow建立控件(如按鈕,複選框和靜態控件)時,請使用lpWindowName指定控件的文本。 
								//使用SS_ICON樣式建立靜態控件時,請使用lpWindowName指定圖標名稱或標識符。 要指定標識符,請使用語法「#num」。
			WS_OVERLAPPEDWINDOW,//正在建立窗口的樣式。此參數能夠是窗口樣式值的組合,以及「備註」部分中指示的控件樣式。
								//參考:https://docs.microsoft.com/zh-cn/windows/desktop/winmsg/window-styles
			CW_USEDEFAULT,//窗口的初始水平位置。 
						  //對於重疊或彈出窗口,x參數是窗口左上角的初始x座標,以屏幕座標表示。 
						  //對於子窗口,x是窗口左上角相對於父窗口客戶區左上角的x座標。 
						  //若是此參數設置爲CW_USEDEFAULT,則系統選擇窗口左上角的默認位置並忽略y參數。 
						  //CW_USEDEFAULT僅對重疊窗口有效; 若是爲彈出窗口或子窗口指定,則x和y參數設置爲零。
			CW_USEDEFAULT,//窗口的初始垂直位置。 
						  //對於重疊或彈出窗口,y參數是窗口左上角的初始y座標,以屏幕座標表示。 
						  //對於子窗口,y是子窗口左上角相對於父窗口客戶區左上角的初始y座標。 
						  //對於列表框,y是列表框客戶區左上角相對於父窗口客戶區左上角的初始y座標。
						  //若是使用WS_VISIBLE樣式位設置建立重疊窗口而且x參數設置爲CW_USEDEFAULT,則y參數肯定窗口的顯示方式。 
						  //若是y參數是CW_USEDEFAULT,則窗口管理器在建立窗口後使用SW_SHOW標誌調用ShowWindow。 
						  //若是y參數是某個其餘值,則窗口管理器使用該值調用ShowWindow做爲nCmdShow參數。
			CW_USEDEFAULT,//窗口的寬度(以設備爲單位)。 
						  //對於重疊窗口,nWidth是窗口寬度,屏幕座標或CW_USEDEFAULT。 
						  //若是nWidth是CW_USEDEFAULT,則系統選擇窗口的默認寬度和高度; 
						  //默認寬度從屏幕的初始x座標延伸到右邊緣,默認高度從初始y座標延伸到圖標區域的頂部。 
						  //CW_USEDEFAULT僅對重疊窗口有效; 若是爲彈出窗口或子窗口指定了CW_USEDEFAULT,則nWidth和nHeight設置爲零。
			CW_USEDEFAULT,//窗口的高度,以設備爲單位。 
						  //對於重疊窗口,nHeight是窗口座標中窗口的高度。 
						  //若是nWidth設置爲CW_USEDEFAULT,則系統忽略nHeight。
			NULL,//正在建立的窗口的父窗口或全部者窗口的句柄。要建立子窗口或擁有的窗口,請提供有效的窗口句柄。此參數對於彈出窗口是可選的。
				 //要建立僅消息窗口,請向現有僅消息窗口提供hwnd_消息或句柄。
			NULL,//菜單的句柄,或根據窗口樣式指定子窗口標識符。
				 //對於重疊窗口或彈出窗口,hmenu標識要與窗口一塊兒使用的菜單;若是要使用類菜單,則能夠爲空。
				 //對於子窗口,hmenu指定子窗口標識符,該標識符是對話框控件用來通知其父窗口有關事件的整數值。
				 //應用程序肯定子窗口標識符;對於具備相同父窗口的全部子窗口,該標識符必須是惟一的。
			hInstance,//與窗口關聯的模塊實例的句柄。
			NULL//指向要經過createStruct結構(lpcreateParams成員)傳遞到窗口的值的指針,該結構由wm_create消息的lparam參數指向。
				//此消息在返回以前由函數發送到建立的窗口。
				//若是應用程序調用CreateWindow來建立MDI客戶機窗口,lpparam應指向ClientCreateStruct結構。
				//若是MDI客戶機窗口調用CreateWindow來建立MDI子窗口,lpParam應該指向MDICreatestruct結構。若是不須要其餘數據,lpparam可能爲空。
		);

		ShowWindow(hwnd, iCmdshow);//設置指定窗口的顯示狀態。
								   //參考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-showwindow
		UpdateWindow(hwnd);//updateWindow函數經過向窗口發送wm_paint消息(若是窗口的更新區域不爲空)來更新指定窗口的客戶機區域。
						   //該函數將wm_paint消息直接發送到指定窗口的窗口過程,繞過應用程序隊列。若是更新區域爲空,則不發送消息。
						   //參考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-updatewindow

		while (GetMessage//從調用線程的消息隊列中檢索消息。該函數將發送傳入的已發送消息,直到能夠檢索已發佈的消息。
						 //與getmessage不一樣,peekmessage函數不等待消息在返回以前發佈。
						 //參考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getmessage
		(
			&msg, //指向從線程的消息隊列接收消息信息的MSG結構的指針。
			NULL, //要檢索其消息的窗口的句柄。
				  //窗口必須屬於當前線程。
				  //若是hwnd爲空,getmessage將檢索屬於當前線程的任何窗口的消息,以及當前線程的消息隊列中hwnd值爲空的任何消息(請參見msg結構)。
				  //所以,若是hwnd爲空,則同時處理窗口消息和線程消息。
				  //若是hwnd爲 - 1,則getmessage僅檢索當前線程的消息隊列中hwnd值爲空的消息,
				  //也就是說,由postmessage(當hwnd參數爲空時)或postmthreadmessage發佈的線程消息。
			0, //要檢索的最低消息值的整數值。
			   //使用wm_keyfirst(0x0100)指定第一個鍵盤消息,或使用wm_mouse first(0x0200)指定第一個鼠標消息。
			   //在這裏和wmsgfiltermax中使用wm_input僅指定wm_輸入消息。
			   //若是wmsgfiltermin和wmsgfiltermax都爲零,則getmessage返回全部可用消息(即,不執行範圍篩選)。
			0//要檢索的最高消息值的整數值。
			 //使用wm_keylast指定最後一條鍵盤消息,或使用wm_mouselast指定最後一條鼠標消息。
			 //在這裏和wmsgfiltermin中使用wm_input僅指定wm_輸入消息。
			 //若是wmsgfiltermin和wmsgfiltermax都爲零,則getmessage返回全部可用消息(即,不執行範圍篩選)。
		))
		{
			TranslateMessage(&msg);//將虛擬密鑰消息轉換爲字符消息。
								   //字符消息被髮送到調用線程的消息隊列,以便下次線程調用getmessage或peekmessage函數時讀取。
								   //參考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-translatemessage
			DispatchMessage(&msg);//將虛擬密鑰消息轉換爲字符消息。
								  //字符消息被髮送到調用線程的消息隊列,以便下次線程調用getmessage或peekmessage函數時讀取。
								  //參考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-dispatchmessage
		}

		return msg.wParam;//有關該消息的其餘信息。 確切含義取決於消息成員的值。
						  //參考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagmsg
	}
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	RECT rect;

	switch (message)
	{
	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);//beginpaint函數準備用於繪製的指定窗口,並用有關繪製的信息填充paintstruct結構。
									//參考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-beginpaint
		GetClientRect(hwnd, &rect);//檢索富編輯控件的客戶端矩形。
								   //參考:https://docs.microsoft.com/en-us/windows/desktop/api/tom/nf-tom-itextdocument2-getclientrect

		DrawText//drawtext函數在指定的矩形中繪製格式化文本。
				//它根據指定的方法格式化文本(展開選項卡、調整字符、換行等)。
				//參考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-drawtext
		(
			hdc, //設備上下文的句柄
			TEXT("Hello, this is my first window project."), //指向要指定要繪製的文本的字符串的指針。
															 //若是nCount參數爲 - 1,則字符串必須以空值終止。
															 //若是uFormat包含DT_MODIFYSTRING,則該函數最多能夠爲該字符串添加四個附加字符。
															 //包含字符串的緩衝區應足夠大以容納這些額外字符。
			-1, //字符串的長度(以字符爲單位)。 
				//若是nCount爲-1,則假定lpchText參數是指向以null結尾的字符串的指針,DrawText會自動計算字符計數。
			&rect, //指向rect結構的指針,該結構包含要格式化文本的矩形(以邏輯座標表示)。
			DT_SINGLELINE| DT_CENTER| DT_VCENTER //格式化文本的方法。單行、水平中心、豎直中心。
		);

		EndPaint(hwnd, &ps);//EndPaint函數標記指定窗口中繪製的結束。 
							//每次調用BeginPaint函數都須要此函數,但僅在繪製完成後才須要此函數。
							//參考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-endpaint
		return 0;

	case WM_DESTROY:
		PostQuitMessage(0);//向系統指示線程已請求終止(退出)。它一般用於響應wm_銷燬消息。
		return 0;
	}

	return DefWindowProc(hwnd, message, wParam, lParam);
	//調用默認窗口過程爲應用程序不處理的任何窗口消息提供默認處理。 
	//此功能可確保處理每條消息。 
	//使用窗口過程接收的相同參數調用DefWindowProc。
	//參考:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-defwindowproca
}
相關文章
相關標籤/搜索