【问题标题】:IWebBrowser2 Ctrl + C and other shortcuts supportIWebBrowser2 Ctrl + C 等快捷键支持
【发布时间】:2014-01-05 11:57:33
【问题描述】:

看来我的问题不是小事。

我将自己的窗口挂接到 IE 主窗口。我的窗口源自 WTL 的 CWindowImpl 并承载 IWebBrowers2 控件,该控件显示了一些内容。

IWebBrowser2 显示带有<input type='text'/> 编辑框的html,我需要支持所有键,这是编辑和操作文本所必需的(Ctrl + C、Ctrl + V、Ctrl + X 等...+ Esc、Delete、箭头上下)。

我还需要禁止一些快捷键,例如 Ctrl + P、Ctrl + S,因为它们会调用特定于我不需要的网页的对话框。


似乎是常见问题,我需要为我的 IWebBrowser2 对象调用 TranslateAccelerator。

网上也有类似的问题——Tab key doesn't work in IWebbrowser2

解决方案——hot key not work!!

Tab key support in an IWebBrowser2 control

这是一个非常有趣的线程,我需要的全部 - Handling Control-C in a hosted web browser control


所以,首先我需要为我的 IWebBrowser2 对象调用 TranslateAccelerator。但我必须先从键盘获取消息。

那么,让我们看看它的外观。

我的挂钩窗口没有收到任何键盘输入消息。一个具有“Internet Explorer_Server”类的窗口接收所有这些(实际上,它是 IWebBrowser2 内的 IE 的 hwnd)。

所以我需要挂钩这个 hwnd 的 window proc。

m_ieOldProc = (PROC)::SetWindowLongPtr ( hIEWnd, GWLP_WNDPROC, (LONG_PTR)_IEWndProc );

在 hooked wnd proc 中,我执行以下操作:

// ...
switch ( uMsg )
{
    case WM_KEYUP: 
    case WM_KEYDOWN: 
    {
        // ...
        IOleInPlaceActiveObject* pAccelerator;
        CComPtr< IWebBrowser2 > pWebBrowser =  CWebWindow::GetWebBrowser( hwnd );
        if( pWebBrowser )
        {               
            hr = pWebBrowser->QueryInterface( IID_IOleInPlaceActiveObject,(void**)&pAccelerator );
            if ( SUCCEEDED(hr) )
            {
                pAccelerator->TranslateAccelerator(&msg);
                pAccelerator->Release();
            }           
        }
        // ...
    }
}
// ...

是的!有些事情成功了! Esc、Delete、向上和向下箭头键现在可以使用。

但不是全部。快捷方式有问题。

  1. Ctrl + C、Ctrl + A 不起作用。

Ctrl + X,Ctrl + V - 工作。

这是 Spy++ 中用于 hwnd 的消息日志,其类为“Internet Explorer_Server”。

在 Ctrl + C 上我没有收到 WM_COMMAND。

在 Ctrl + X 上:

我不知道为什么。

2 。 “坏”的捷径确实有效。 打印对话框在 Ctrl + P 上调用,网页保存对话框在 Ctrl + S 上调用,等等。 在这种情况下,我什么也做不了。无论我在挂钩窗口 proc 中返回什么,它们仍在显示。 所以我需要在发送到窗口之前处理它们。


解决方案?

你可以提到在这个问题的所有解决方案中都有:

  1. 预翻译消息
  2. 其实是 TranslateAccelerator

到目前为止,我在挂钩消息过程中只有 TranslateAccelerator。

预翻译必须这样做:

BOOL PreTranslateMessage(MSG* pMsg)
{
    if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
        (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
        return FALSE;

    // give HTML page a chance to translate this message
    return (BOOL)SendMessage(WM_FORWARDMSG, 0, (LPARAM)pMsg);
}

另外,在 PreTranslateMessage 中,我可以过滤“坏”的快捷方式而不将它们发送到窗口。

另一个人建议也使用 PretranslateMessage(来自上面线程的对话框):

– 从 CMessageFilter 派生你的窗口,安装它 CMessageLoop::AddMessageFilter,实现 PreTranslateMessage 如图 在示例中。

– 我想我现在已经按照样本的建议做了。但问题是我的“父”窗口没有得到击键 - 他们都去 IE AX 控件。

– 这就是您需要 CMessageFilter 的原因。它与消息挂钩 泵,在消息被发送到它们的目标窗口之前。

好的,但是托管 IWebBrowser2 的我的根窗口没有收到任何键盘消息。 我的窗口中也没有 PreTranslateMessage,只有窗口 proc 调用(由父级,CWindowImpl)。

如上所述,我可以从 CMessageFilter 派生,实现 PreTranslateMessage,但我无法使用 CMessageLoop::AddMessageFilter 订阅事件,因为我不创建主窗口并且无权访问它的 CMessageLoop。


那么我现在应该怎么做才能让这一切顺利进行呢? 我应该使用 PreTranslateMessage 以及如何使用?

【问题讨论】:

  • 您要解决什么问题需要您将窗口注入 Internet Explorer?托管您自己的 IWebBrowser2 实例不是更简单,您可以在其中控制消息循环吗?
  • @EricBrown 这是一种与 IE 的集成。像 IE 版本的搜索框,没有它。所以不,我不能这样做。

标签: internet-explorer winapi hook wtl iwebbrowser2


【解决方案1】:

最近我也遇到了复制/剪切命令不起作用的问题。事实证明这不是 TranslateAccelerator 或类似的键盘问题。问题是 COM 库是使用 CoInitialize/CoInitializeEx 初始化的。但是需要调用 OleInitialize 才能使剪贴板工作。 MSDN“WebBrowser Customization”页面上有说明:

您的应用程序应该使用 OleInitialize 而不是 CoInitialize 启动 COM。 OleInitialize 启用对剪贴板的支持, 拖放操作、OLE 和就地激活。采用 OleUninitialize 在应用程序关闭时关闭 COM 库 下来。

http://msdn.microsoft.com/en-us/library/aa770041(v=vs.85).aspx

如果还是不行,看看我在PHP桌面项目中IWebBrowser2控件的实现(C API):

https://code.google.com/p/phpdesktop/source/browse/phpdesktop-msie/msie/

【讨论】:

    【解决方案2】:

    听起来您已经实现了一个工具栏。在这种情况下,您应该实现IInputObject,并且浏览器框架会在适当的时候将调用转发给您,以便您可以适当地翻译加速器(和否决加速器)。

    【讨论】:

    • 并非如此。在注册中注册的不是这样的“合法”工具栏。它只是一个窗口,里面有IWebBrowser2,插入到IE中我想要的地方。为了使 IInputObject 实现方法调用,我必须实现 IObjectWithSiteImpl、IOleControlSite 等。据我了解,它必须是“合法”工具栏(类似 codeproject.com/Articles/1323/…)才能完成这项工作。
    • @nicolausYes 为了进入消息循环,您需要实现 IInputObject。说您不想正确编码并不能免除您正确编码的责任。
    • 我没有说我不想要。我已经实现了 IInputObject,但我的方法从不调用。如果你用谷歌搜索,你会发现一些类似这样的帖子 - bit.ly/1jt4zitbit.ly/1gN2Sui。有些人使用其他接口(IObjectWithSiteImpl)实现合法工具栏需要调用 IInputObject 方法。所以我得出一个结论,这种技术只适用于“合法”工具栏。如果我没有正确注册我的“工具栏”,IE 怎么知道我正在实现 IInputObject?我说的不对?
    猜你喜欢
    • 2013-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多