Auch mit Visual Studio 2022 ist F# noch immer ein Stiefkind was WinForms Entwicklung angeht, trotzdem sind Dinge wie gehabt wesentlich knapper, präziser und je nach Geschmack schöner mit F# abzubilden – im speziellen eine sehr einfache Kiosk App die nichts anderes als eine Seite Anzeigen soll von der man am besten nicht “entkommt”:
- Kein Kontextmenü
- Keine Downloads bzw. nur für Autostart (bestimmte Dateiextension)
- Keine neuen Fenster
- Nur bestimmte URLs (Regex) erlaubt
Ergebnis:
open System
open System.Windows.Forms
open System.IO
open System.Text.RegularExpressions
open System.Diagnostics
open Microsoft.Web.WebView2.WinForms
open Microsoft.Web.WebView2.Core
let InitForm (env:CoreWebView2Environment) =
let webViewForm = new Form(Text = "Kiosk Titel", Width=int (float Screen.PrimaryScreen.Bounds.Width * 0.8), Height=int (float Screen.PrimaryScreen.Bounds.Height * 0.6), StartPosition=FormStartPosition.CenterScreen, ShowIcon=false)
let webView = new WebView2()
webView.Dock <- System.Windows.Forms.DockStyle.Fill
webView.Location <- new System.Drawing.Point(0, 0)
webViewForm.Controls.Add webView
webView.EnsureCoreWebView2Async(env) |> ignore
webView.CoreWebView2InitializationCompleted.AddHandler(fun sender args ->
webView.CoreWebView2.Settings.AreDefaultContextMenusEnabled <- false
webView.CoreWebView2.Settings.AreDevToolsEnabled <- false
webView.CoreWebView2.Settings.AreBrowserAcceleratorKeysEnabled <- false
webView.CoreWebView2.Settings.AreDefaultScriptDialogsEnabled <- false
webView.CoreWebView2.Settings.AreHostObjectsAllowed <- false
webView.CoreWebView2.Settings.IsPasswordAutosaveEnabled <- false
webView.CoreWebView2.Settings.IsGeneralAutofillEnabled <- false
webView.CoreWebView2.Settings.IsWebMessageEnabled <- false
webView.CoreWebView2.DownloadStarting.AddHandler(fun downloadsender downloadargs ->
let deferral = downloadargs.GetDeferral()
System.Threading.SynchronizationContext.Current.Post(fun _ ->
downloadargs.Handled <- true // no download dialog
downloadargs.DownloadOperation.StateChanged.AddHandler(fun statesender stateargs ->
if (downloadargs.DownloadOperation.State = CoreWebView2DownloadState.Completed) then
if (System.IO.Path.GetExtension(downloadargs.DownloadOperation.ResultFilePath).ToUpper() = ".XXX") then // valid extensions to start
let proc=new ProcessStartInfo(downloadargs.DownloadOperation.ResultFilePath)
proc.UseShellExecute <- true
Process.Start(proc) |> ignore
)
deferral.Dispose()
, null)
)
webView.CoreWebView2.NavigationStarting.AddHandler(fun navigatesender navigateargs ->
if (Regex.Match(navigateargs.Uri,"^https://(mysite|myothersite)\.local/.*", RegexOptions.IgnoreCase).Success = false) then navigateargs.Cancel <- true
)
webView.CoreWebView2.NewWindowRequested.AddHandler(fun newwindowsender newwindowargs ->
newwindowargs.Handled <- true // do not open window
)
webView.CoreWebView2.Navigate "https://mysite.local" |> ignore
)
webViewForm
[<EntryPoint; STAThread>]
let main argv =
let userDataFolder = $"{Path.GetTempPath()}\KioskWebUserData"
let options = new CoreWebView2EnvironmentOptions("--kiosk")
let env=CoreWebView2Environment.CreateAsync("",userDataFolder,options).GetAwaiter().GetResult()
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(false)
Application.Run(InitForm env)
0
Projektdatei:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1020.30" />
</ItemGroup>
</Project>