一. 消息与事件
Windows中的事件是一个“动作”,这个动作可能是用户操作应用程序产生的,也可能是Windows自己产生的。
Windows为了能够准确的描述这些信息,提供了一个结构体:MSG,该结构体里面记录的事件的详细信息。
二. 消息流程
1. 系统 或 用户触发某个动作 //事件
2. 系统将这些信息存储到MSG结构体中 //消息
3. 系统将该消息存储到相关应用程序的消息队列中
MSG Msg;
4. while(GetMessage(&Msg,NULL,0,0)) //从队列中获取消息
{
TranslateMessage(&Msg); //翻译消息
DispatchMessage(&Msg); //分派消息
}
5. DispatchMessage将加工过的消息传递给操作系统
6. 系统调用窗口回调函数
三. 创建一个窗口
注意:所谓注册窗口需要传入一个自定义的窗口类型,之后创建的窗口就按照此类型创建。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "windows.h"
using namespace std;
//APIENTRY(API入口) __stdcall
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow) {
DWORD x = (DWORD)hInstance;
TCHAR className[] = TEXT("My First Window");
//1. 设计窗口类
WNDCLASS wndclass = { 0 }; //即使不用的参数也要赋值为0,否则窗口创建不出来
wndclass.hbrBackground = (HBRUSH)COLOR_MENU; //窗口的背景色
wndclass.lpfnWndProc = WindowProc; //窗口过程函数
wndclass.lpszClassName = className; //窗口类的名字
wndclass.hInstance = hInstance; //定义窗口类的应用程序的实例句柄
//2. 注册窗口
RegisterClass(&wndclass);
//3. 创建窗口
HWND hwnd = CreateWindow(
className, //类名
TEXT("我的第一个窗口"), //窗口标题
WS_OVERLAPPEDWINDOW, //窗口外观样式
10, //相对于父窗口的X坐标
10, //相对于父窗口的Y坐标
600, //窗口的宽度
300, //窗口的高度
NULL, //父窗口句柄,为NULL
NULL, //菜单句柄,为NULL
hInstance, //当前应用程序的句柄
NULL); //附加数据一般为NULL
if (hwnd == NULL) //是否创建成功
return 0;
//4. 显示窗口
ShowWindow(hwnd, SW_SHOW);
//5. 消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
下面就是回调函数了,也就是具体的消息处理函数。
回调函数并不处理所有的消息,它将不处理的消息调用DefWindowProc函数返回给操作系统处理。
用户点击窗口红叉时操作系统仅仅将它关闭,但并不会销毁。需要需要添加PostQuitMessage(0);,否则就有可能内存泄漏。
//6. 回调函数
LRESULT CALLBACK WindowProc(
IN HWND hwnd,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
{
switch (uMsg)
{
//窗口消息
case WM_CREATE:
{
//DbgPrintf("WM_CREATE %d %d\n", wParam, lParam);
CREATESTRUCT* createst = (CREATESTRUCT*)lParam;
//DbgPrintf("CREATESTRUCT %s\n", createst->lpszClass);
return 0;
}
case WM_MOVE:
{
//DbgPrintf("WM_MOVE %d %d\n", wParam, lParam);
POINTS points = MAKEPOINTS(lParam);
//DbgPrintf("X Y %d %d\n", points.x, points.y);
return 0;
}
case WM_SIZE:
{
//DbgPrintf("WM_SIZE %d %d\n", wParam, lParam);
int newWidth = (int)(short)LOWORD(lParam);
int newHeight = (int)(short)HIWORD(lParam);
//DbgPrintf("WM_SIZE %d %d\n", newWidth, newHeight);
return 0;
}
case WM_DESTROY:
{
//DbgPrintf("WM_DESTROY %d %d\n", wParam, lParam);
PostQuitMessage(0);
return 0;
}
//键盘消息
case WM_KEYUP:
{
//DbgPrintf("WM_KEYUP %d %d\n", wParam, lParam);
return 0;
}
case WM_KEYDOWN:
{
//DbgPrintf("WM_KEYDOWN %d %d\n", wParam, lParam);
return 0;
}
//鼠标消息
case WM_LBUTTONDOWN:
{
//DbgPrintf("WM_LBUTTONDOWN %d %d\n", wParam, lParam);
POINTS points = MAKEPOINTS(lParam);
//DbgPrintf("WM_LBUTTONDOWN %d %d\n", points.x, points.y);
return 0;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam); //window提供的默认的消息处理函数
}