Win32消息处理API---GetMessage

    技术2022-05-11  15

     

    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;

    }

     


    最新回复(0)