Win32 SDK 編程開始, 創建窗口, 消息的處理, 消息循環


Windows SDK 編程的一般步驟為:
    1. 注冊窗口類, 使用到的結構 WNDCLASSEX, 函數 RegisterClassEx.
    2. 創建窗口, 函數 CreateWindowEx.
    3. 消息循環, 結構 MSG, 函數 GetMessage, TranslateMessage, DispatchMessage.
    4. 進入無限循環, 消息處理 :-)

  下面是代碼, 當然, 還有分析:

#include <windows.h>    //包含 Windows 相關的 API 函數

//這里就是所謂的消息處理函數了
//CALLBACK 說明當前函數是回調函數, 就是說明調用約定
//hwnd:窗口句柄, uMsg:收到的消息, wParam, lParam:與該消息有關的參數
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)    //消息選擇
    {
    //這里我添加一個左鍵按下的消息
    case WM_LBUTTONDOWN:
        MessageBox(hwnd, "左鍵按下", "提示", MB_OK);
        return 0;
        
    case WM_DESTROY:    //當前窗口被銷毀時
        PostQuitMessage(0);    //發出退出程序的消息
        return 0;    //如果處理了該消息, 就返回 0 來告知 Windows

    case WM_CLOSE:    //當用戶點擊窗口右上角的關閉按鈕時
        DestroyWindow(hwnd);    //銷毀窗口
        return 0;

    case WM_PAINT:    //當窗口需要重繪時
        {
            PAINTSTRUCT ps = {0};
            BeginPaint(hwnd, &ps);    //開始重繪
            
            EndPaint(hwnd, &ps);    //結束重繪
            return 0;
        }
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);    
    //對於我們不想處理的消息, 比如鼠標在窗口上移動時發出的消息
    //我們就原樣傳給默認的窗口消息處理函數處理, 不然應用程序會失去響應
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    //注意 Windows 程序應該使用 WinMain 入口函數了, 不再使用 main 函數
    //當然, 如果不創建窗口, 不使用窗口 也可以使用 main.
    WNDCLASSEX wc = {0};            //窗口類結構, 為注冊窗口類作准備
    wc.cbClsExtra = 0;                //附加的類信息, 沒有, 設為0
    wc.cbSize = sizeof(wc);            //WNDCLASSEX結構的大小
    wc.cbWndExtra = 0;                //窗口額外內存, 沒有, 設為0
    wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);            //窗口背景, 這里使用灰色背景
    wc.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));        //應用程序使用的鼠標類型
    wc.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));    //光標類型
    wc.hIconSm = NULL;                    //應用程序程序的小光標, 不管, 設為 NULL
    wc.hInstance = hInstance;            //應用程序程序實例句柄, 由 WinMain 函數傳遞過來
    wc.lpfnWndProc = WndProc;            //這個很重要, 就是當前窗口的消息處理函數, 傳遞 WndProc 的地址
    wc.lpszClassName = "vbgk_class";    //創建類時使用的類名, 可以自定義
    wc.lpszMenuName = NULL;                //菜單, 沒有, 就使用 NULL
    wc.style = CS_HREDRAW | CS_VREDRAW;    //類的風格, 垂直重繪, 水平重繪

    if(!RegisterClassEx(&wc))    //注冊窗口類
    {
        MessageBox(NULL, "Register Class Failed!", NULL, MB_OK);
        return 1;
    }
    
    //創建窗口咯, 介紹一下 CreateWindowEx 函數的參數
    HWND hWnd = CreateWindowEx(
                0,                    //擴展窗口風格
                "vbgk_class",        //這里就是我們剛才創建的窗口類名
                "木木ing", 
                WS_OVERLAPPEDWINDOW,//窗口風格
                CW_USEDEFAULT,        //初始化時的 X 坐標
                CW_USEDEFAULT,        //Y坐標
                320,        //窗口寬度, 我們這里設為 320
                240,        //窗口高度
                NULL,        //父窗口句柄, 沒有
                NULL,        //菜單, 沒有
                hInstance,    //實例句柄, 來自WinMain
                NULL        //發送 WM_CREATE 消息時的附加參數, 一般為零
                );
    if(!hWnd)
    {
        MessageBox(NULL, "CreateWindowEx Failed!", NULL, MB_OK);
        return 2;
    }

    UpdateWindow(hWnd);                //更新窗口
    ShowWindow(hWnd, nCmdShow);        //顯示窗口

    MSG msg;
    BOOL bRet;
    //進入消息循環
    while((bRet = GetMessage(&msg, NULL, 0, 0)) != -1)
    {
        if(bRet == 0)
        {
            break;
        }

        TranslateMessage(&msg);    //翻譯消息
        DispatchMessage(&msg);    //分發消息
    }

    return msg.wParam;    //WinMain函數結束, 整個程序退出
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM