diff --git a/CefSharp.Wpf.HwndHost.Example/App.config b/CefSharp.Wpf.HwndHost.Example/App.config new file mode 100644 index 0000000000..1e8988739d --- /dev/null +++ b/CefSharp.Wpf.HwndHost.Example/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/CefSharp.Wpf.HwndHost.Example/App.xaml b/CefSharp.Wpf.HwndHost.Example/App.xaml new file mode 100644 index 0000000000..4f5c756edb --- /dev/null +++ b/CefSharp.Wpf.HwndHost.Example/App.xaml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/CefSharp.Wpf.HwndHost.Example/App.xaml.cs b/CefSharp.Wpf.HwndHost.Example/App.xaml.cs new file mode 100644 index 0000000000..d2d4a5c6a8 --- /dev/null +++ b/CefSharp.Wpf.HwndHost.Example/App.xaml.cs @@ -0,0 +1,62 @@ +// Copyright © 2019 The CefSharp Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +using System; +using System.IO; +using System.Windows; +using CefSharp.Wpf.HwndHost.Handler; + +namespace CefSharp.Wpf.HwndHost.Example +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + public App() + { +#if !NETCOREAPP3_1_OR_GREATER + CefRuntime.SubscribeAnyCpuAssemblyResolver(); +#endif + } + + protected override void OnStartup(StartupEventArgs e) + { + var settings = new CefSettings() + { + //By default CefSharp will use an in-memory cache, you need to specify a Cache Folder to persist data + CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\\Cache") + }; + + //Example of setting a command line argument + //Enables WebRTC + // - CEF Doesn't currently support permissions on a per browser basis see https://bitbucket.org/chromiumembedded/cef/issues/2582/allow-run-time-handling-of-media-access + // - CEF Doesn't currently support displaying a UI for media access permissions + // + //NOTE: WebRTC Device Id's aren't persisted as they are in Chrome see https://bitbucket.org/chromiumembedded/cef/issues/2064/persist-webrtc-deviceids-across-restart + settings.CefCommandLineArgs.Add("enable-media-stream"); + //https://peter.sh/experiments/chromium-command-line-switches/#use-fake-ui-for-media-stream + settings.CefCommandLineArgs.Add("use-fake-ui-for-media-stream"); + //For screen sharing add (see https://bitbucket.org/chromiumembedded/cef/issues/2582/allow-run-time-handling-of-media-access#comment-58677180) + settings.CefCommandLineArgs.Add("enable-usermedia-screen-capturing"); + + //See https://github.com/cefsharp/CefSharp/wiki/General-Usage#multithreadedmessageloop + //The default is true + const bool multiThreadedMessageLoop = true; + + IBrowserProcessHandler browserProcessHandler = null; + + if(!multiThreadedMessageLoop) + { + settings.MultiThreadedMessageLoop = false; + browserProcessHandler = new IntegratedMessageLoopBrowserProcessHandler(Dispatcher); + } + + // Make sure you set performDependencyCheck false + Cef.Initialize(settings, performDependencyCheck: false, browserProcessHandler: browserProcessHandler); + + base.OnStartup(e); + } + } +} diff --git a/CefSharp.Wpf.HwndHost.Example/AssemblyInfo.cs b/CefSharp.Wpf.HwndHost.Example/AssemblyInfo.cs new file mode 100644 index 0000000000..ed33db9bfa --- /dev/null +++ b/CefSharp.Wpf.HwndHost.Example/AssemblyInfo.cs @@ -0,0 +1,14 @@ +// Copyright © 2019 The CefSharp Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/CefSharp.Wpf.HwndHost.Example/Behaviours/HoverLinkBehaviour.cs b/CefSharp.Wpf.HwndHost.Example/Behaviours/HoverLinkBehaviour.cs new file mode 100644 index 0000000000..1fc77b3656 --- /dev/null +++ b/CefSharp.Wpf.HwndHost.Example/Behaviours/HoverLinkBehaviour.cs @@ -0,0 +1,34 @@ +using System.Windows; +using System; +using Microsoft.Xaml.Behaviors; + +namespace CefSharp.Wpf.HwndHost.Example.Behaviours +{ + public class HoverLinkBehaviour : Behavior + { + // Using a DependencyProperty as the backing store for HoverLink. This enables animation, styling, binding, etc... + public static readonly DependencyProperty HoverLinkProperty = DependencyProperty.Register("HoverLink", typeof(string), typeof(HoverLinkBehaviour), new PropertyMetadata(string.Empty)); + + public string HoverLink + { + get { return (string)GetValue(HoverLinkProperty); } + set { SetValue(HoverLinkProperty, value); } + } + + protected override void OnAttached() + { + AssociatedObject.StatusMessage += OnStatusMessageChanged; + } + + protected override void OnDetaching() + { + AssociatedObject.StatusMessage -= OnStatusMessageChanged; + } + + private void OnStatusMessageChanged(object sender, StatusMessageEventArgs e) + { + var chromiumWebBrowser = sender as ChromiumWebBrowser; + chromiumWebBrowser.Dispatcher.BeginInvoke((Action)(() => HoverLink = e.Value)); + } + } +} diff --git a/CefSharp.Wpf.HwndHost.Example/Behaviours/TextBoxBindingUpdateOnEnterBehaviour.cs b/CefSharp.Wpf.HwndHost.Example/Behaviours/TextBoxBindingUpdateOnEnterBehaviour.cs new file mode 100644 index 0000000000..24ad3b4e7a --- /dev/null +++ b/CefSharp.Wpf.HwndHost.Example/Behaviours/TextBoxBindingUpdateOnEnterBehaviour.cs @@ -0,0 +1,28 @@ +using System.Windows.Controls; +using System.Windows.Input; +using Microsoft.Xaml.Behaviors; + +namespace CefSharp.Wpf.HwndHost.Example.Behaviours +{ + public class TextBoxBindingUpdateOnEnterBehaviour : Behavior + { + protected override void OnAttached() + { + AssociatedObject.KeyDown += OnTextBoxKeyDown; + } + + protected override void OnDetaching() + { + AssociatedObject.KeyDown -= OnTextBoxKeyDown; + } + + private void OnTextBoxKeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter) + { + var txtBox = sender as TextBox; + txtBox.GetBindingExpression(TextBox.TextProperty).UpdateSource(); + } + } + } +} diff --git a/CefSharp.Wpf.HwndHost.Example/CefSharp.Wpf.HwndHost.Example.csproj b/CefSharp.Wpf.HwndHost.Example/CefSharp.Wpf.HwndHost.Example.csproj new file mode 100644 index 0000000000..fea51297f1 --- /dev/null +++ b/CefSharp.Wpf.HwndHost.Example/CefSharp.Wpf.HwndHost.Example.csproj @@ -0,0 +1,50 @@ + + + net472 + WinExe + x86;x64 + false + true + AllRules.ruleset + app.manifest + CefSharp.Wpf.HwndHost.Example.App + false + win7-x86;win7-x64 + 9.0 + + + + + + + + PreserveNewest + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CefSharp.Wpf.HwndHost.Example/CefSharp.Wpf.HwndHost.Example.netcore.csproj b/CefSharp.Wpf.HwndHost.Example/CefSharp.Wpf.HwndHost.Example.netcore.csproj new file mode 100644 index 0000000000..5ce3208620 --- /dev/null +++ b/CefSharp.Wpf.HwndHost.Example/CefSharp.Wpf.HwndHost.Example.netcore.csproj @@ -0,0 +1,67 @@ + + + + + obj.netcore\ + bin.netcore\ + + + + + + WinExe + netcoreapp3.1;net5.0-windows + $(TargetFrameworks);net6.0-windows + CefSharp.Wpf.HwndHost.Example + CefSharp.Wpf.HwndHost.Example + true + false + app.manifest + MinimumRecommendedRules.ruleset + x86;x64;arm64 + + arm64 + CefSharp.Wpf.HwndHost.Example.App + + Major + win-x86;win-x64 + win-x86 + win-x64 + win-arm64 + false + 9.0 + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + PreserveNewest + + + + + + + + + + + + + diff --git a/CefSharp.Wpf.HwndHost.Example/Converter/EnvironmentConverter.cs b/CefSharp.Wpf.HwndHost.Example/Converter/EnvironmentConverter.cs new file mode 100644 index 0000000000..a5564df204 --- /dev/null +++ b/CefSharp.Wpf.HwndHost.Example/Converter/EnvironmentConverter.cs @@ -0,0 +1,19 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace CefSharp.Wpf.HwndHost.Example.Converter +{ + public class EnvironmentConverter : IValueConverter + { + object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return Environment.Is64BitProcess ? "x64" : "x86"; + } + + object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return Binding.DoNothing; + } + } +} diff --git a/CefSharp.Wpf.HwndHost.Example/Converter/TitleConverter.cs b/CefSharp.Wpf.HwndHost.Example/Converter/TitleConverter.cs new file mode 100644 index 0000000000..60333176e4 --- /dev/null +++ b/CefSharp.Wpf.HwndHost.Example/Converter/TitleConverter.cs @@ -0,0 +1,19 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace CefSharp.Wpf.HwndHost.Example.Converter +{ + public class TitleConverter : IValueConverter + { + object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return "CefSharp.MinimalExample.Wpf.HwndHost - " + (value ?? "No Title Specified"); + } + + object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return Binding.DoNothing; + } + } +} diff --git a/CefSharp.Wpf.HwndHost.Example/Handlers/DisplayHandler.cs b/CefSharp.Wpf.HwndHost.Example/Handlers/DisplayHandler.cs new file mode 100644 index 0000000000..48b8f6c812 --- /dev/null +++ b/CefSharp.Wpf.HwndHost.Example/Handlers/DisplayHandler.cs @@ -0,0 +1,53 @@ +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; + +namespace CefSharp.Wpf.HwndHost.Example.Handlers +{ + public class DisplayHandler : CefSharp.Handler.DisplayHandler + { + private Border parent; + private Window fullScreenWindow; + + protected override void OnFullscreenModeChange(IWebBrowser chromiumWebBrowser, IBrowser browser, bool fullscreen) + { + var webBrowser = (ChromiumWebBrowser)chromiumWebBrowser; + + _ = webBrowser.Dispatcher.InvokeAsync(() => + { + if (fullscreen) + { + //In this example the parent is a Border, if your parent is a different type + //of control then update this code accordingly. + parent = (Border)VisualTreeHelper.GetParent(webBrowser); + + //NOTE: If the ChromiumWebBrowser instance doesn't have a direct reference to + //the DataContext in this case the BrowserTabViewModel then your bindings won't + //be updated/might cause issues like the browser reloads the Url when exiting + //fullscreen. + parent.Child = null; + + fullScreenWindow = new Window + { + WindowStyle = WindowStyle.None, + WindowState = WindowState.Maximized, + Content = webBrowser + }; + fullScreenWindow.Loaded += (_,_) => webBrowser.Focus(); + + fullScreenWindow.ShowDialog(); + } + else + { + fullScreenWindow.Content = null; + + parent.Child = webBrowser; + + fullScreenWindow.Close(); + fullScreenWindow = null; + parent = null; + } + }); + } + } +} diff --git a/CefSharp.Wpf.HwndHost.Example/MainWindow.xaml b/CefSharp.Wpf.HwndHost.Example/MainWindow.xaml new file mode 100644 index 0000000000..d775e488aa --- /dev/null +++ b/CefSharp.Wpf.HwndHost.Example/MainWindow.xaml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + +