博客
关于我
开发基于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中一条SQL语句到底是如何执行的呢?
查看>>
MySQL中你必须知道的10件事,1.5万字!
查看>>
MySQL中使用IN()查询到底走不走索引?
查看>>
Mysql中使用存储过程插入decimal和时间数据递增的模拟数据
查看>>
MySql中关于geometry类型的数据_空的时候如何插入处理_需用null_空字符串插入会报错_Cannot get geometry object from dat---MySql工作笔记003
查看>>
mysql中出现Incorrect DECIMAL value: '0' for column '' at row -1错误解决方案
查看>>
mysql中出现Unit mysql.service could not be found 的解决方法
查看>>
mysql中出现update-alternatives: 错误: 候选项路径 /etc/mysql/mysql.cnf 不存在 dpkg: 处理软件包 mysql-server-8.0的解决方法(全)
查看>>
Mysql中各类锁的机制图文详细解析(全)
查看>>
MySQL中地理位置数据扩展geometry的使用心得
查看>>
Mysql中存储引擎简介、修改、查询、选择
查看>>
Mysql中存储过程、存储函数、自定义函数、变量、流程控制语句、光标/游标、定义条件和处理程序的使用示例
查看>>
mysql中实现rownum,对结果进行排序
查看>>
mysql中对于数据库的基本操作
查看>>
Mysql中常用函数的使用示例
查看>>
MySql中怎样使用case-when实现判断查询结果返回
查看>>
Mysql中怎样使用update更新某列的数据减去指定值
查看>>
Mysql中怎样设置指定ip远程访问连接
查看>>
mysql中数据表的基本操作很难嘛,由这个实验来带你从头走一遍
查看>>
Mysql中文乱码问题完美解决方案
查看>>