It seems I've got not a trivial problem.
I hook my own window into IE main window. My window is derived from WTL's CWindowImpl and hosts IWebBrowers2 control, which shows some content.
IWebBrowser2 shows html with <input type='text'/>
editbox where I need a support of all keys, necessary for editing and manipulating with text (Ctrl + C, Ctrl + V, Ctrl + X, etc... + Esc, Delete, arrows up and down).
Also I need to forbid some shortcuts, such as Ctrl + P, Ctrl + S, because they call dialogs specific to webpage that I don't need.
Seems to be common problem and I need to call TranslateAccelerator for my IWebBrowser2 object.
There are some similar questions on the web – Tab key doesn't work in IWebbrowser2
Solution – hot key not work!!
Tab key support in an IWebBrowser2 control
Here is very interesting thread, all I need – Handling Control-C in a hosted web browser control
So, first of all I need to call TranslateAccelerator for my IWebBrowser2 object. But I have to get message from keyboard first.
So, lets see how it looks.
My hooked window doesn't recieve any keyboard input messages. A window with a class "Internet Explorer_Server" recieve all of them (actually, it's a hwnd of IE inside IWebBrowser2).
So I need to hook window proc of this hwnd.
m_ieOldProc = (PROC)::SetWindowLongPtr ( hIEWnd, GWLP_WNDPROC, (LONG_PTR)_IEWndProc );
Inside hooked wnd proc I do the following:
// ...
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();
}
}
// ...
}
}
// ...
Yes! Some things got work! Esc, Delete, Up and Down arrows keys work now.
But not all. There are the problem with shortcuts.
- Ctrl + C, Ctrl + A don't work.
Ctrl + X, Ctrl + V - do work.
Here is a log of messages in Spy++ for hwnd with a class "Internet Explorer_Server".
On Ctrl + C I don't recieve WM_COMMAND.
On Ctrl + X:
And I don't know why.
2 . "Bad" shortcuts do work. Print dialog is calling on Ctrl + P, webpage save dialog on Ctrl + S, etc. And I can't do anything in this case. Whatever I return in hooked window proc, they are still showing. So I need to handle them before sending to the window.
Solution?
You can mention that in all solutions on this problem there are:
- PreTranslateMessage
- Actually TranslateAccelerator
Until this moment I have only TranslateAccelerator in hooked message proc.
Pretranslate have to do something like that:
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);
}
Also, in PreTranslateMessage I can filter "bad" shortcuts and don't send them to the window.
Another man suggests to use PretranslateMessage too (dialog from thread above):
– Derive your window from CMessageFilter, install it with CMessageLoop::AddMessageFilter, implement PreTranslateMessage as shown in the example.
– I think I've done now what the sample suggests. But the problem is that my 'parent' window doesn't get the keystrokes - they all go to the IE AX control.
– That's why you need CMessageFilter. It gets hooked into the message pump, before message are dispatched to their destination windows.
Ok, but my Root window, which hosts IWebBrowser2 doesn't receive any keyboard messages. Also I don't have PreTranslateMessage in my window, only window proc call (by parent, CWindowImpl).
As suggested above, I can derive from CMessageFilter, implement PreTranslateMessage, but I can't subscribe on events with CMessageLoop::AddMessageFilter because I don't create main window and don't have access to it's CMessageLoop.
So what I should to do now to make all this work? Should I go with PreTranslateMessage and how?
It sounds like you've implemented a toolbar. In this case, you should be implementing
IInputObject
, and the browser frame will forward calls to you at the appropriate time so that you can translate accelerators (and veto accelerators) appropriately.