博客
关于我
开发基于MFC的ActiveX控件的时候的一些消息处理
阅读量:358 次
发布时间:2019-03-04

本文共 7154 字,大约阅读时间需要 23 分钟。

MFC有PreTranslageMessage() 可以处理一些基于MFC的消息处理。

可是有时候如果你开发一个基于MFC的ActiveX作为容器,内部实现是Win32 或者其他框架会发现,好多消息都不能正常收到。

除非把你现有的内部的控件基于各种MFC的基类实现(会重载各种MFC的PreTranslateMessage)才能收到各种消息。

根本原因是基于MFC的ActiveX控件没有自己的消息循环,要基于使用ActiveX的容器来处理消息。这样有时候会忽略掉一些我们需要的消息。

微软官方有出过KB来解决问题,这里贴出了备忘一下。

PRB: MFC ActiveX Control in IE Doesn't Detect Keystrokes

https://support.microsoft.com/en-us/kb/168777


The TAB key, arrow keys, and accelerator keys do not work as expected when an ActiveX control is the parent window of a modeless dialog box or of a propertysheet window

https://support.microsoft.com/en-us/kb/187988


SYMPTOMS
Accelerator keys, such as ARROW keys, are first received by the message pump of the ActiveX control's container. Even if the control has the focus, it does not receive messages for keystrokes that have special meaning to control containers, such as ARROW and TAB keys. MFC ActiveX controls have a chance to intercept these messages by overriding their PreTranslateMessage function. 

However, PreTranslateMessage is not always called for an MFC ActiveX control.
CAUSE
PreTranslateMessage in an MFC ActiveX control is called by the TranslateAccelerator method of the IOleInPlaceActiveObject interface of the control. Internet Explorer only calls this method for the control that is currently UI-Active. Only one control can be UI-Active at a time. 

Internet Explorer does not automatically UI-Activate any controls when a page is first loaded. Internet Explorer waits until the user tabs to an ActiveX control on the page to UI-Activate it. Also, MFC ActiveX controls UI-Activate themselves when they are clicked with the mouse. In an MFC ActiveX control, this is done in COleControl::OnLButtonUp. 

If you have a child control inside your COleControl, mouse-click messages on the child control are not sent to the COleControl and MFC does not UI- Activate the ActiveX control, even though the child control has just been given the keyboard focus. Internet Explorer intercepts the keystrokes and does not give the control a chance to filter them in PreTranslateMessage.
RESOLUTION
Here is a typical PreTranslateMessage. This code forwards ARROW, HOME, and END keys back to the control so that they can be received using a MESSAGE_MAP entry:
   // trap keys and forward on to the control   BOOL CMyActiveXCtrl::PreTranslateMessage(MSG* pMsg)   {      switch (pMsg->message)      {         case WM_KEYDOWN:         case WM_KEYUP:            switch (pMsg->wParam)            {               case VK_UP:               case VK_DOWN:               case VK_LEFT:               case VK_RIGHT:               case VK_HOME:               case VK_END:                  SendMessage (pMsg->message, pMsg->wParam, pMsg->lParam);                  // Windowless controls won't be able to call SendMessage.                  // Instead, just respond to the message here.                  return TRUE;            }            break;      }      return COleControl::PreTranslateMessage(pMsg);   }				
If you have a child control within your ActiveX control, you need to UI-Activate the whole control whenever that child control is activated. For example, if you have an edit control inside your ActiveX control, add a handler as follows to your ActiveX control class:
   int CMyActiveXCtrl::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT   message)   {      if (!m_bUIActive)          OnActivateInPlace (TRUE, NULL); // == UI-Activate the control      return COleControl::OnMouseActivate(pDesktopWnd, nHitTest, message);   }				
Because Internet Explorer may not immediately UI-Activate a control, even if that is the only control on the page, it may be desirable to automatically request a UI-Activation when the control is created. This can be done during the COleControl::OnCreate (WM_CREATE) handler. Windowless controls do not get WM_CREATE or any windows messages; therefore, this code won't work in a windowless control. Also note that this does not guarantee that a control will remain UI-Activated. If there are other controls on a page that request UI-Activation in a similar manner, only one will eventually be UI-Activated and receive keystroke messages as described. And if the user TABs away from an ActiveX Control, Internet Explorer will automatically UI-deactivate the control.
   int CMyActiveXCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)   {      if (COleControl::OnCreate(lpCreateStruct) == -1)         return -1;      OnActivateInPlace (TRUE, NULL); // == UI-Activate the control      return 0;   }				
MORE INFORMATION
The following sample shows a way to install the Windows message hook to a modeless CPropertySheet-derived class:

Sample Code

   // Handle to the Windows Message hook. It can be a global variable or a   // member variable in your CPropertySheet-derived class.   HHOOK hHook = NULL;   // Hook procedure for WH_GETMESSAGE hook type.   LRESULT CALLBACK GetMessageProc(int nCode, WPARAM wParam, LPARAM lParam)   {      // Switch the module state for the correct handle to be used.      AFX_MANAGE_STATE(AfxGetStaticModuleState( ));      // If this is a keystrokes message, translate it in controls'      // PreTranslateMessage().      LPMSG lpMsg = (LPMSG) lParam;      if( (nCode >= 0) &&         PM_REMOVE == wParam &&         (lpMsg->message >= WM_KEYFIRST && lpMsg->message <= WM_KEYLAST) &&         AfxGetApp()->PreTranslateMessage((LPMSG)lParam) )         {         // The value returned from this hookproc is ignored, and it cannot         // be used to tell Windows the message has been handled. To avoid         // further processing, convert the message to WM_NULL before         // returning.         lpMsg->message = WM_NULL;         lpMsg->lParam = 0L;         lpMsg->wParam = 0;         }      // Passes the hook information to the next hook procedure in      // the current hook chain.      return ::CallNextHookEx(hHook, nCode, wParam, lParam);   }   // Declare and define the following two functions:   BOOL CModelessPropertySheet::OnInitDialog()   {      CPropertySheet::OnInitDialog();      // Install the WH_GETMESSAGE hook function.      hHook = ::SetWindowsHookEx(         WH_GETMESSAGE,         GetMessageProc,         AfxGetInstanceHandle(),         GetCurrentThreadId());      ASSERT (hHook);      return TRUE;   // Return TRUE unless you set the focus to a control.                     // EXCEPTION: OCX Property Pages should return FALSE.   }   void CModelessPropertySheet::OnClose()   {      // Uninstall the WH_GETMESSAGE hook function.      VERIFY (::UnhookWindowsHookEx (hHook));      CPropertySheet::OnClose();   }				

Steps to Reproduce the Problem

  1. Select the MFC ActiveX ControlWizard to create an ActiveX control. Accept all the default settings.
  2. Display a modeless dialog box or propertysheet window when double-clicking inside the control.
RESULTS : When the modeless dialog box or propertysheet window is shown, pressing the TAB key or accelerator keys has no effect.
大致流程是 ,需要在CxxxCtrl的OnInit 函数内注册全局钩子(参数中传入消息回调函数) 截获消息

在消息回调函数中调用PreTranslateMessage()  处理对话框消息,加速键消息,然后处理特殊按键

最后调用COleControl::PreTranslateMessage(pMsg);  如果该ActiveX控件内包含其他MFC类的子控件

若经过PreTranslateMessage处理以后把消息全部置空,这样这些消息就不会再被容器应用程序所处理。

转载地址:http://gxbg.baihongyu.com/

你可能感兴趣的文章
OSI 7 层网络模型
查看>>
JDK 内置线程池
查看>>
JDK 内置的多线程协作工具类的使用场景
查看>>
Java 中哪些对象可以获取类对象
查看>>
linux 的 cp 命令如何复制不提示覆盖
查看>>
缓存穿透 / 缓存击穿 / 缓存雪崩 / 缓存一致性
查看>>
linux 的 sleep 命令
查看>>
js 的 let var const 区别
查看>>
vue计算属性和监听器区别
查看>>
前端常用知识随手记
查看>>
11.2.6 时间值的小数秒
查看>>
11.2.7 日期和时间类型之间的转换
查看>>
redis 内存溢出_从数据存储的角度告诉你Redis为什么这么快!
查看>>
实例分析Facebook激励视频广告接入
查看>>
实例:使用OKGO下载网络压缩包资源,然后解压缩放在本地使用
查看>>
解决mybatis嵌套查询使用PageHelper分页不准确
查看>>
Redis源码分析(七)--- zipmap压缩图
查看>>
大规模集群自动化部署工具--Chef的安装部署
查看>>
HDFS源码分析(六)-----租约
查看>>
自定义Hive Sql Job分析工具
查看>>