
抓取消息:
GetMessage:从系统获取消息,将消息从系统中移除,阻塞函数。当系统无消息时,会等候下一条消息。
PeekMessage:以查看的方式从系统获取消息,可以不将消息从系统移除,非阻塞函数。当系统无消息时,返回FALSE,继续执行后续代码。
BOOL PeekMessage(
LPMSG lpMsg,// message information
HWND hWnd,//handle to window
UINT wMsgFilterMin,//first message
UINT wRemoveMsg//移除标识
PM_REMOVE/PM_NOREMOVE
);
发送消息:
SendMessage:发送消息,会等候消息处理的结果。
PostMessage:投递消息,消息发出后立刻返回,不等候消息的执行结果。
BOOL SendMessage/PostMessage(
HWND hWnd, //消息发送的目的窗口
UINT Msg, //消息ID
WPARAM wParam, //消息参数
LPARAM lParam //消息参数
);
消息的分类:
系统消息:ID范围0-0x03ff
由系统定义好的消息,可以在程序中直接使用。
用户自定义消息:ID范围0x0400-0x7fff(31743)
由用户自定义,满足用户自己的需求。
由用户自己发出消息,并相应处理。
自定义消息宏:WM_USER
消息队列:
每个窗口程序都有消息队列
程序可以冲队列中获取消息
只有GetMessage会到消息队列中抓消息
GetMessage只能从消息队列抓消息
系统消息队列:由系统维护的消息队列。存放系统产生的消息,例如鼠标、键盘。
程序消息队列:属于每一个应用程序(线程)的消息队列。由应用程序(线程)维护。
消息和消息队列的关系:
当鼠标、键盘产生消息,会将消息存放到系统消息队列,然后系统找到对应程序把消息投递到程序的消息队列中
根据消息和消息队列之间的使用关系,消息分两类:
队列消息:消息的发送和获取,都是通过消息队列完成。
非队列消息:消息的发送和获取,是直接调用消息的窗口处理完成。
队列消息:消息发送后,先进队列,然后通过消息循环,从队列中获取。
GetMessage:从消息队列获取消息
PostMessage:将消息投递到消息队列
常见队列消息:WM_QUIT、WM_PAINT、键盘、鼠标、定时器。
非队列消息:消息发送时,首先查找消息接收窗口的处理函数,直接调用处理函数,完成消息。
SendMessage:直接将消息发送给窗口处理函数,并等候处理结果。
常见的非队列消息:WM_CREATE、WM_SIZE等。
大多数消息本身没有队列或者非队列的属性。取决于程序员是否让他进队列。
GetMessage详解:
在程序(线程)消息队列查找消息,如果队列有消息,检查消息是否满足指定条件(HWND, ID范围),不满足条件就不会取出消息,否则从队列取出消息返回。
如果程序(线程)消息队列没有消息,GetMessage会向系统质询,系统会检查系统消息队列,如果有该程序的消息,系统会将消息转发到程序消息队列中。
如果系统消息队列也没有消息,检查当前进程的所有窗口的需要重新绘制的区域,如果发现有需要绘制的区域,产生WM_PAINT消息,发送到系统消息队列,系统将它投递到程序消息队列,GetMessage从程序消息队列中取得此消息返回处理。
如果没有重新绘制的区域,检查定时器如果有到时的定时器,产生WM_TIMER,和上述过程一样返回处理执行。
如果没有到时的定时器,整理程序的资源、内存等等。
GetMessage会继续等候下一条消息。PeekMessage会返回FALSE,交出程序的控制权。
注意:GetMessage如果获取到的是WM_QUIT,函数会返回FALSE。
WM_PAINT消息:
产生时间:当窗口需要绘制而且GetMessage没抓到消息的时候。还有ShowWindow的时候。
附带消息:wParam: 0。
lParam: 0。
专职用法:用于绘图。
窗口无效区域:需要重新绘制的区域。
BOOL InvalidateRect(
//这个函数一调,说明需要重绘窗口了。
HWND hWnd,//窗口句柄
ConST RECT* lpRect,//区域的矩形坐标
BOOL bErase//重绘前是否先擦除
);
WMP_PAINT消息处理步骤:
1.开始绘图
HDC BeginPaint(
HWND hWnd,
LPPAINTSTRUCT lpPaint//绘图参数的缓冲区
);返回绘图设备句柄HDC
2.正式绘图
3.结束绘图
BOOL EndPaint(
HWND hWnd
ConST PAINTSTRUCT* lpPaint //绘图参数的指针BeginPaint返回
);
#define _CRT_SECURE_NO_WARNINGS #include#include #define WM_MYMESSAGE WM_USER//WM_USER的取值是0x0400,从他开始包括他往后31742个字节都可以自定义消息。 HANDLE g_hOutput = 0; //接受标准输出句柄 void onCreate(HWND hWnd, LPARAM lParam) { CREATESTRUCT* pcs = (CREATESTRUCT*)lParam; char* pszText = (char*)pcs->lpCreateParams; MessageBox(NULL, pszText, "Infor", MB_OK); PostMessage(hWnd, WM_MYMESSAGE, 1, 2); CreateWindowEx(0, "EDIT", "hello", WS_CHILD | WS_VISIBLE | WS_BORDER, 0, 0, 200, 200, hWnd, NULL, 0, NULL); } void onSize(HWND hWnd, LPARAM lParam) { short nWidth = LOWORd(lParam); short nHeight = HIWORd(lParam); char szText[256] = { 0 }; sprintf(szText, "WM_SIZE:宽:%d, 高:%dn", nWidth, nHeight); WriteConsole(g_hOutput, szText, strlen(szText), NULL, NULL); } void onMyMessage(HWND hWnd, WPARAM wParam, LPARAM lParam) { char szText[256] = { 0 }; sprintf(szText, "自定义消息被处理:wParam = %d, lParam = %dn", wParam, lParam); MessageBox(hWnd, szText, "Infor", MB_OK); } void onPaint(HWND hWnd) { char pszText[] = TEXT("WM_PAINTn"); 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); } //窗口处理函数(自定义,处理消息) LRESULT CALLBACK WndProc(HWND hWnd, UINT msgId, WPARAM wParam, LPARAM lParam) { switch (msgId) { case WM_LBUTTONDOWN: //InvalidateRect(hWnd, NULL, true); break; case WM_PAINT: onPaint(hWnd); break; case WM_MYMESSAGE: onMyMessage(hWnd, wParam, lParam); break; case WM_SIZE: onSize(hWnd, lParam); break; case WM_CREATE: onCreate(hWnd, lParam); break; case WM_DESTROY: //PostQuitMessage(0); PostMessage(hWnd, WM_QUIT, 0, 0); break; case WM_SYSCOMMAND: if (wParam == SC_CLOSE) { int nRet = MessageBox(hWnd, "是否退出", "注意", MB_YESNO); if (nRet != IDYES) { return 0; } break; } } return DefWindowProc(hWnd, msgId, wParam, lParam); } //入口函数 int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns, LPSTR lpCmdLine, int nCmdShow) { AllocConsole();//增加dos窗口 g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE); //注册窗口类 WNDCLASS wc = { 0 }; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.hCursor = NULL; wc.hIcon = NULL; wc.hInstance = hIns; wc.lpfnWndProc = WndProc; TCHAR name[] = TEXT("Main"); wc.lpszClassName = name; wc.lpszMenuName = NULL; wc.style = CS_HREDRAW | CS_VREDRAW; RegisterClass(&wc);//将以上所有赋值全部写入 *** 作系统。 char pszText[] = "hello data"; //在内存中创建窗口 HWND hWnd = CreateWindow(name, TEXT("title"), WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, hIns, pszText); //注册子窗口类 wc = { 0 }; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.hCursor = NULL; wc.hIcon = NULL; wc.hInstance = hIns; wc.lpfnWndProc = DefWindowProc; TCHAR name1[] = TEXT("Child"); wc.lpszClassName = name1; wc.lpszMenuName = NULL; wc.style = CS_HREDRAW | CS_VREDRAW; RegisterClass(&wc);//将以上所有赋值全部写入 *** 作系统。 //在内存中创建子窗口 //HWND hChild1 = CreateWindowEx(0, name1, TEXT("ChildTitle"), WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0, 0, 200, 200, hWnd, NULL, hIns, NULL); //HWND hChild2 = CreateWindowEx(0, "Child", "c2", WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW, 200, 0, 200, 200, hWnd, NULL, hIns, NULL); //显示窗口 ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); //消息循环 MSG nMsg = { 0 }; while (1) { if (PeekMessage(&nMsg, NULL, 0, 0, PM_NOREMOVE)) { //有消息 if (GetMessage(&nMsg, NULL, 0, 0)) { TranslateMessage(&nMsg); DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理 } else return 0; } else { //没消息,空闲处理 char temp[] = "1 2 3 4 5 6 7 8 9 "; WriteConsole(g_hOutput, temp, strlen(temp), NULL, NULL); } } return 0; }
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)