IDocHostUIHandler::TranslateAccelerator快捷键不响应解决办法(即ctrl+c, ctrl+v不起作用解决办法)

ctrl+c, ctrl+v不起作用的时候, 如果使用的是CHtmlView, 那么是它的一个BUG, 在资源文件中加入以下内容可以解决:/
//
// Accelerator
//
IDC_XTPRO2 ACCELERATORS
BEGIN
    “C”,            ID_EDIT_COPY,           VIRTKEY, CONTROL, NOINVERT
    “X”,            ID_EDIT_CUT,            VIRTKEY, CONTROL, NOINVERT
    “V”,            ID_EDIT_PASTE,          VIRTKEY, CONTROL, NOINVERT
END
加入有C, X, V 开头的三行, 这个比较容易. 今天讨论的主题不是CHtmlView的问题, 而是在标准Winodws API SDK编程下, 如何处理IWebBrowser2中的快捷键问题.

一. TranslateAccelerator为什么得不到调用?
IDocHostUIHandler::TranslateAccelerator Method is Called by MSHTML when IOleInPlaceActiveObject::TranslateAccelerator or IOleControlSite::TranslateAccelerator is called

IOleInPlaceActiveObject::TranslateAccelerator -  Processes menu accelerator-key messages from the container’s message queue. This method should only be used for objects created by a DLL object application.
An object created by an EXE object application gets keystrokes from its own message pump, so the container does not get those messages.If you need to implement this method, you can do so by simply wrapping the call to the Window’s TranslateAccelerator function.

IOleControlSite::TranslateAccelerator – Instructs the control site to process the keystroke.This method is called by a control that can be UI-active. In such cases, a control can process all keystrokes first through IOleInPlaceActiveObject::TranslateAccelerator, according to normal OLE Compound Document rules. Inside that method, the control can give the container certain messages to process first by calling IOleControlSite::TranslateAccelerator and using the return value to determine if any processing took place. Otherwise, the control always processes the message first. If the control does not use the keystroke as an accelerator, it passes the keystroke to the container through this method.
 
以上Y文给我们讲得很明白, 必须要IOleInPlaceActiveObject 或者 IOleControlSite 的 TranslateAccelerator 方法得到调用, IDocHostUIHandler::TranslateAccelerator才会响应, 可见IDocHostUIHandler::TranslateAccelerator并不是主动响应的, 而是你的应用程序框架调用的, 调用的地方在你的消息泵处理时.

二. 如何使TranslateAccelerator得到调用?
在CHtmlView中, 是如下调用TranslateAccelerator的:

BOOL CHtmlView::PreTranslateMessage(MSG* pMsg)
{
 // 省略若干处理
 //…..
 
 // check if the browser control wants to handle the message
 BOOL bRet = FALSE;
 if(m_pBrowserApp != NULL)
 {
  CComQIPtr<IOleInPlaceActiveObject> spInPlace = m_pBrowserApp;
  if (spInPlace)
   bRet = (spInPlace->TranslateAccelerator(pMsg) == S_OK) ? TRUE : FALSE;
 }
 return bRet;
}

PreTranslateMessage 是MFC中消息派发前的预处理消息机制, 旨在提供给调用者决策消息传递通路.

我的程序中没有这样的函数, 就难以派发消息, IWebBrowser2就不能够响应ctrl+c, ctrl+v, ctrl+x等一切键盘快捷键. 所以, 解决的关键是要实现一个消息派发机制, 参见下面的入口函数:

//MFC的消息入口代码, 仅作参考
BOOL AFXAPI AfxInternalPumpMessage()
{
 _AFX_THREAD_STATE *pState = AfxGetThreadState();
 if (!::GetMessage(&(pState->m_msgCur), NULL, NULL, NULL))
 {
  // Note: prevents calling message loop things in ‘ExitInstance’
  // will never be decremented
  return FALSE;
 }
  // process this message
 if (pState->m_msgCur.message != WM_KICKIDLE && !AfxPreTranslateMessage(&(pState->m_msgCur)))
 {
  ::TranslateMessage(&(pState->m_msgCur));
  ::DispatchMessage(&(pState->m_msgCur));
 }
  return TRUE;
}

在::TranslateMessage(&(pState->m_msgCur));之前, 当浏览器窗口在获得焦点时, 我们应该禁止::TranslateMessage(&(pState->m_msgCur))的执行, 所以就该在此之前加上自己的AfxPreTranslateMessage函数. 在这个函数中去调用CHtmlView::PreTranslateMessage(..), 这样就解决了快捷键不响应的问题.

三. 总结及其它方面
 IWebBrowser2中复制的关键:
1. 菜单复制, 需要在构造函数中添加: OleInitialize(NULL);
2. 快捷键复制, 需要处理IOleInPlaceActiveObject接口, 一般在CHtmlView::PreTranslateMessage(MSG* pMsg) 处处理, 如果你用的不是CHtmlView类, 没用MFC/ATL之类的,
那么就需要在消息入口处处理这个事情, 否则WebBrowser按键可能不响应
3. 要合理处理PreTranslateMessage的返回值, FALSE的时候才把消息传递下去.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值