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


  在學習了比較多的 Windows SDK 編程相關的知識后, 擬用 Win32 SDK(純 API, 非MFC)開始編寫 Windows 程序了.
  准備工作:C語言(C++更好), VC++6.0(因為它簡單些, 使用 VS2010 等待也可以). 由於VC++6.0 版本過老, 對C語言的某些新特性並沒有很好地支持(比如變量的定義位置), 所以在此(及以后)我們都采用 .CPP 格式的編寫源代碼, 但基本上是C語言的語法. 我的平台是 Windows XP SP3, Win7也同樣編譯.
  由於是第一篇日志, 就寫一個簡單的窗口吧. 函數的相關功能, 請參考在線 MSDN.
  
  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", //這里就是我們剛才創建的窗口類名
"女孩不哭",
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函數結束, 整個程序退出
}

插圖:


女孩不哭(QQ:191035066) @ cnblogs/nbsofer @ 2012-04-02


免責聲明!

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



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