• MFC-对话框程序核心-IsDialogMessage函数-MSG 消息结构-GetMessage函数-DispatchMessage函数



    在MFC编程中,常用消息如下:

    #define WM_INITDIALOG                   0x0110
    #define WM_COMMAND                      0x0111
    #define WM_MOUSEMOVE                    0x0200
    #define WM_CREATE                       0x0001
    #define WM_DESTROY                      0x0002
    #define WM_MOVE                         0x0003
    #define WM_SIZE                         0x0005
    #define WM_PAINT                        0x000F
    #define WM_CLOSE                        0x0010
    #define WM_SHOWWINDOW                   0x0018
    #define SPI_SETGRADIENTCAPTIONS         0x1009
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

      如果需要Hook窗口消息,这些函数必须有一定程序的了解。

    1.IsDialogMessage函数

      函数功能:该函数决定一个消息是否指定给指定的对话框,如果是,则处理消息。 
      函数原型:BOOL IsDialogMessage(HWND hDlg,LPMSG IpMsg);
      hDlg:标识对话框。
      IpMsg:指向一个含有将被检测的消息的MSG结构。
      返回值:如果消息被处理,则返回值为非零值;如果消息没有被处理,则返回值为零。
      检测该消息是否是对应句柄的对话框消息,如果是,则交个user32.dll模块对齐进行处理,实际上user32.dll模块将其转发给对话框所属的窗口函数了,在对话框所属的窗口函数里面对消息进行判断,最终调用消息对应的函数,而消息对应的函数是我们之前映射好的,已经存在于对话框消息映射表了。

    while(GetMessage(&stMsg,NULL,0,0))
    {
    	if(!IsDialogMessage(hDlg,&stMsg))
    	{
    		TranslateMessage(&stMsg);
    		DispatchMessage(&stMsg);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    MSG 消息结构
      在 Windows 程序中,消息是由 MSG 结构体来表示的。
      结构原型:

    typedef struct tagMSG {
      HWND   hwnd;
      UINT   message;
      WPARAM wParam;
      LPARAM lParam;
      DWORD  time;
      POINT  pt;
    } MSG, *PMSG, *LPMSG;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    获取参数,然后转发。

    2.GetMessage函数

      在创建窗口、显示窗口、更新窗口后,我们需要编写一个消息循环,不断地从消息队列中取出消息,并进行响应。要从消息队列中取出消息,我们需要调用GetMessage()函数,该函数的原型声明如下:

    BOOL GetMessage(
              LPMSG lpMsg,              // address of structure with message
              HWND hWnd,                // handle of window
              UINT wMsgFilterMin,       // first message
              UINT wMsgFilterMax        // last message
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

      参数lpMsg指向一个消息(MSG)结构体。GetMessage从线程的消息队列中取出的消息信息将保存在该结构体对象中。
      参数hWnd指定接收属于哪一个窗口的消息。通常我们将其设置为NULL,用于接收属于调用线程的所有窗口的窗口消息。
      参数wMsgFilterMin指定要获取的消息的最小值,通常设置为0。
      参数wMsgFilterMax指定要获取的消息的最大值。如果wMsgFilterMin和wMsgFilter Max都设置为0,则接收所有消息。
      GetMessage函数接收到除WM_QUIT外的消息均返回非零值。对于WM_QUIT消息,该函数返回零。如果出现了错误,该函数返回-1,例如,当参数hWnd是无效的窗口句柄或lpMsg是无效的指针时。

    3.DispatchMessage函数

    WINUSERAPI
    LRESULT
    WINAPI
    DispatchMessageA(
        _In_ CONST MSG *lpMsg);
    
    • 1
    • 2
    • 3
    • 4
    • 5

      函数原型:LONG DispatchMessage(CONST MSG*lpmsg);
      参数:lpmsg:指向含有消息的MSG结构的指针。
      返回值:返回值是窗口程序返回的值。尽管返回值的含义依赖于被调度的消息,但返回值通常被忽略。

    4.窗口过程函数模型

    LONG OldWndProc = 0;
    LRESULT CALLBACK WindowProc2(  HWND hwnd,      // handle to window
    							UINT uMsg,      // message identifier
    							WPARAM wParam,  // first message parameter
    							LPARAM lParam   // second message parameter
    							)
    {
    	if (uMsg == WM_KEYDOWN)
    	{
    		if (wParam == VK_F6)
    		{
    			AfxMessageBox(L"您按下了F6键");
    		}
    	}
    	return CallWindowProc((WNDPROC)OldWndProc,hwnd,uMsg,wParam,lParam);
    }
     
    void CttDlg::OnBnClickedOk()
    {
    	// TODO: 在此添加控件通知处理程序代码
    	OldWndProc = ::SetWindowLong(m_hWnd,GWL_WNDPROC,(LONG)WindowProc2);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    5.作者答疑

      如有疑问,敬请留言。

  • 相关阅读:
    Java 多线程为啥要有ThreadLocal,怎么用,这篇讲全了!
    C# 图解教程 第5版 —— 第6章 方法
    计算空间物体包围球的两种算法实现
    开发者模式:单例模式
    NFT Insider #69:星巴克将公布基于Web3的忠诚度计划,林俊杰宣布持有蒂芙尼NFT
    【C++入门系列】——命名空间和输入输出
    为百度翻译花了3元,感觉还是值得的
    SAP MM学习笔记36 - 释放支付保留的发票
    julia系列3:函数、模块与宏
    java计算机毕业设计springboot+vue毕业设计选题系统
  • 原文地址:https://blog.csdn.net/m0_67316550/article/details/125513711