I migrated from CEF to WebView2 to render in-game overlays for better stability and performance. By default, you can't use WebView2 to render overlay using d3d11, but you can workaround this using https://gist.github.com/pabloko/5b5bfb71ac52d20dfad714c666a0c428
But here's a problem - when you click on the overlay html content, child window (Chrome_WidgetWin_0) will steal focus from main window,
and all your keyboard input will be received by Chrome_WidgetWin_0 window, that means your main window WndProc won't be able to receive
WM_KEYDOWN, WM_SYSKEYDOWN, etc while Chrome_WidgetWin_0 window have focus. To workaround this too, you can use my method below:
- In browser creation code edit:
HRESULT __stdcall EdgeBrowser::Invoke(HRESULT errorCode, ICoreWebView2CompositionController *_comp) {
if (FAILED(errorCode) || !GetWindow(mainWindow, GW_CHILD)) {
return failFast();
}
if(onChildWindowCreated) //make your own callback
onChildWindowCreated(GetWindow(mainWindow, GW_CHILD));- In your method where's browser is created:
Factory::createBrowser(..., [](HWND child) {
executeOnMainThread([&]() {
Overlay::originalWebView2ChildProc = (HRESULT (*)(HWND, UINT, WPARAM, LPARAM)) SetWindowLongPtrW(child, GWLP_WNDPROC, (LONG_PTR)Overlay::handleWebView2ChildProc);
}).wait();
});- Define handleWebView2ChildProc function:
HRESULT(*originalWebView2ChildProc)(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) = nullptr;
HRESULT Overlay::handleWebView2ChildProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch(message) {
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
case WM_INPUT:
case WM_CHAR:
case WM_SYSKEYUP:
case WM_SYSCHAR:
case WM_SYSCOMMAND:
case WM_KEYUP: {
Overlay::handleMessages(hwnd, message, wParam, lParam); //steal keyboard input from child window while it's focused and send to your message processing function to handle keys such open/close overlay, etc
if(!isOverlayShown) //restore focus when overlay became not visible so handleWebView2ChildProc won't be called until you click on overlay content again
SetFocus(MainWindow::windowHWND);
return 0;
}
default:
return originalWebView2ChildProc(hwnd, message, wParam, lParam);
}
}- Done. You can also send keyboard input manually from your code to the browser using
originalWebView2ChildProc.