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

本文共 7126 字,大约阅读时间需要 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/

你可能感兴趣的文章
mysql 中索引的问题
查看>>
MySQL 中锁的面试题总结
查看>>
MySQL 中随机抽样:order by rand limit 的替代方案
查看>>
MySQL 为什么需要两阶段提交?
查看>>
mysql 为某个字段的值加前缀、去掉前缀
查看>>
mysql 主从
查看>>
mysql 主从 lock_mysql 主从同步权限mysql 行锁的实现
查看>>
mysql 主从互备份_mysql互为主从实战设置详解及自动化备份(Centos7.2)
查看>>
mysql 主从关系切换
查看>>
MYSQL 主从同步文档的大坑
查看>>
mysql 主键重复则覆盖_数据库主键不能重复
查看>>
Mysql 事务知识点与优化建议
查看>>
Mysql 优化 or
查看>>
mysql 优化器 key_mysql – 选择*和查询优化器
查看>>
MySQL 优化:Explain 执行计划详解
查看>>
Mysql 会导致锁表的语法
查看>>
mysql 使用sql文件恢复数据库
查看>>
mysql 修改默认字符集为utf8
查看>>
Mysql 共享锁
查看>>
MySQL 内核深度优化
查看>>