nic*_*Yes 3 hook winapi internet-explorer wtl iwebbrowser2
看来我没有什么小问题。
我将自己的窗口挂接到 IE 主窗口。我的窗口是从 WTL 的 CWindowImpl 派生出来的,并承载了 IWebBrowers2 控件,它显示了一些内容。
IWebBrowser2 显示带有<input type='text'/>编辑框的html ,我需要支持所有键,这是编辑和操作文本所必需的(Ctrl + C、Ctrl + V、Ctrl + X 等... + Esc、删除、向上和向下箭头)。
另外我需要禁止一些快捷方式,例如 Ctrl + P、Ctrl + S,因为它们调用特定于我不需要的网页的对话框。
似乎是常见问题,我需要为 IWebBrowser2 对象调用 TranslateAccelerator。
网上有一些类似的问题——Tab键在IWebbrowser2中不起作用
解决方案——热键不起作用!!
这是一个非常有趣的线程,我只需要 -在托管的 Web 浏览器控件中处理 Control-C
所以,首先我需要为我的 IWebBrowser2 对象调用 TranslateAccelerator。但我必须先从键盘获取消息。
那么,让我们看看它的外观。

我的钩子窗口没有收到任何键盘输入消息。一个类为“Internet Explorer_Server”的窗口接收所有这些(实际上,它是 IWebBrowser2 中 IE 的一个 hwnd)。
所以我需要钩住这个 hwnd 的 window proc。
m_ieOldProc = (PROC)::SetWindowLongPtr ( hIEWnd, GWLP_WNDPROC, (LONG_PTR)_IEWndProc );
Run Code Online (Sandbox Code Playgroud)
在 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();
}
}
// ...
}
}
// ...
Run Code Online (Sandbox Code Playgroud)
是的!有些事情得到了工作!Esc、Delete、向上和向下箭头键现在可以使用了。
但不是所有的。快捷方式有问题。
Ctrl + X、Ctrl + V - 工作。
以下是 Spy++ 中 hwnd 的消息日志,类为“Internet Explorer_Server”。
在 Ctrl + CI 上不接收 WM_COMMAND。

在 Ctrl + X 上:

我不知道为什么。
2 . “坏”快捷方式确实有效。打印对话框在 Ctrl + P 上调用,在 Ctrl + S 上调用网页保存对话框等。在这种情况下我无能为力。无论我在 hooked window proc 中返回什么,它们仍在显示。所以我需要在发送到窗口之前处理它们。
解决方案?
您可以提到在此问题的所有解决方案中都有:
直到这一刻,我在钩住的消息过程中只有 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);
}
Run Code Online (Sandbox Code Playgroud)
此外,在 PreTranslateMessage 中,我可以过滤“坏”快捷方式,并且不将它们发送到窗口。
另一个人建议也使用 PretranslateMessage(来自上面线程的对话框):
– 从 CMessageFilter 派生您的窗口,使用 CMessageLoop::AddMessageFilter 安装它,如示例中所示实现 PreTranslateMessage。
– 我想我现在已经完成了样本的建议。但问题是我的“父”窗口没有得到击键 - 它们都转到 IE AX 控件。
– 这就是您需要 CMessageFilter 的原因。在消息被分派到它们的目标窗口之前,它被连接到消息泵中。
好的,但是我托管 IWebBrowser2 的 Root 窗口没有收到任何键盘消息。此外,我的窗口中没有 PreTranslateMessage,只有窗口 proc 调用(由父级,CWindowImpl)。
如上所述,我可以从 CMessageFilter 派生,实现 PreTranslateMessage,但我无法使用 CMessageLoop::AddMessageFilter 订阅事件,因为我没有创建主窗口并且无权访问它的 CMessageLoop。
那么我现在应该怎么做才能使所有这些工作?我应该使用 PreTranslateMessage 以及如何使用?
最近我也遇到了复制/剪切命令不起作用的问题。事实证明,这不是 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/
| 归档时间: |
|
| 查看次数: |
2113 次 |
| 最近记录: |