最近不想用MFC寫東西了,有沒有安裝Qt和其餘圖形化開發環境,只能搗鼓API了。因而乎,就有了如下的學習--windows
首先,老套的建立個Windows窗口,因爲本身有點小懶,就直接用Hello Word的源碼了。app
#include <windows.h> #include <stdio.h> // 窗口過程函數 LRESULT CALLBACK WinSunProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); int WINAPI WinMain( HINSTANCE hInstance, // handle to current instance HINSTANCE hPrevInstance, // handle to previous instance LPSTR lpCmdLine, // command line int nCmdShow // show state ) { // 窗口類 WNDCLASS wndcls; wndcls.cbClsExtra = 0; // 類附加內存 wndcls.cbWndExtra = 0; // 窗口附加內存 wndcls.hbrBackground = (HBRUSH) GetStockObject(COLOR_WINDOW); // 背景畫刷句柄 wndcls.hCursor = LoadCursor(NULL, IDC_ARROW); // 窗口光標句柄 wndcls.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 窗口圖標句柄 wndcls.hInstance = hInstance; // 包含窗口過程函數的程序實例 wndcls.lpfnWndProc = WinSunProc; // 只想窗口過程函數的指針 wndcls.lpszClassName = "CRoot"; // 窗口類名稱 wndcls.lpszMenuName = NULL; // 菜單資源 wndcls.style = CS_HREDRAW | CS_VREDRAW; // 窗口樣式 RegisterClass(&wndcls); // 建立窗口, 定義一個變量用來保存成功建立窗口後返回的句柄 HWND hwnd; hwnd = CreateWindow( // 窗口建立成功時返回爲窗口分配的句柄 失敗時返回NULL "CRoot", // 窗口類名 "Hello World", // 窗口名字 WS_CAPTION|WS_SYSMENU, // 窗口樣式 CW_USEDEFAULT, CW_USEDEFAULT, // 窗口左上角座標 200, 120, // 窗口寬高 NULL, // 父窗口句柄 NULL, // 窗口菜單句柄 hInstance, // 窗口所屬應用程序實例 NULL // WM_CREATE消息附加參數lParam傳入的數據指針 ); // 顯示及刷新窗口 ShowWindow(hwnd, SW_SHOWNORMAL); UpdateWindow(hwnd); // 定義消息結構體 MSG msg; while (GetMessage( // WM_QUIT消息返回0 錯誤返回-1 &msg, // 指向消息的結構體 NULL, // 指定接收屬於哪一窗口的消息 一般設爲NULL,用來接收屬於調用線程的全部窗口的窗口消息 0, // 獲取消息的最小值 一般爲0 0)) // 獲取消息的最大值 都設爲0表示接收全部消息 { TranslateMessage(&msg); // 將虛擬消息轉換爲字符消息 投遞到調用線程的消息隊列中 下次調用GetMessage時被取出 DispatchMessage(&msg); // 將消息傳遞給操做系統 由操做系統調用窗口過程函數對消息進行處理 } return msg.wParam; } // 窗口過程函數 LRESULT CALLBACK WinSunProc( HWND hwnd, // 窗口句柄 UINT uMsg, // 消息代碼 WPARAM wParam, // 附加參數 LPARAM lParam ) { switch(uMsg) { case WM_CHAR: char szChar[20]; sprintf(szChar, "char code is %d", wParam); MessageBox(hwnd, szChar, "char", 0); break; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; }
而後,咱們要在消息循環裏面添加建立Button的代碼,由於Button是一個子窗口,因此建立方式也如同建立窗口同樣,使用CreateWindow()函數。框架
而,此窗口要一開始跟隨父窗口出現,因此要在父窗口建立時建立該Button。嗯,因此要在窗口過程函數裏面監聽下WM_CREATE消息。ide
代碼片斷:函數
switch(uMsg) { case WM_CHAR: char szChar[20]; sprintf(szChar, "char code is %d", wParam); MessageBox(hwnd, szChar, "char", 0); break; case WM_CREATE: CreateWindowEx(0,"Button","按鈕1",WS_VISIBLE|WS_CHILD,0,0,100,50,hwnd,(HMENU)0,0,0); default: return DefWindowProc(hwnd, uMsg, wParam, lParam); }
這裏要說明一下啦,一開始我也搞得暈暈乎乎,不知道怎麼搞Button的消息事件,這裏咱們用Button的ID啦。先看下微軟的MSDN關於CreateWindow()函數學習
HWND WINAPI CreateWindow( _In_opt_ LPCTSTR lpClassName, _In_opt_ LPCTSTR lpWindowName, _In_ DWORD dwStyle, _In_ int x, _In_ int y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent, _In_opt_ HMENU hMenu, _In_opt_ HINSTANCE hInstance, _In_opt_ LPVOID lpParam );
關鍵點在參數HMENU hWndParent,第一眼一看是否是感受像菜單?不錯啦~確實在菜單中用到的。進一步看他的解釋this
hMenu [in, optional]spa
Type: HMENU操作系統
A handle to a menu, or specifies a child-window identifier depending on the window style. For an overlapped or pop-up window, hMenu identifies the menu to be used with the window; it can be NULL if the class menu is to be used. For a child window, hMenu specifies the child-window identifier, an integer value used by a dialog box control to notify its parent about events. The application determines the child-window identifier; it must be unique for all child windows with the same parent window.線程
紅色選中大致意思說,當在作一個子窗口的時候,這個參數就是一個整形表示,用於標識這個子窗口,提供父窗口的消息處理。總的來講就是所謂的控件ID啦~
既然有標識,就好辦啦,咱們就判斷是否是他,如果這個按鈕,咱們就讓他響應相應的操做啦~~
可是怎麼知道按鈕被Click了呢?咱們又得監聽另外一個消息WM_COMMAND,它有兩個參數,其中一個就傳輸了所謂的控件ID
wParam
For a description of this parameter.
lParam
For a description of this parameter.
咱們能夠判斷他若是是這個按鈕的ID,咱們就讓他幹某些事情。咱們首先要轉換下wParam的類型,不然和咱們寫的ID的類型不同的。
case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); switch (wmId) { case (0)://以前咱們建立按鈕時,寫的ID爲0
//功能代碼 //....... break; //...更多代碼 }
好了,總體框架差很少完工啦,本身再加下代碼啥的就沒問題了。在這裏,我再次浪費下篇幅,給出完整代碼:
關於wmId一開始寫程序沒有編譯,由於邏輯錯誤,未有注意到,忘記聲明他了。爲了防止被default給忽略掉,咱們把他寫在switch(uMsg)以前。
1 #include <windows.h> 2 #include <stdio.h> 3 #include <Windef.h> 4 5 // 窗口過程函數 6 LRESULT CALLBACK WinSunProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 7 8 int WINAPI WinMain( 9 HINSTANCE hInstance, // handle to current instance 10 HINSTANCE hPrevInstance, // handle to previous instance 11 LPSTR lpCmdLine, // command line 12 int nCmdShow // show state 13 ) 14 15 { 16 // 窗口類 17 WNDCLASS wndcls; 18 wndcls.cbClsExtra = 0; // 類附加內存 19 wndcls.cbWndExtra = 0; // 窗口附加內存 20 wndcls.hbrBackground = (HBRUSH) GetStockObject(COLOR_WINDOW); // 背景畫刷句柄 21 wndcls.hCursor = LoadCursor(NULL, IDC_ARROW); // 窗口光標句柄 22 wndcls.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 窗口圖標句柄 23 wndcls.hInstance = hInstance; // 包含窗口過程函數的程序實例 24 wndcls.lpfnWndProc = WinSunProc; // 只想窗口過程函數的指針 25 wndcls.lpszClassName = "CRoot"; // 窗口類名稱 26 wndcls.lpszMenuName = NULL; // 菜單資源 27 wndcls.style = CS_HREDRAW | CS_VREDRAW; // 窗口樣式 28 RegisterClass(&wndcls); 29 30 // 建立窗口, 定義一個變量用來保存成功建立窗口後返回的句柄 31 HWND hwnd; 32 hwnd = CreateWindow( // 窗口建立成功時返回爲窗口分配的句柄 失敗時返回NULL 33 "CRoot", // 窗口類名 34 "Hello World", // 窗口名字 35 WS_CAPTION|WS_SYSMENU, // 窗口樣式 36 CW_USEDEFAULT, CW_USEDEFAULT, // 窗口左上角座標 37 200, 120, // 窗口寬高 38 NULL, // 父窗口句柄 39 NULL, // 窗口菜單句柄 40 hInstance, // 窗口所屬應用程序實例 41 NULL // WM_CREATE消息附加參數lParam傳入的數據指針 42 ); 43 44 // 顯示及刷新窗口 45 ShowWindow(hwnd, SW_SHOWNORMAL); 46 UpdateWindow(hwnd); 47 48 // 定義消息結構體 49 MSG msg; 50 while (GetMessage( // WM_QUIT消息返回0 錯誤返回-1 51 &msg, // 指向消息的結構體 52 NULL, // 指定接收屬於哪一窗口的消息 一般設爲NULL,用來接收屬於調用線程的全部窗口的窗口消息 53 0, // 獲取消息的最小值 一般爲0 54 0)) // 獲取消息的最大值 都設爲0表示接收全部消息 55 { 56 TranslateMessage(&msg); // 將虛擬消息轉換爲字符消息 投遞到調用線程的消息隊列中 下次調用GetMessage時被取出 57 DispatchMessage(&msg); // 將消息傳遞給操做系統 由操做系統調用窗口過程函數對消息進行處理 58 } 59 return msg.wParam; 60 } 61 62 // 窗口過程函數 63 LRESULT CALLBACK WinSunProc( 64 HWND hwnd, // 窗口句柄 65 UINT uMsg, // 消息代碼 66 WPARAM wParam, // 附加參數 67 LPARAM lParam 68 ) 69 { 70 WORD wmId = LOWORD(wParam); 71 //WORD wmEvent = HIWORD(wParam); 72 switch(uMsg) 73 { 74 /*case WM_CHAR: 75 char szChar[20]; 76 sprintf(szChar, "char code is %d", wParam); 77 MessageBox(hwnd, szChar, "char", 0); 78 break;*/ 79 case WM_CREATE: 80 CreateWindowEx(0,"Button","按鈕1",WS_VISIBLE|WS_CHILD,0,0,70,40,hwnd,(HMENU)0,0,0); 81 break; 82 case WM_COMMAND: 83 switch (wmId) 84 { 85 case 0://(HMENU) 和建立中的id對應 86 //這裏寫你要讓按鈕實現的功能 87 MessageBoxA(NULL,"Hello Button!","My TestProject",MB_OK); 88 } 89 break; 90 91 default: 92 return DefWindowProc(hwnd, uMsg, wParam, lParam); 93 } 94 95 return 0; 96 }
目前已經在GNU GCC Compiler成功!