2007年1月31日星期三

Visual C++ 用一个消息处理函数来处理一批消息

用一个消息处理函数来处理一批消息

有时我们可能想用一个消息处理函数来处理一批消息。这时类向导就无能为力了。我们必须手工加入消息映射来完成这种工作。可用如下方法实现:

  首先在处理该消息所在类的实现文件(亦即.CPP)中加入的消息映射入口:

   ...

  BEGIN_MESSAGE_MAP(CMyApp, CWinApp)

   file://{{AFX_MSG_MAP(CMyApp)

   ...

   file://}}AFX_MSG_MAP

   ON_COMMAND_RANGE(ID_MYCMD_ONE, ID_MYCMD_TEN, OnDoSomething)

  END_MESSAGE_MAP( )

  ...

粗体标志的语句是我们加入的语句(以后约定我们加入的语句均用粗体标志).其中我们使用了宏ON_COMMAND_RANGE来实现从命令消息ID_MYCMD_ONE到 ID_MYCMD_TEN都 由OnDoSomthing一个消息函数处理.注意.ID_MYCMD_ONE到 ID_MYCMD_TEN的ID值一定要连续.且ID_MYCMD_ONE值一般较小.

  完成上述工作之后我们还需要在该类的头文件(亦即.H)中加入消息处理函数的申明:

  // Generated message-map functions

  protected:

  file://{{AFX_MSG(CMyApp)

  ...

  file://}}AFX_MSG

  afx_msg void OnDoSomething( UINT nID );

  DECLARE_MESSAGE_MAP()

  由于这不是VC类向导加入的函数申明,所以放在了//}}AFX_MSG之外.

  注意这个消息处理函数有一个UINT类型参数.而处理单一命令的消息处理函数一般是没有参数(除更新用户接口对象状态命令消息处理函数).这个参数的主要作用是提供用户选择的命令的ID值.

  最后要做的工作就是在该类的实现文件中实现该消息处理函数. 同样,有时我们也想使用一个消息处理函数处理一批更新用户接口对象状态命令消息.方法同上:

  首先在.CPP文件中加入语句如下:

   ...

   BEGIN_MESSAGE_MAP(CMyApp, CWinApp)

    file://{{AFX_MSG_MAP(CMyApp)

     ...

    file://}}AFX_MSG_MAP

    ON_UPDATE_COMMAND_UI_RANGE (ID_MYCMD_ONE, ID_MYCMD_TEN, OnUpdateSomething)

   END_MESSAGE_MAP( )

    ...

  在该类的头文件(亦即.H)中加入消息处理函数的申明:

   // Generated message-map functions

   protected:

   file://{{AFX_MSG(CMyApp)

   ...

   file://}}AFX_MSG

   afx_msg void OnUpdateSomething( CcmdUI * pcmdui );

   DECLARE_MESSAGE_MAP()

请各位注意了,仔细的读者已经注意到这里的消息处理函数并未像命令消息处理函数需要一个额外的UINT类型的参数.原因在于pcmdui中已包含了此信息.所以不再需要这个参数了.最后不要忘了完成函数体 !

有时我们可能需要为一组控件处理相同的WM_NOTIFY消息.这时需要使用ON_NOTIFY_RANGE而不是ON_NOTIFY.当你使用 ON_NOTIFY_RANGE时,你需要指定控件的ID范围.其消息映射入口及函数原型如下:

   ON_NOTIFY_RANGE( wNotifyCode, id, idLast, memberFxn )

    参数说明:

     wNotifyCode: 消息通知码.比如:LVN_KEYDOWN,

     id: 第一控件的标识ID。

     idLast:最后一个控件的标识ID。(标识值一定要连续)

     memberFxn: 消息处理函数。

    成员函数必须有如下原型申明:

    afx_msg void memberFxn( UINT id, NMHDR * pNotifyStruct, LRESULT * result );

    其中id的表示发送通知消息的控件标识ID

没有评论: