02、GetMessage
功能说明
WinCE下:该函数从呼叫进程的消息队列中检索消息,并且将所检索到的消息放入到一个指定的结构体(即MSG结构)中;
Win32下:该函数从呼叫进程的消息队列中检索消息,如果被检索到的消息为可分派消息,则该函数就分派该消息,如果被检索到的消息为不可分派消息,则GetMessage返回非正值,导致消息循环的结束。例如可分派的消息有:WM_PAINT、WM_SIZE、WM_CREATE等,不可分派的消息有WM_QUIT等。
函数格式
BOOL GetMessage(
LPMSG lpMsg, // 检索到的消息
HWND hWnd, // 窗口指向
UINT wMsgFilterMin, // 消息范围的下界限参数
UINT wMsgFilterMax // 上界限参数
);
参数说明
1>、lpMsg,【out】
指向MSG结构的指针,该结构用于存放从进程消息队列里检索(接收)到的消息。
2>、hWnd,【in】
窗口句柄,如果非零,则GetMessage只检索该窗口(也包括其子窗口)消息,如果为零,则GetMessage检索整个进程内的消息。非零窗口句柄必须属于GetMessage所属的进程。
3>、wMsgFilterMin,【in】
指定被检索的最小消息值的整数,通常使用WM_KEYFIRST指定第一键盘消息或WM_MOUSEFIRST指定鼠标消息。Windows XP中:在此处使用的是WM_INPUT,同时wMsgFilterMax指定的消息也只有WM_INPUT。
4>、wMsgFilterMax,【in】
指定被检索的最大消息值的整数,通常使用WM_KEYLAST指定最末键盘消息或WM_MOUSELAST指定最末鼠标消息。Windows XP中:在此处使用的是WM_INPUT,同时wMsgFilterMin指定的消息也只有WM_INPUT。
如果wMsgFilterMin和wMsgFilterMax都为零, 则GetMessage检索所有有效的信息(即,没有进行消息过滤,没有范围限制);同时,如果hWnd非零,则检索属于hWnd窗口的消息;如果hWnd为零,就是整个进程内的所有消息。
返回值
如果GetMessage检索到的消息不为WM_QUIT,则返回一个正值,如果检索到WM_QUIT消息,返回值是零,如果在检索消息时出现了错误,则返回值是-1。例如,当hWnd是无效的窗口句柄或lpMsg是空指针时。警示:因为返回值的三种状态,即:> 0、= 0、< 0,在使用GetMessage写程序时尽量避免如下格式的代码:
while (GetMessage(lpMsg, hWnd, 0, 0)) ...
因为当返回值为-1时,while循环还会继续执行的(读者可以自行验证),这样会导致应用程序出现致命错误而引起系统崩溃。所以建议写代码时应如下格式所示:
BOOL bRet = FALSE;
while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0) {
if (bRet == -1) { // handle the error and possibly exit
} else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
备注
1、应用程序在进行的消息循环内,通常用返回值来确定是否终止主消息循环并退出程序;
2、GetMessage函数获取消息之后,将会使该消息被消息队列所删除(WM_PAINT消息除外,至于WM_PAINT则只有在其被合并处理之后才被删除);
3、GetMessage只检索呼叫进程的消息,不检索属于其它进程的消息。
4、常数 WM_KEYFIRST和WM_KEYAST可作为过滤值检索与键盘输入相关的所有消息,常数WM_MOUSEFIRST和WM_MOUSELST可用来检索所有的鼠标消息;而在Windows XP中,二参数均使用WM_INPUT作为检索键盘和鼠标的输入。
5、当消息检索对象为进程消息队列时,如果进程消息队列正在进行消息存放操作,则GetMessage会等待这个存放操作结束后,再检索消息;如果消息队列为空,GetMessage也会等待的。
6、应用程序只能使用wMsgFilterMin和wMsgFilterMax参数的低字节,而高字节是保留给系统使用的。
适用
Windows NT: 3.1及以上版本;Windows:95及以上版本;Windows CE:1.0及以上版本:头文件:winuser.h;输入库:user32.Iib;Unicode:在Windows NT环境下以Unicode和ANSI方式实现。
应用举例
这是一个Win32程序的创建,在创建该Win32程序时,初始化程序入口函数:包括注册应用程序主窗口、注册主窗口事件发布函数、创建窗体和消息循环体。
HINSTANCE hinst; HWND hwndMain;
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) {
MSG msg; BOOL bRet; WNDCLASS wc;
UNREFERENCED_PARAMETER(lpszCmdLine); // 告诉编译器,该参数没有被引用,不要报警告
// Register the window class for the main window.
if (!hPrevInstance) {
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)WndProc; // 注册窗口事件发布函数
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon((HINSTANCE)NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor((HINSTANCE)NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = _T("MainMenu");
wc.lpszClassName = _T("MainWndClass");
if (!RegisterClass(&wc)) return FALSE; // 注册进程主窗口类
}
hinst = hInstance; // save instance handle
// Create the main window.
hwndMain = CreateWindow(_T("MainWndClass"), _T("Sample"),
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
(HWND)NULL, (HMENU)NULL, hinst, (LPVOID)NULL);
// If the main window cannot be created, terminate the application.
if (!hwndMain) return FALSE;
// Show the window and paint its contents.
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
// Start the message loop.
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0) { // 注册消息循环体
if (bRet == -1) { // handle the error and possibly exit
} else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// Return the exit code to the system.
return msg.wParam;
}