天天看点

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呼叫窗口时直接送给窗口消息处理程序。也就是说,队列化的消息被「发送」给消息队列,而非队列化的消息则「发送」给窗口消息处理程序。任何情况下,窗口消息处理程序都将获得窗口所有的消息–包括队列化的和非队列化的。

窗口消息处理程序是窗口的”消息中心”。

继续阅读