win32——消息机制
消息处理是win32里面很重要的一部分。今天主要介绍win32的消息机制和消息处理的相关函数。
本次使用的开发环境是vs2013,使用的开发语言是C/C++, 创建的项目是win32项目
一.消息基本概念
1.1 消息队列:
当windows应用程序开始执行时,系统会为该程序建立一个消息
队列用于存放消息,然后用getmessage等进行消息获取处理。
程序从队列中获取消息后处理.分为系统消息队列(有系统维护,
存放系统产生的消息如键盘鼠标消息)程序消息队列(存放应用
程序消息应用程序自行处理)
过程:事件->封装消息->投递消息队列->消息相应
备注: //window最大的特色是良好的用户交互性
//window是事件驱动的操作系统,事件怎么驱动?通过消息来驱动
//产生消息、传递消息、处理消息的过程被称为windows的消息机制
//windows操作系统为每一个窗口都提供了一个消息队列
1.2 消息分类:
系统消息:系统已经定义好的消息WM_DESTRY等(0~0x03FF)
自定义消息:用户自行定义 WM_USER+10等;(0x400~0x7fff)
队列消息:消息发送和获取都是在消息队列
(WM_PAINT,鼠标键盘定时器消息)
GetMessage--从消息队列获取消息
PostMessage-将消息投放到消息队列
非队列消息:不进队列直接消息处理函数完成
(WM_CREATE,WM_SIZE)
1.3 MSG结构体信息
typedef struct tagMSG {
HWND hwnd; //指定消息所处的窗口
UINT message; //指定消息的标识符 (宏定义处理方便)
WPARAM wParam;//MSG的附加消息
LPARAM lParam;//附加消息
DWORD time;//投递到消息队列的事件
POINT pt;//投递时鼠标当前位置
} MSG
二.消息获取/发送函数
GetMessage-从消息队列中获取一个消息后移除(堵塞),当队列中
无消息获取则等候下一个消息
PeekMessage---查看消息队列中消息,非堵塞,无消息是返回false
PeekMessage()常用的一种用法:
//ZeroMemory(&msg, sizeof(msg));
//while (msg.message != WM_QUIT)//消息的id不是退出消息
//{
// if (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))
// {
// if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))//翻译快捷键
// {
// TranslateMessage(&msg);//翻译消息(并不是所有的消息都需要翻译)
// DispatchMessage(&msg);//投递消息
// }
// }
消息处理常用的函数
SendMessage--把消息发送到指定窗口,直接消息处理函数处理,获取到返回结果后结束(堵塞)
PostMessage--将消息放入指定窗口消息队列,不等待结果直接返回(非堵塞)
TranslateAccelerator(msg.hwnd, hAccelTable, &msg) //翻译快捷键
TranslateMessage(&msg);//翻译消息(并不是所有的消息都需要翻译, 翻译后的消息进消息队列)
DispatchMessage(&msg);//投递消息 投递给消息处理函数
//GetMessage 是从消息队列一次取出一个消息,阻塞的过程,没有消息一直在等待,如果有消息,分两种情况
//一种得到普通的消息,返回true;一种是得到一个wm_quit(退出),返回false;//PeekMessage 从消息队列取消息,非阻塞的过程 ,如果有消息,返回true,如果没有消息,返回false
三.消息处理过程(getMessage)
从当前程序的消息队列中进行查找,如果有消息则判断是否满足窗口句柄,id范围等条件.满足的话取出消息发送给消息处理函数后返回,如果不满足则向系统消息队列获取属于本进程的消息,如果找到满足条件的则把系统中消息队列中的存入本程序消息队列中.如果系统消息队列也没有则检查窗口是否重绘,是则产生WM_PAIT消息,然后返回处理,如果没有重绘,查看定时器有没有需要处理,有则产生WM_TIMER消息.如果没定时器则优化资源,处理内存.然后等候下一个消息(PEEKmessage不会等待,会直接返回false后交出程序的控制权)
处理过程:查找本程序消息---> 如果消息队列有则判断是否满足条件(ID)—>满足取出消息(不满足不取)-->查窗口相关系统消息(如无程序消息)-->转去程序消息(如有)->检查重绘(如无系统消息)---->发送wm_paint消息----->检查定时器(如无重画)->整理程序资源内存->等待
四.控制台显示(穿插)
1.AllocConsole() 为调用进程分配一个新的控制台
2.获取标准输出HANDLE g_h = GetStdHandle(STD_OUTPUT_HANDLE)
3.char szText[256] = { 0 }; sprintf(szText, “%s\n”, “wm_size” );
BOOL WriteConsole(
HANDLE hConsoleOutput,//操作的句柄
CONST VOID * lpBuffer,//需要写入的内容
DWORD nNumber, //写入的字节数
LPDWORD lpNu,//指向接收实际写入字节数的变量指针可为NULL
LPVOID lpReserved//必须为NULL );