win32应用程序创建流程
窗口創建過程
創建一個完整的窗口,需要經過下面幾個操作步驟:
1.編寫WinMain函數(可以查看MSDN)。
2.設計窗口類(WNDCLASS)。
3.注冊窗口類。
4.創建窗口。
5.顯示并更新窗口。
6.編寫消息循環。
7.編程窗口過程函數。
編寫WinMain函數
WinMain是Windows程序的入口點函數,當操作系統啟動一個程序時,它就調用該程序的WinMain函數。它和DOS程序的入口點函數main是一樣的作用。
WinMain函數的原型聲明如下:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd); 參數說明:
- hInstance 表示該程序當前運行的實例句柄,這是一個數值,操作系統會為每個運行中的實例分配句柄值。
- hPrevInstance 當前實例的前一個句柄的實例。
- lpCmdLine 指定給應用程序的命令行參數。
- nShowCmd 指定程序的窗口應該如何顯示。
設計窗口類
一個完整的窗口類具有許多特征,包括光標(鼠標進入該窗口時的形狀)、圖標、背景顏色等,在創建一個窗口前,需要對一個窗口進行設計,在windows中,窗口的特征有WNDCLASS結構體來定義,WNDCLASS結構體的定義如下:
typedef struct {UINT style; //這一類型窗口的樣式WNDPROC lpfnWndProc; //指向窗口過程的函數指針int cbClsExtra; //類附加內存int cbWndExtra; //窗口附加內存HINSTANCE hInstance; //實例句柄HICON hIcon; //窗口類的圖標句柄HCURSOR hCursor; //窗口類的光標句柄HBRUSH hbrBackground; //窗口類的背景 LPCTSTR lpszMenuName; //菜單名字LPCTSTR lpszClassName; //窗口類名字 } WNDCLASS;
注冊窗口
設計完窗口類后,需要調用RegisterClass函數對其注冊,注冊成功后,才可以創建該類型的窗口。函數聲明如下:
ATOM RegisterClass(const WNDCLASS* lpWndClass);
創建窗口
設計好窗口類并進行注冊成功之后,就可以利用CreateWindow函數產生這種類型的窗口了,其函數聲明如下:
HWND CreateWindow(LPCTSTR lpClassName, //指定窗口類的名稱,需要和WNDCLASS的className一樣。LPCTSTR lpWindowName, //窗口的名字DWORD dwStyle, //創建的窗口樣式int x, //窗口左上角的x坐標int y, //窗口左上角的y坐標int nWidth, //窗口寬度int nHeight, //窗口高度HWND hWndParent, //父窗口句柄HMENU hMenu, //窗口菜單的句柄HANDLE hInstance, //應用程序句柄PVOID lpParam ); //附件參數,多文檔窗口為CLIENTCREATESTRUCT結構體,其余多是NULL
顯示窗口
窗口創建成功之后,我們要讓它顯示出來,調用函數ShowWindow來顯示窗口,函數原型如下:
BOOL ShowWindow(HWND hWnd, int nCmdShow);nCmdShow指定了窗口顯示的狀態,具體窗口狀態可以查看MSDN
更新窗口
被調用ShowWindow函數之后,我們需要緊接調用UpdateWindow來刷新窗口。UpdateWindow函數聲明如下:
BOOL UpdateWindow(HWND hWnd// handle to window);其參數是創建成功后的窗口句柄,UpdateWindow函數通過發送一個WM_PAINT消息來刷新窗口,UpdateWindow將WM_PAINT消息直接發送給了窗口過程函數進行消息處理,而沒有放到消息隊列中去。
消息循環
在創建窗口、顯示窗口、更新窗口后,我們需要編寫一個消息循環,不斷地從消息隊列中取出消息,并進行響應。獲取消息可以調用GetMessage()函數,消息循環常見代碼如下:
MSG msgInfo;while (GetMessage(&msgInfo, NULL, 0, 0)){TranslateMessage(&msgInfo);DispatchMessage(&msgInfo);}
更多內容見“windows消息處理機制”。
編程窗口過程函數
在完成上述步驟后,剩下的工作主要是編寫一個窗口過程函數,用于處理發送給窗口的消息。一個Windows應用程序的主要代碼部分就隱藏在窗口過程,其函數聲明如下:
LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
窗口過程函數的名字是可隨便命名的,但函數定義的形式必須和上述聲明保持一致。WindowProc函數的4個參數分別對應消息的窗口句柄。消息代碼、消息代碼的兩個附加參數。
一個程序可以有多個窗口,窗口過程函數的hwnd就標識了接收消息的特定窗口。在窗口過程函數內部使用switch/case語句來確定窗口過程接收消息類型以及消息的處理。例如:
//編寫窗口過程函數 LRESULT CALLBACK WindProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {switch (uMsg){case WM_CHAR:{char szMsg[20] = {0};sprintf_s(szMsg,"char code is %d", wParam);MessageBox(hWnd,szMsg, "char", 0);break;}case WM_PAINT:...case WM_CLOSE:...case WM_DESTROY:...default: return DefWindowProc(hWnd,uMsg,wParam,lParam);} }
完整代碼
#include <Windows.h> #include <stdio.h>//窗口過程函數聲明 LRESULT CALLBACK WndProcess(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);/**************************************************************** *函數名稱:WinMain *功 能:winddow應用程序入口 *作 者:Jin *日 期:2016年8月10日 ****************************************************************/ int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) {//設計窗口類WNDCLASS wndcls;wndcls.cbClsExtra = 0;wndcls.cbWndExtra = 0;wndcls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);wndcls.hCursor = LoadCursor(NULL, IDC_ARROW);wndcls.hIcon = LoadIcon(NULL, IDI_APPLICATION);wndcls.hInstance = hInstance;wndcls.lpfnWndProc = WndProcess;wndcls.lpszClassName = "Jin";wndcls.lpszMenuName = NULL;//垂直和橫軸大小發生變化,窗口重繪wndcls.style = CS_HREDRAW | CS_VREDRAW; //注冊窗口RegisterClass(&wndcls);HWND hWnd = NULL;//創建窗口hWnd = CreateWindow("Jin", "Jin Win32", WS_OVERLAPPEDWINDOW, 0, 0,\600, 400, NULL, NULL, hInstance, NULL);//顯示&刷新ShowWindow(hWnd,SW_SHOWNORMAL);UpdateWindow(hWnd);//定義消息循環MSG msgInfo;while (GetMessage(&msgInfo, NULL/*所有窗口*/, 0, 0)){TranslateMessage(&msgInfo); //換字符消息DispatchMessage(&msgInfo); //分發消息}return msgInfo.wParam; }/**************************************************************** *函數名稱:WndProcess *功 能:窗口過程消對應的消息處理 *作 者:Jin *日 期:2016年8月21日 ****************************************************************/ LRESULT CALLBACK WndProcess(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {switch (uMsg){case WM_CHAR:{char szChar[20] = {0};sprintf_s(szChar,"char code is %d", wParam);MessageBox(hWnd,szChar, "char", MB_OK);break;}case WM_LBUTTONDOWN:{MessageBox(hWnd, "mouse clicked", "mouse", MB_OK);HDC hDc;hDc = GetDC(hWnd);TextOut(hDc, 0, 50, "hello world", strlen("hello world"));ReleaseDC(hWnd,hDc);break;}case WM_PAINT:{HDC hDC;PAINTSTRUCT ps;hDC = BeginPaint(hWnd, &ps);TextOut(hDC,0,0,"CSDN", strlen("CSDN"));EndPaint(hWnd, &ps);break;}case WM_CLOSE:{if (IDYES == MessageBox(hWnd, "are you sure to exit?", "message", MB_YESNO)){DestroyWindow(hWnd);//窗口消失,產生WM_DESTROY新消息}break;}case WM_DESTROY:{PostQuitMessage(0);//產生WM_QUIT消息,然后程序退出break;}default: return DefWindowProc(hWnd,uMsg,wParam,lParam);}return 0; }運行初始結果
轉載于:https://www.cnblogs.com/jinxiang1224/p/8468390.html
總結
以上是生活随笔為你收集整理的win32应用程序创建流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php魔术方法__SET __GET
- 下一篇: VS2013在Release情况下使用v