win32编程 -- 消息机制(三)

简介: win32编程 -- 消息机制(三)

一、消息队列


1、消息队列用于存放消息的一个队列,消息在队列中先入先出。所有窗口程序都具有消息队列。程序可以从队列中获取消息。


2、消息队列的类型


系统消息队列:由系统维护的消息队列。存放系统产生的消息,例如鼠标、键盘等。只有一个,系统启动的时候就有


程序消息队列:属于每一个应用程序(线程)的消息队列。由应用程序(线程)维护。


3、消息队列的关系


当鼠标、键盘产生消息时,会将消息存放到系统消息队列    


系统会根据存放的消息,找到对应窗口的消息队列


将消息投递到程序的消息队列中


二、消息和消息队列


1、消息分成两类:=


队列消息:消息的发送和获取,都是通过消息队列完成。


非队列消息:消息的发送和获取,是直接调用消息的窗口处理完成。


2、队列消息


消息发送后,首先放入队列,然后通过消息循环,从队列当中获取。 GetMessage,从消息队列中获取消息,PostMessage , 将消息投递到消息队列,常见队列消息:WM_PAINT、键盘、鼠标、定时器。


3、非队列消息,消息发送时,首先查找消息接收窗口的窗口处理函数,直接调用处理函数,完成消息。 SendMessage,直接将消息发送给窗口的处理函数,并等候处理结果。 常见消息:WM_CREATE、WM_SIZE等。


三、消息的获取


1、消息循环


GetMessage /PeekMessage从程序的消息队列当中,获取到消息。


TranslateMessage:检查获取到的消息,如果发现是按键消息,产生一个字符消息,并放入程序的消息队列。


DispatchMessage:根据消息,找到窗口处理函数,调用窗口处理函数,完成消息的处理。


2、GetMessage/PeekMessage次序


在程序(线程)消息队列查找消息,如果队列有消息,检查消息是否满足指定条件(HWND,ID范围),不满足条件就不会取出消息,否则从队列取出消息返回。


如果程序(线程)消息队列没有消息,向系统消息队列获取属于本程序的消息。如果系统队列的当前消息属于本程序,系统会将消息转发到程序消息队列中。


如果系统消息队列也没有消息,检查当前进程的所有窗口的需要重新绘制的区域,如果发现有需要绘制的区域,产生WM_PAINT消息,取得消息返回处理。


如果没有重新绘制区域,检查定时器如果有到时的定时器,产生WM_TIMER,返回处理执行。


如果没有到时的定时器,整理程序的资源、内存等等。


GetMessage会继续等候下一条消息。PeekMessage会返回FALSE,交出程序的控制权。


注意:GetMessage如果获取到是WM_QUIT,函数会返回FALSE。


四、消息的发送


SendMessage:发送消息到指定的窗口,并等候对方将消息处理,然后消息执行结果,用于非队列消息的发送。


PostMessage:将消息放到消息队列中,立刻返回,用于队列消息的发送。无法获知消息是否被对方处理。


五、绘图消息,WM_PAINT


1、当窗口需要绘制的时候,会发送窗口处理函数。/2、窗口无效区域 - 被声明成需要重新绘制的区域。    


BOOL InvalidateRect(
       HWND hWnd,           //窗口句柄
       CONST RECT* lpRect,         //区域的矩形坐标
BOOL bErase          //重绘前是否先擦除
);

3、在程序中,如果需要绘制窗口,调用函数声明窗口无效区域。 WM_PAINT参数     - WPARAM - 不使用     - LPARAM  - 不使用    


4、消息处理步骤


开始绘图处理


HDC BeginPaint(
       HWND hwnd, //绘图窗口
       LPPAINTSTRUCT lpPaint //绘图参数的BUFF
); //返回绘图设备句柄HDC

绘图


结束绘图处理


BOOL EndPaint(
       HWND hWnd, //绘图窗口
       CONST PAINTSTRUCT * lpPaint  //绘图参数的指针BeginPaint返回
);

5、相关代码


#include <windows.h>
HINSTANCE g_hInstance = 0;//接收当前程序实例句柄
HANDLE g_输出句柄 = 0;//接收标准输出句柄
void 绘图(HWND hWnd)
{
const wchar_t* str = L"我是绘图";
       WriteConsole(g_输出句柄, str, wcslen(str), NULL, NULL);
//代码必须写到wm_paint消息处理中调用
       PAINTSTRUCT p = {0};//创建画笔
       HDC hdc = BeginPaint(hWnd, &p);//返回画图的位置
       TextOut(hdc, 100, 100, L"哎呦",2);
       EndPaint(hWnd, &p);
}
//2、窗口处理函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID,
       WPARAM wParam, LPARAM lParam)
{
//7、处理消息
switch (msgID)
       {
case WM_LBUTTONDOWN:
              InvalidateRect(hWnd, NULL, TRUE);//按下左键绘图
break;
case WM_PAINT:
              绘图(hWnd);
break;
case WM_DESTROY:
              PostQuitMessage(0);//销毁窗口
break;
       }
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//3、注册函数,第一个参数,窗口类名称,第二个参数,指向窗口处理函数的函数指针
void Register(LPCWSTR lpClassName, WNDPROC winProc)
{
       WNDCLASSEX wc = { 0 };
       wc.cbSize = sizeof(wc);//结构体大小
       wc.cbClsExtra = 0;//窗口类的申请缓存区,0表示不开启缓存
       wc.cbWndExtra = 0;//窗口的申请缓存区,0表示不开启缓存
       wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);//背景颜色,一般白色
       wc.hCursor = NULL;//设置光标。null表示默认
       wc.hIcon = NULL;//默认左上角的图标
       wc.hInstance = g_hInstance;//第一个参数实例句柄,可以找到进程在那块内存
       wc.lpfnWndProc = winProc; //lp 一般都是指针,处理函数名或指针
       wc.lpszClassName = lpClassName;//窗口类名称,比如公司名字
       wc.lpszMenuName = NULL;//没有菜单用null
       wc.style = CS_HREDRAW | CS_VREDRAW;//窗口变化,会重绘,窗口类的一般风格
       RegisterClassEx(&wc);
}
//4、创建窗口,(窗口类名称,窗口标题栏名称)
HWND CreateMain(LPCWSTR lpClassName, LPCWSTR lpWindowName)
{
       HWND hWnd = CreateWindowExW(0, lpClassName,lpWindowName,  WS_OVERLAPPEDWINDOW, 100, 100, 500, 600, NULL, NULL, g_hInstance, NULL);
return hWnd;
}
//5、显示窗口(窗口句柄)
void Display(HWND hWnd)
{
       ShowWindow(hWnd, SW_SHOW);//句柄,显示方式
       UpdateWindow(hWnd);//调用一次刷新窗口
}
//6、消息循环
void Message()
{
       MSG nMsg = { 0 };
while (GetMessage(&nMsg, nullptr, 0, 0))
       {
              TranslateMessage(&nMsg);
              DispatchMessage(&nMsg);
       }
}
//1、入口函数
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevIns, LPSTR lpCmdLine, int   nCmdShow)
{
       AllocConsole();//显示dos窗口
       g_输出句柄 = GetStdHandle(STD_OUTPUT_HANDLE);
       g_hInstance = hInstance;
       Register(L"主", WndProc);
       HWND hWnd = CreateMain(L"主", L"主窗口");
       Display(hWnd);
       Message();
return 0;
}

6、运行结果


0a2653c851af460fa595bd959398a8f1.png

目录
相关文章
|
3月前
|
Windows
win32编程 -- 消息机制(一)
win32编程 -- 消息机制(一)
17 0
|
3月前
win32编程 -- 消息机制(二)
win32编程 -- 消息机制(二)
18 0
win32编程 -- 消息机制(二)
|
3月前
|
消息中间件
win32编程 -- 消息机制(三)
win32编程 -- 消息机制(三)
17 0
|
3月前
win32编程 -- 键盘消息
win32编程 -- 键盘消息
21 0
|
3月前
win32编程 -- 鼠标消息
win32编程 -- 鼠标消息
15 0
|
3月前
win32编程 -- 定时消息
win32编程 -- 定时消息
9 0
|
3月前
|
安全 Windows 容器
win32编程 -- 进程
win32编程 -- 进程
18 0
|
12月前
|
数据可视化 C++ Windows
非可视化编程的windows窗口 C++ 代码设计:附例程并多多知识点
非可视化编程的windows窗口 C++ 代码设计:附例程并多多知识点
171 0
|
消息中间件 程序员 API
WINDOWS核心编程--Windows程序内部运行机制(下)
WINDOWS核心编程--Windows程序内部运行机制
155 0
WINDOWS核心编程--Windows程序内部运行机制(下)
|
消息中间件 存储 缓存
WINDOWS核心编程--Windows程序内部运行机制(上)
WINDOWS核心编程--Windows程序内部运行机制
281 0
WINDOWS核心编程--Windows程序内部运行机制(上)