MFC 消息类型详解

原文来自: http://blog.tianya.cn/blogger/post_show.asp?BlogID=554498&PostID=8872182

  1、命令消息(WM_COMMAND)
  所有派生自 CCmdTarget 的类都有资格接受WM_COMMAND。
  
  2、Window消息(WM_xxx)
  所有派生自 CWnd 的类都有资格接受 WM_xxx。
  
  3、控件消息(WM_NOTIFY)
  控件向其父窗口通知消息。
  
  消息处理
  1、WM_xxx 消息处理
  窗口类(自身)处理→基类处理→CWnd∷DefWindowProc()处理;
  其所对应的宏一般为在消息 WM_ 前面加上 ON_。
  
  2、命令消息处理
  命令消息来自命令用户接口对象(菜单、加速键或工具栏按钮)发出的WM_COMMAND消息;
  ㈠、WM_COMMAND消息
  其所包含的类型和对应的宏如下:
  ①、ON_COMMAND(ID,pfn)
  标准的命令消息;
  
  ②、ON_COMMAND_EX(ID,pfn)
  多个对象对同一个命令 ID 的处理;
  其函数的原型如下:
  afx_msg BOOL pfn(UINT nID)
  说明:
  当返回 TRUE 时表示已经处理,不用在消息处理链中继续处理该命令;为 FALSE 时表示继续在消息处理
  
  链中处理该命令。
  注意:
  其一:在多对象处理中一定要使用该宏;
  其二:pfn(UINT nID)(消息处理函数)返回值将其类型void改成BOOL,而且必须为FALSE;
  其三:多个对象的处理是由高层向低层的过程:即视图类→主框架窗口类→应用程序类;
  
  ③、ON_COMMAND_RANGE(nID,nLastID,pfn)
  多个命令 ID 提供相同的处理;
  注意:
  其一:确保nID、nLastID的值在 Resource.h 中是连续的。
  其二:一般在函数 pfn(UINT nID) 中加入参数,用来确定那一个按钮点击。
  
  ㈡、CN_UPDATE_COMMAND_UI消息
  当菜单项、工具栏按钮等[命令用户接口对象]要更新其状态时所对应的消息,它所包含的类型和对应的宏
  
  如下:
  ①、ON_UPDATE_COMMAND_UI(ID,pfn)
  其中函数的原型如下:
  afx_msg void pfn(CCmdUI* pCmdUI)
  
  ②、ON_UPDATE_COMMAND_UI_RANGE(nID,nLastID,pfn)
  该函数可以处理一组[命令用户接口对象]的外观;
  其中函数的原型如下:
  afx_msg void pfn(CCmdUI* pCmdUI)
  重要:
  CCmdUI 中的 m_nID 成员表示不同的 ID,因此可以利用它来进行区别处理。
  
  3、控件的通知消息
  从控件和子窗口发送到父窗口的WM_COMMAND通知消息(即在发送命令消息中加入控件的通知码)。
  注意:在 Window9x 新控件中不再传送WM_COMMAND通知消息,而是发送 WM_NOTIFY 消息,但
  
  为了兼容,旧有的控件还是传送WM_COMMAND消息。
  例如:
  CEdit控件向父窗口发送 EN_CHANGE 通知代码的WM_COMMAND消息。
  注意:框架像传送其它 WM_ 消息一样传送通知消息,但有一个例外,即由 [按钮] 控件发送的
  
  BN_CLICKED 通知消息,被作为命令消息特别处理。
  ㈠、WM_COMMAND 其所对应的宏如下:
  ①、ON_CONTROL(通知码, nID,fn)
  ②、ON_CONTROL_RANGE(通知码, nFirstID,nEndID,fn)
  注意:
  这两个宏的应用和 ON_COMMAND、ON_COMMAND_RANGE相同,所不同的是在宏前面加入[通知
  
  码]。
  注意:可以根据不同的控件的[通知码]派生出特定的宏,其所派生的宏一般为在 [通知码] 前面加上 ON_
  
  。
  ㈡、WM_NOTIFY 其所对应的宏如下:
  ①、ON_NOTIFY(通知码, nID,fn)
  其中函数的原型如下:
  afx_msg void fn(NMHDR* pNotifyStruct,LRESULT* result)
  其中结构:
  typedef struct tagNMHDR {
  HWND hwndFrom; //发送通知消息的控件的句柄;
  UINT idFrom; //发送通知消息的控件的 ID;
  UINT code; //通知码;
  } NMHDR;
  
  ②、ON_NOTIFY_EX(通知码, nID,fn)
  表示一个消息在多个对象的成员函数中进行处理。
  其中函数的原型如下:
  afx_msg BOOL fn(UINT nID,NMHDR* pNotifyStruct,LRESULT* result)
  说明:
  它必须返回 BOOL 类型的数值,其意义和 ON_COMMAND_EX 相同。
  
  ③、ON_NOTIFY_RANGE(通知码, nFirstID,nEnd,fn)
  表示多个控件的通知消息在同一个函数中进行处理。
  其中函数的原型如下:
  afx_msg void fn(UINT nID,NMHDR* pNotifyStruct,LRESULT* result)
  说明:
  其意义和ON_COMMAND_RANGE相同。
  
  4、反射消息处理
  父窗口在处理控件窗口的通知消息WM_CTLCOLOR、WM_COMMAND、WM_NOTIFY时,会把该消息
  
  转化为反射消息,并转交给控件子窗口处理,只有在控件子窗体不处理该消息时,父窗口才有机会处理
  
  。
  注意:在类的属性对话框中的消息页面可查反射消息(前面有"="标志)
  ①、WM_CTLCOLOR_REFLECT反射消息
  其所对应的宏如下:
  ON_WM_CTLCOLOR_REFLECT()
  反射消息函数的原型:
  HBRUSH class_name∷CtlColor(CDC* pDC,UINT nCtlColor)
  {
  return NULL;
  }
  该函数用来重置控件的顔色;注意:必须 return CBrush才有效。
  
  
  5、自定义的窗口消息
  自定义窗口消息的消息标志都大于WM_USER(至少是WM_USER+100,因为许多控件都使用这一范围的
  
  WM_USER消息)
  使用自定义的消息分为二步:
  ①、在 Resource.h 中定义消息标记
  #define WM_MYMSG (WM_USER+1000)
  
  ②、在消息映射表中加入消息映射宏
  BEGIN_MESSAGE_MAP()
  
  ON_MESSAGE(WM_MYMSG,fn)
  END_MESSAGE_MAP()
  说明:
  其对应的宏为 ON_MESSAGE(),其成员函数的原型为:
  afx_msg LRESULT fn(WPARAM,LPARAM)
  
  6、登记消息
  ①、在系统中注册并获取一个登记消息的消息标记
  UINT RegisterWindowMessage(LPCTSTR)
  说明:
  通过 API 函数来注册消息标记,其中 LPCTSTR 为用户的任意字符串。例如:
  UINT WM_MYMSG=RegisterWindowMessage("MYMSG");
  其中 WM_MYMSG 是自定义无符号整型的消息标记。
  
  ②、在消息映射表中加入消息映射宏
  BEGIN_MESSAGE_MAP()
  
  ON_REGISTERED_MESSAGE(WM_MYMSG,fn)
  END_MESSAGE_MAP()
  说明:
  其对应的宏为 ON_REGISTERED_MESSAGE(),其成员函数的原型为:
  afx_msg LRESULT fn(WPARAM,LPARAM)
  注意:登记消息可以实现跨进程的数据通讯。
  
  7、线程消息
  只有继承自CWinThread类才能允许处理线程消息。
  ①、定义线程的消息标记
  有两种方法:
  (1)、使用自定义的消息标记,即:WM_USER;
  (2)、使用登记的消息标记,即:RegisterWindowMessage;
  
  ②、在CWinThread继承类的消息映射表中添加宏
  ON_THREAD_MESSAGE(消息标记,fn) //自定义的消息;
  ON_REGISTERED_THREAD_MESSAGE(消息标记,fn) //登记的 //消息
  ③、其函数的原型如下:
  afx_msg void fn(WPARAM wPARAM,LPARAM lParam)
  
  ④、引发线程消息
  线程消息的引发必须调用 CWinThread 类的PostThreadMessage将消息投递到线程消息队列中。
  注意:可以通过 AfxGetApp() 函数获取一个全局的应用对象。
  PostThreadMessage(UINT,WPARAM,LPARAM)
  
  8、WM_COPYDATA
  操作系统维护一块内存来管理 WM_COPYDATA 消息,该消息主要用于跨进程传递数据,传递的数据量
  
  达到 232。
  ①、定义一个 COPYDATASTRUCT 数据结构
  typedef struct tagCOPYDATASTRUCT {
  DWORD dwData; //自定义的特殊数据;
  DWORD cbData; //以字节为单位的 lpData 的大小;
  PVOID lpData; //传送的数据内存块的指针;
  } COPYDATASTRUCT;
  
  ②、其所对应的宏
  ON_WM_COPYDATA()
  
  ③、其所对应的函数的原型
  afx_msg BOOL OnCopyData(CWnd*,COPYDATASTRUCT*)
  说明:
  CWnd*:发送该消息的窗口的指针;
  
  9、投递和发送消息
  通过向一个窗体投递或发送消息,可以间接地驱动窗体的消息过程。
  投递(PostMessage):将消息放到线程的消息队列中,然后不等线程处理该消息就直接返回到调用方。
  发送(SendMessage):当一个线程向目标线程发送消息时,该线程要一直等待,直到目标线程处理了该
  
  消息为止。
  ①、投递消息
  BOOL CWnd∷PostMessage(UINT,WPARAM=0,LPARAM=0)
  说明:
  CWnd:目标窗口;
  该函数将一条消息放入到应用程序的消息队列,然后不等窗口处理就直接返回。
  
  ②、发送消息
  LRESULT CWnd∷SendMessage(UINT,WPARAM=0,LPARAM=0)
  说明:
  CWnd:目标窗口;
  该函数将一条消息放入到应用程序的消息队列,等待窗口处理后才返回。
  为了避免线程陷入永久等待状态,可以用SendMessageTimeout代替SendMessage:
  LRESULT SendMessageTimeout(HWND,UINT,WPARAM,LPARAM,UINT,UINT,PDWORD_PTR)
  说明:
  HWND:窗口句柄;
  UINT:消息发送的选项,为SMTO_BLOCK时,可以防止线程无 限等待,即根据一定的超时值返回。
  UINT:超时,以毫秒为单位;
  PDWORD_PTR:返回值;
  注意:CWnd没有对该函数的包装。
  
  ③、投递和发送消息
  BOOL CWnd∷SendNotifyMessage(UINT,WPARAM,LPARAM)
  说明:
  CWnd:目标窗口;
  该消息具有SendMessage和PostMessage两种功能:
  当目标窗口和发送窗口为同一个线程时,则相当于SendMessage的功能;否则当不为同一个线程时,则
  
  为PostMessage的功能。
  
  6-1、投递和发送 WM_XXX 消息
  在发送标准的 WINDOW 消息时,只要将该消息的 ID、wParam、lParam参数放在 SendMessage()和
  
  PostMessage()函数的相应位置即可。
  
  6-2、投递和发送命令消息和控件的通知消息
  在投递和发送命令消息时,消息的 ID为 WM_COMMADN,而对于不同的菜单项、加速键、控件则
  
  wParam、lParam的取值不同。
  wParam分成低、高两部分,低部分为菜单项、加速键、控件的ID。高部分则:
  菜单项:0;加速键:1;控件:通知码
  lParam:当控件时是控件的句柄,否则为 NULL。
  
  对于wParam参数可以采用自定义宏:
  WPARAM MAKEWPARAM(WORD wLow,WORD wHigh)
  
  6-3、投递和发送自定义的窗口消息
  在投递和发送自定义的窗口消息时,参数 wParam、lParam 没有特别的涵义,只和普通函数的形参一样
  
  进行数据的传递。
  注意:
  PostMessage 和 SendMessage 是不同的,前者投递后就返回,而后者必须等到消息处理后再返回;所
  
  以在参数是 [局部] 或 [临时]时,使用PostMessage函数会引发错误(除非参数使用 指针,则可避免错误)
  
  ,而必须使用SendMessage函数。
  6-4、投递和发送注册的窗口消息
  和 6-3 基本一样,但它要特别注意的问题是:在跨进程的处理消息时,如果将消息PostMessage、
  
  SendMessage到某个进程 A,则必须在进程 B 中获取进程 A 的窗口类名,并通过窗口类名获取窗口的
  
  指针,最后再根据指针调用 PostMessage、SendMessage 函数。
  注意:在获取窗口的指针时,可以根据窗口类名或窗口的标题。
  
  
  6-5、投递和发送WM_COPYDATA消息
  SendMessage(消息标记,WPARAM,LPARAM)
  其中:
  消息标记:WM_COPYDATA;
  WPARAM:发送该消息的窗口句柄;
  LPARAM:COPYDATASTRUCT结构的指针,先通过(LPVOID)进行转换,再通过(LPARAM)进行转换,
  
  如下形式:
  (LPARAM)(LPVOID)&cds
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值