Win32学习笔记(五) 消息队列

本文解析了消息队列在Windows系统中的作用,区分了系统消息队列与程序消息队列,重点介绍了GetMessage函数的工作原理,包括消息的获取、转发与处理过程。实例展示了WM_PAINT和WM_TIMER消息的处理方式,以及GetMessage如何驱动窗口消息循环。
摘要由CSDN通过智能技术生成

1.消息队列的概念
消息队列是用于存放消息的队列
消息在队列中先入先出
所有窗口程序都具有消息队列
程序可以从队列中获取消息
2消息队列的分类
系统消息队列:由系统维护的消息队列,存放系统产生的消息,例如鼠标、键盘等
程序消息队列:属于每一个应用程序(线程)的消息队列。由应用程序(线程)维护。
通常消息会先进入系统消息队列,然后再通过窗口句柄分配到程序消息队列里。
PostMessage 是到了系统队列,SendMessage 直接将消息发送给窗口的处理函数,并等候处理结果。
3.消息和消息队列的关系
消息和消息队列的关系
1.当鼠标、键盘产生消息时,会将消息存放到系统消息队列
2.系统会根据存放的消息,找到对应程序的消息队列。
3.将消息投递到程序的消息队列中

根据消息和消息队列之间的使用关系,将消息分成两类:
队列消息 - 消息 的发送和获取,都是通过消息队列完成
非队列消息 - 消息的发送和获取,是直接调用消息的窗口处理完成。

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

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

4.深谈GetMessage
1.在程序(线程)消息队列查找消息,如果队列有消息,检查消息是否满足指定条件(HWND,ID范围),不满足条件就不会取出消息,否则从队列取出消息返回。
2.如果程序(线程)消息队列没有消息,向系统消息队列获取属于本程序的消息。如果系统队列的当前消息属于本程序,系统会将消息转发到程序消息队列中。
3.如果系统消息队列页没有消息,检查当前进程的所有窗口的需要重新绘制的区域,如果发现有需要绘制的区域,产生WM_PAINT消息,取得消息返回处理
4.如果没有重新绘制区域,检查定时器如果有到时的定时器,产生WM_TIMER,返回处理 执行
5.如果没有到时的定时器,整理程序的资源、内存等等。
6.GetMessage会继续等候吓一条消息。PeekMessage会返回FALSE,交出程序的控制权
注意:GetMessage如果获取到是WM_QUIT,函数会返回FALSE。

WM_PAINT
产生时间:当窗口需要绘制的时候
专职用法:用于绘图

声明窗口无效区域:需要重新绘制的区域
BooL InvalidateRect(
HWND hWnd. //窗口句柄
CONST RECT* IpRect, //区域的矩形坐标
BOOL bErase //重绘前是否先擦除
);

#include <windows.h>
HANDLE g_hOutput = 0;
void OnPaint(HWND hWnd) {
	const char* pszText = "WM_PAINT\n";
	WriteConsole(g_hOutput, pszText, strlen(pszText), NULL, NULL);

	PAINTSTRUCT ps = { 0 };
	HDC hdc = BeginPaint(hWnd, &ps);
	TextOut(hdc, 100, 100, "hello", 5);
	EndPaint(hWnd, &ps);
	//以上绘制的代码,必须放在处理WM_PAINT消息时调用.

}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM IParam)
{
	switch (msgID) {
	case WM_PAINT:
		OnPaint(hWnd);
		break;
	case WM_LBUTTONDOWN:
		InvalidateRect(hWnd, NULL, TRUE);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hWnd, msgID, wParam, IParam);
}

int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns, LPSTR lpCmdLine, int nCmdShow) {
	WNDCLASS wc = { 0 };
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wc.hCursor = NULL;
	wc.hIcon = NULL;
	wc.hInstance = hIns;
	wc.lpfnWndProc = WndProc;
	wc.lpszClassName = "Main";
	wc.lpszMenuName = NULL;
	wc.style = CS_HREDRAW | CS_VREDRAW;
	RegisterClass(&wc); //将以上所有赋值全部写入操作系统中
	//在内存创建窗口
	HWND hWnd = CreateWindow("Main", "window", WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL
		, hIns
		, NULL);
	// 4.更新和显示窗口
	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);
	// 5.应用程序消息循环
	MSG msg = { 0 };
	BOOL bRet;
	// 调用 GetMessage 函数从调用线程的消息队列中取得一个消息
	while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
	{
		if (bRet != -1)
		{
			TranslateMessage(&msg); // 将虚拟键消息转换为字符消息
			DispatchMessage(&msg); // 将消息分发到窗口处理
		}
	}

	return 0;
}
//需要在任务管理器中退出线程!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值