天天看點

Windows程式設計-視窗和消息

完整代碼注釋

#include <Windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("HelloWin");
    HWND hwnd;
    MSG msg;
    // 視窗類,指定基本的視窗資訊,CreateWindow參數指定更詳細的資訊
    WNDCLASS wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;  // 視窗類樣式
    wndclass.lpfnWndProc = WndProc;  // 視窗消息處理程式
    wndclass.cbClsExtra = 0;  // 視窗類結構預留白間
    wndclass.cbWndExtra = 0;  // Windows内部預留白間
    wndclass.hInstance = hInstance;  // 程式的執行實體句柄
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);  // 加載圖示
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);  // 加載滑鼠光标
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);  // 取得一個圖形(白色背景畫刷)對象
    wndclass.lpszMenuName = NULL;  // 指定視窗類别菜單
    wndclass.lpszClassName = szAppName;  // 視窗類文字名稱
    if (!RegisterClass(&wndclass))  // 注冊視窗類
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
            szAppName, MB_ICONERROR);
        return 0;
    }
    hwnd = CreateWindow(szAppName,  // 視窗類名稱,視窗聯結視窗類别的方式
        TEXT("The Hello Program"), // 視窗标題
        WS_OVERLAPPEDWINDOW, // 标準樣式的視窗
        CW_USEDEFAULT,// initial x position
        CW_USEDEFAULT,// initial y position
        CW_USEDEFAULT,// initial x size
        CW_USEDEFAULT,// initial y size
        NULL, // parent window handle
        NULL, // window menu handle
        hInstance, // program instance handle
        NULL); // creation parameters
    // 在顯示器上顯示視窗,第二個參數:正常、最大化、最小化、隐藏
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);  // 重畫顯示區域,發送消息給消息處理程式
    while (GetMessage(&msg, NULL, 0, 0))  // 從消息隊列擷取消息
    {
        TranslateMessage(&msg);  // 将msg結構傳給Windows,進行一些鍵盤轉換
        DispatchMessage(&msg);  // 調用消息處理程式
    }
    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam,
    LPARAM lParam)  // 視窗消息處理程式的四個參數與MSG結構的前四個字段是相同的
{
    HDC hdc;
    PAINTSTRUCT ps;
    RECT rect;
    switch (message) {
    case WM_CREATE:  // 視窗建立時,處理WM_CREATE消息
        // 播放聲音檔案
        PlaySound(TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC);
        return 0;  // 必須傳回0
    case WM_PAINT:  // 更新畫面時,處理WM_PAINT消息
        hdc = BeginPaint(hwnd, &ps); // 獲得裝置内容句柄
        GetClientRect(hwnd, &rect);  // 設定RECT坐标(視窗大小)
        DrawText(hdc, TEXT("你好視窗!"), -1, &rect,
            DT_SINGLELINE | DT_CENTER | DT_VCENTER);
        EndPaint(hwnd, &ps);  // 釋放裝置内容句柄
        return 0;
    case WM_DESTROY:  // 處理WM_DESTROY消息
        // 在程式的消息隊列中插入一個WM_QUIT消息,GetMessage會傳回0,退出消息循環
        PostQuitMessage(0);
        return 0;
    }
    // 不予處理的所有消息應該被傳給名為DefWindowProc
    return      

播放WAV

VS2015引入WINMM.LIB,用來播放WAV:工程,右鍵屬性,連結器,輸入,附加依賴項

調用的Windows函數

LoadIcon 加載圖示供程式使用。

LoadCursor 加載滑鼠光标供程式使用。

GetStockObject 取得一個圖形對象(在這個例子中,是取得繪制視窗背景的畫刷對象)。

RegisterClass 為程式視窗注冊視窗類别。

MessageBox 顯示消息框。

CreateWindow 根據視窗類别建立一個視窗。

ShowWindow 在螢幕上顯示視窗。

UpdateWindow 訓示視窗自我更新。

GetMessage 從消息隊列中取得消息。

TranslateMessage 轉譯某些鍵盤消息。

DispatchMessage 将消息發送給視窗消息處理程式。

PlaySound 播放一個聲音檔案。

BeginPaint 開始繪制視窗。

GetClientRect 取得視窗顯示區域的大小。

DrawText 顯示字元串。

EndPaint 結束繪制視窗。

PostQuitMessage 在消息隊列中插入一個「退出程式」消息。

DefWindowProc 執行内定的消息處理。

大寫字母辨別

字首 類别 英文
CS 視窗類别樣式 class style
CW 建立視窗 create window
DT 繪制文字 draw text
IDI 圖示ID ID icon
IDC 遊标ID ID cursor
MB 消息框 message border
SND 聲音 sound
WM 視窗消息 window message
WS 視窗樣式 window style

四種資料結構

結構 含義
MSG 消息結構
WNDCLASS 視窗類别結構
PAINTSTRUCT 繪圖結構
RECT 矩形結構
/*
 * 消息資料結構
 */
typedef struct tagMSG {
    HWND        hwnd;  // 接收消息的視窗句柄
    UINT        message;  // 消息辨別符
    WPARAM      wParam;  // 32位的消息參數(message parameter)
    LPARAM      lParam;  // 32位的消息參數
    DWORD       time;  // 放入消息隊列中的時間
    POINT       pt;  // 消息放入消息隊列時的滑鼠坐标
#ifdef _MAC
    DWORD       lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;      

WM_QUIT消息将導緻GetMessage傳回0

大寫辨別符

句柄是一個(通常為32位的)整數,它代表一個對象。

辨別符 含義
HINSTANCE 執行實體(程式自身)句柄
HWND 視窗句柄
HDC 裝置内容句柄
HICON 圖示句柄 handle to an icon
HCURSOR 滑鼠光标句柄
HBRUSH 畫刷句柄

匈牙利表示法

字首 資料型态
c char或WCHAR或TCHAR
by BYTE (無正負号字元)
n short
i int
x, y int分别用作x坐标和y坐标
cx, cy int分别用作x長度和y長度;C代表「計數器」
b或f BOOL (int);f代表「旗标」
w WORD (無正負号短整數)
l LONG (長整數)
dw DWORD (無正負号長整數)
fn function(函數)
s string(字元串)
sz 以位元組值0結尾的字元串
h 句柄
p 名額

消息中心

假設使用者執行HELLOWIN,并且使用者最終單擊了 Close按鈕,或者假設用鍵盤或滑鼠從系統菜單中選擇了 Close, DefWindowProc處理這一鍵盤或者滑鼠輸入,在檢測到使用者選擇了Close選項之後,它給視窗消息處理程式發送一條WM_SYSCOMMAND消息。WndProc将這個消息傳給DefWindowProc。DefWindowProc給視窗消息處理程式發送一條WM_CLOSE消 息 來 響 應 之 。 WndProc 再 次 将 它 傳 給 DefWindowProc 。 DestroyWindow 呼 叫DestroyWindow來響應這條WM_CLOSE消息。DestroyWindow導緻Windows給視窗消息處理程式發送一條WM_DESTROY消息。WndProc再呼叫PostQuitMessage,将一條WM_QUIT消息放入消息隊列中,以此來響應此消息。這個消息導緻WinMain中的消息循環終止,然後程式結束。

消息能夠被分為「隊列化的」和「非隊列化的」。隊列化的消息是由Windows放入程式消息隊列中的。在程式的消息循環中,重新傳回并配置設定給視窗消息處理程式。非隊列化的消息在Windows呼叫視窗時直接送給視窗消息處理程式。也就是說,隊列化的消息被「發送」給消息隊列,而非隊列化的消息則「發送」給視窗消息處理程式。任何情況下,視窗消息處理程式都将獲得視窗所有的消息–包括隊列化的和非隊列化的。

視窗消息處理程式是視窗的”消息中心”。

繼續閱讀