I am trying to create a software in WPF which hosts a browser (WebView2 currently 1.0.818.41) and also show a OnScreenKeyboard
when there is a input field focused in the browser.
I have done this kind of stuff with CefSharp in WPF before but I cannot do it with WebView2 currently. My problem is I do not find a way to send keystrokes from the OnScreenKeyboard
(or from the WPF Window) to the Browser.
In CefSharp there we have a function called ChromiumWebBrowser.GetHost().SendKeyEvent()
but I cannot find something similar in WebView2.
Am I blind or is this something which is currently not implemented (or maybe not planned)?
Thank you in advance!
There is no direct way. What can be done is execute some JS, which in turn posts a message to WebView. This message can then be caught back in wv2_WebMessageReceived
event.
There is extensive documentation on the interop between.NET and JS and interop between JS and .NET WPF Forms here.
A solution would be to inject a sendMessage
JS function in the NavigationStarting
event:
private void wv2_NavigationStarting(Microsoft.UI.Xaml.Controls.WebView2 sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationStartingEventArgs args){
var sc = "function sendMessage(txt) { window.chrome.webview.postMessage(txt); }";
wv2.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(sc);
}
Now you collect input fields and add onfocus
and onblur
events to these input fields for example in the NavigationCompleted
event like this:
private void wv2_NavigationCompleted(Microsoft.UI.Xaml.Controls.WebView2 sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs args){
string script = "const collection ="+
"document.getElementsByTagName(\"input\");" +
"for (let i = 0; i < collection.length; i++){" +
"collection[i].onfocus= ()=>{ sendMessage('onFocus('+collection[i].name')'); }; " +
"collection[i].onblur= (ev)=>{ sendMessage('onBlur('+collection[i].name')'); };"+
"}";
sender.ExecuteScriptAsync(script);
}
Now catch the message in the wv2_WebMessageReceived
event:
private void wv2_WebMessageReceived(Microsoft.UI.Xaml.Controls.WebView2 sender, Microsoft.Web.WebView2.Core.CoreWebView2WebMessageReceivedEventArgs args)
{
var postMess = args.TryGetWebMessageAsString();
if (postMess == "onFocus(nameOfField)" )
{
// here activate the button(keyboard)
// store the Name on focusField variable
}
if (postMess == "onBlur" && paneShown)
{
// here deactivate the button(keyboard)
// release the focusField
}
}
Now you can send a click event to the input fields:
private void btn_Clicked(Object sender, EventArgs args)
{
var script = "var field "+
"= document.getElementsByName("+focusField+");" +
" field.value+=field.value"+args.keyValue();
wv2.CoreWebView2.ExecuteScriptAsync(script);
}
wv2
is an instance of WebView2
and the code is typed directly here and not compiled. Hope you get the idea.