`
mof51mof
  • 浏览: 19610 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

VC消息映射

阅读更多

VC消息映射
2010年08月14日
  视类增加一个消息相应函数后,在源文件中都会增加三处代码。 1  消息相应函数原型。
  在CDrawView中会有这样的代码:
  // Generated message map functions
  protected:
  //{{AFX_MSG(CMainFrame)
  afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
  afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
  //}}AFX_MSG
  DECLARE_MESSAGE_MAP()
  在DECLARE_MESSAGE_MAP()宏上有两个AFX_MSG注释宏,在这两个注释宏之间有一个函数原型OnLButtonDown,因为她位于两个注释宏之间,所以是以灰色显示,还函数声明的前部有一个afx_msg限定符,这也是一个宏。该宏表明这个函数是一个消息响应函数的声明。
  AFX_MSG(CLASSNAME):
  ClassWizard and AppWizard insert specially formatted comment delimiters in your source code files to mark the places in your files that ClassWizard can write to. AFX_MSG is used to mark the beginning and end of ClassWizard entries in your header file (.H) related to message maps
  2   ON_WM_LBUTTONDOWN()消息映射宏
  在CDrawView类的源文件中,有如下代码:
  BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
  //{{AFX_MSG_MAP(CMainFrame)
  ON_WM_CREATE()
  ON_WM_LBUTTONDOWN()
  //}}AFX_MSG_MAP
  END_MESSAGE_MAP()
  在 上述代码中,BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP() 这两个宏之间定义了CDrawView类的消息映射表,其中有一个ON_WM_LBUTTONDOWN()这消息映射宏,这个宏的作用就是吧鼠标左键按下消息WM_LBUTTONDOWN与一个消息相应函数关联起来。通过这种机制,一旦有消息产生,程序就会调用相应的消息相应函数来进行处理。
  3  消息响应函数的定义
  在CDrawView的源文件中,可以看到OnLButtonDown函数的定义。
  MFC消息映射机制的具体实现方法是:
  在每个能接收和处理消息的类中,定义一个消息和消息函数静态对照表,即消息映射表。在消息映射表中,消息和对应的消息处理指针是成对出现的。某个类能处理的所有消息及其对应的消息处理函数的地址都列在这个类所对应的静态表中。当有消息需要处理时,程序只要搜索该消息静态表,查看表中是否含有该消息,就可知道该类能否处理该消息,如果能处理该消息,则同样依照静态表能很容易找到并调用对应的消息处理函数。
  MFC消息映射的具体实现过程。MFC在后台维护了一个窗口句柄和对应的C++对象的对照表,以一个实例CDrawView类为例,与它的对象相关的有一个窗口,窗口当然有它的窗口句柄,该句柄与CDrawView对象的一个指针存在这意义对应关系,在窗口句柄与C++对招标中就维护了这种对应关系。当收到某一消息时,消息的第一个参数就指明该消息与那个窗口句柄相关,通过对照表,就可以找到与之相关的C++对象指针。然后把这个指针传递给应用程序框架窗口类的基类,后者会调用一个名为WindowProc的函数。 其具体代码如下:
  LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
  {
  // OnWndMsg does most of the work, except for DefWindowProc call
  LRESULT lResult = 0;
  if (!OnWndMsg(message, wParam, lParam, &lResult))
  lResult = DefWindowProc(message, wParam, lParam);
  return lResult;
  }
  根据WindowProc函数的定义,我们发现它是一个虚函数。同时,也发现,CWnd::WindowProc函数内部调用了一个OnWndMsg的函数,真正的消息路由,也就是消息映射就是由此函数完成的。CWnd::OnWndMsgvirtual BOOL OnWndMsg( UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult );
  Return Value
  Nonzero if message was handled; otherwise 0.
  Parameters
  message
  Specifies the message to be sent.
  wParam
  Specifies additional message-dependent information.
  lParam
  Specifies additional message-dependent information.
  pResult
  The return value of WindowProc. Depends on the message; may be NULL.
  //CWnd::WindowProc  
  virtual LRESULT WindowProc( UINT message, WPARAM wParam, LPARAM lParam );//
  nWndMsg部分代码如下:BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
  {
  LRESULT lResult = 0;
  // special case for commands
  if (message == WM_COMMAND)
  {
  if (OnCommand(wParam, lParam))
  {
  lResult = 1;
  goto LReturnTrue;
  }
  return FALSE;
  }
  // special case for notifies
  if (message == WM_NOTIFY)
  {
  NMHDR* pNMHDR = (NMHDR*)lParam;
  if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))
  goto LReturnTrue;
  return FALSE;
  }
  OnWndMsg函数的处理过程是:
  判断消息是否有消息响应函数。
  判断的方法是在相应窗口类中查找所需的消息响应函数。因为传递给WindowProc函数的是窗口子类指针,所以OnWndMsg会到相应的子类头文件中查找,看看DECLARE_MESSAGE_MAP()宏之上,两个AFX_MSG注释宏之间是否有相应的消息响应函数原型的声明;再到子类的源文件中,看看BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP()之间是否有相应的消息映射宏。
  如果通过上述步骤,找到了消息相应函数,那么接着就会调用改响应函数,对消息进行处理。如果在子类中没有找到消息响应函数,那么就交由基类进行处理。
  通过以上步骤,MFC就实现了具体的消息映射,从而完成了对消息的相应。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics