MFC自定义消息用法总结

来源:互联网 发布:女演员真实身高 知乎 编辑:程序博客网 时间:2024/06/05 11:37


      接触MFC有半年时间了,对于消息这一块一直不是很懂,中间有编过一些小程序也用到了消息,也只是把别人的粘贴过来,没有细研究。但是,对于MFC来讲这一部分无疑是很重要的一部分,是必须要搞懂的。今天花了一下午的时间将研究了一下消息,现在把它记下来,方便自己以后学习,也希望能给同样初学者一些帮助。

      首先说一下消息的工作机制:

      经常听到的一句话就是window是通过消息机制进行驱动的。那这个是什么意思了?打个比方,新建一个基于对话框的MFC程序,添加一个按钮,添加消息响应函数。我们都知道,当按下这个按钮的时候就会执行这个消息响应函数的内容。那为什么按下这个按钮就会执行这个函数了而不是其他的函数了?它是怎么知道是对应的按钮,而且是被按下了,我们先来看一下消息的结构。

     消息的形式是这样定义的:

 typedef structtagMSG { // msg
HWND hwnd; //
窗口句柄
UINT message; //
消息常量标识符
WPARAM wParam; //32
位消息的特定附加信息,具体表示什么处决于message
LPARAM lParam; //32
位消息的特定附加信息,具体表示什么处决于message
DWORD time; //
消息创建时的时间
POINT pt; //
消息创建时的鼠标位置
} MSG;


hwnd接收消息的32位窗口句柄。窗口可以是任何类型的屏幕对象,
因为Win32能够维护大多数可视对象的句柄(窗口、对话框、按钮、编辑框等)
message
用于区别其他消息的常量值,这些常量可以是Windows单元中预定义的常量,也可以是自定义的常量。
wParam
通常是一个与消息有关的常量值,也可能是窗口或控件的句柄。
lParam
通常是一个指向内存中数据的指针。

      现在我们知道消息的结构是什么样子了,为了全面的了解消息。我们来定义一个消息。

  1. 在头文件中注册消息:

static UINT WM_MY_MESSAGE =RegisterWindowMessage("Message");

----定义了一个名称为WM_MY_MESSAGE的消息。

  1. 在头文件中定义消息映射函数:

protected:
  //{{AFX_MSG(CMessageTestView)
  afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAMlParam); //此行为添加代码


----定义了一个消息响应函数为OnMyMessage,那么后面两个参数是什么意思了,我们后面解释。
  //}}AFX_MSG
  DECLARE_MESSAGE_MAP()

  1. 在其MessageTestView.cpp中,
      先要声明响应消息:
      BEGIN_MESSAGE_MAP(CMessageTestView, CEditView)
      //{{AFX_MSG_MAP(CMessageTestView)
    ON_REGISTERED_MESSAGE(WM_MY_MESSAGE,OnMyMessage)//
    此行添加代码定义唯一消息 

    ---将消息和消息响应函数关联起来 

    //}}AFX_MSG_MAP

  2. 再添加消息响应的函数实现:
    LRESULT CMessageTestView::OnMyMessage(WPARAM wParam, LPARAM lParam)
    { return 0;} 

至此,我们就自定义了一个完整的消息。剩下就是怎么触发这个消息了。触发消息分为两种:

第一种,用SendMessage或者PostMessage函数来实现。

PostMessage(unit Message, WPARAM wParam, LPARAM lParam)函数需要提供消息的名称,还有那个参数默认值为0,在消息响应函数处,我们就能获取到这两个参数。这种用法常用于类之间、进程之间的通信。

第二种,消息响应函数,响应窗口操作。这个就用一个经典的托盘实例来说一下。这是托盘的响应函数,从中我们可以看出wparam参数一般定义了控件的值,而lParam参数定义了操作的内容。

LRESULTCSMMSDlg::OnShowTask(WPARAM wParam, LPARAM lParam)

{

   if(wParam !=IDR_MAINFRAME)//当我们点击托盘图标的时候,wparam参数将它的值传过来

     return 1;

   switch(lParam)//lParam参数,定义了操作的内容

   {

   caseWM_RBUTTONUP:                       //右键起来时弹出菜单

      {

          LPPOINT lpoint =new tagPOINT;

          ::GetCursorPos(lpoint);                   

          CMenu menu;

          menu.CreatePopupMenu();                   

          menu.AppendMenu(MF_STRING,WM_DESTROY,"退ª??");

          //menu.AppendMenu(MF_STRING,WM_DESTROY, "?º?");

          menu.TrackPopupMenu(TPM_LEFTALIGN,lpoint->x ,lpoint->y,this);

          HMENU hmenu = menu.Detach();

          menu.DestroyMenu();

          deletelpoint;

      }

      break;

   caseWM_LBUTTONDBLCLK:                                //左键双击

      {

          this->ShowWindow(SW_SHOWNORMAL);        

      }

      break;

   }

   return 0;

}

回到刚才那个按钮消息响应函数,我们发现它并没有任何参数,这为什么了?实际上所有的消息响应都有WPARAMLPARAM的存在,只是有些消息响应WPARAMLPARAM没有意义,所以在MFC封装后有些固定的消息响应函数看不到WPARAMLPARAM,但依然可以通过GetCurrentMessage()取得当前的消息来查看WPARAMLPARAM

下面给出获取的代码:

  const MSG*pMsg=GetCurrentMessage();

     WPARAMwParam=pMsg->wParam;

     LPARAMlParam=pMsg->lParam;

     UINTmessage=pMsg->message; 

     if(wParam==IDC_BUTTON1)

     {

            AfxMessageBox("aa");

     } 

     switch(lParam)

     {

     caseWM_LBUTTONDOWN:

            {

                   AfxMessageBox("WM_LBUTTONDBLCLK");

            }

            break;

     }

大家,如果有兴趣也可以看一下自动生成的系统消息,它的结构其实也满足上述规则。


0 0
原创粉丝点击