On Windows, the WebBrowserComponent uses ActiveXComponent and IWebBrowser2. There is an issue that the ‘Enter’ key is not being handled correctly, i.e. the Windows message never gets to the activeXHookWndProc call. Needless to say, that’s a bit of an issue.
I have a hack fix for it, which I’m not proud of. But I thought in the interest of the Juce community I’d share it here and maybe it can get the proper attention. The fix is:
- Find the Internet Explorer_Server window handle (a child of the control window created later)
- insert a hook WINDPROC (similar to wat th ActiveXComponent is doing now)
- When the Enter message arrives, SetFocus on the control window and pass the event back to the original wndProc
Here’s the code:
static LRESULT CALLBACK browserProcHook(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
for (auto* ax : ActiveXHelpers::activeXComps)
{
if (ax->control != nullptr && ax->control->browserHWND == hwnd)
{
if ((message == WM_KEYDOWN || message == WM_KEYUP) && VK_RETURN == wParam)
{
SetFocus(ax->control->controlHWND);
}
return ax->control->browserWndProc(hwnd, message, wParam, lParam);
}
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
// intercepts events going to an activeX control, so we can sneakily use the mouse events
static LRESULT CALLBACK activeXHookWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
for (auto* ax : ActiveXHelpers::activeXComps)
{
if (ax->control != nullptr && ax->control->controlHWND == hwnd)
{
//
// HACK FIX:
// The ActiveX component does not receive the Enter key event when using IWebBrowser2
// https://stackoverflow.com/questions/45919368/iwebbrowser2-doesnt-process-enter-key-in-div-tag
// https://social.msdn.microsoft.com/Forums/en-US/b682f756-da08-4aee-b764-c7d3c5bf2b33/enter-key-does-not-work-in-iwebbrowser2-control-when-custom-idochostuihandler-implementation-is?forum=vcmfcatl
// This ugly fix finds the web browser window handle, stores its window procesing function,
// attaches a hook so it intercepts it's events and when detecting a VK_RETURN sets the
// focus to the controlHWND.
//
// I agree this is incredibly ugly. IF a better option is found, please fix accordingly.
//
if (ax->control->browserHWND == nullptr)
{
// The browser window is a child to the controlWnd but is not available right away.
// It is constructed after this function has been called several times.
std::vector<HWND> children;
EnumChildWindows(hwnd, EnumWindows, LPARAM(&children));
for (auto c : children)
{
char buffer[256];
GetClassNameA(c, LPSTR(&buffer), 256);
if (strcmp(buffer, "Internet Explorer_Server") == 0)
{
ax->control->browserHWND = c;
ax->control->browserWndProc = (WNDPROC)GetWindowLongPtr(c, GWLP_WNDPROC);
SetWindowLongPtr(c, GWLP_WNDPROC, (LONG_PTR)Pimpl::browserProcHook);
break;
}
}
}
Ugly, I know. If a better option is available, by all means please fix it.
Thanks!