Win 32 編程之按鈕消息響應(代碼小錯誤修復)

最近不想用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 }
View Code

 

目前已經在GNU GCC Compiler成功!

相關文章
相關標籤/搜索