最近,一位朋友提出希望完善F11和12功能,因此在这篇文章中,我将分享F11全屏和F12开发者工具的思路以及代码,做个记录的同时也希望对cefsharp开发感兴趣的朋友提供一些思路。
二、WPF使用CefSharp.Winform带来的问题
上文提到,为了更好的使用输入法,我将项目中的CefSharp.WPF转为了CefSharp.WinForms,通过WindowsFormsHost来承载CefSharp.WinForms
现在CefSharp的版本为:
<PackageReference Include="CefSharp.WinForms.NETCore" Version="120.1.110" />
同时带来一些问题
1、AllowsTransparency属性不能用
AllowsTransparency只能设置为fasle否则WindowsFormsHost将不可见
可能的原因是Windows Forms本身并不直接支持透明度的特性,而WPF窗体的透明度是通过更先进的图形系统实现的。
因此,当启用WPF窗体的透明度时,可能会导致与Windows Forms控件的嵌入和交互方面的问题,从而使WindowsFormsHost不可用或出现异常。
2、键盘事件和鼠标事件不起作用
当Windows Forms控件在WindowsFormsHost中获得焦点时,WPF的键盘事件可能不会直接传递给嵌入的Windows Forms控件。
为了解决这些问题,需要编写一些额外的代码来将键盘和鼠标事件
三、使用Win32 API拦截和处理特定窗口消息
以下为处理窗口信息的代码,部分代码来源于官方示例
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
private static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
private void SetupMessageInterceptor()
if (messageInterceptor != null)
messageInterceptor.ReleaseHandle();
messageInterceptor = null;
Task.Run(async () =>
while (true)
IntPtr chromeWidgetHostHandle;
if (ChromiumRenderWidgetHandleFinder.TryFindHandle(this, out chromeWidgetHostHandle))
messageInterceptor = new ChromiumWidgetNativeWindow(this, chromeWidgetHostHandle);
messageInterceptor.OnWndProc(message =>
const int WM_MOUSEACTIVATE = 0x0021;
const int WM_NCLBUTTONDOWN = 0x00A1;
const int WM_DESTROY = 0x0002;
const int WM_MOUSEWHEEL = 0x020A;
// Render process switch happened, need to find the new handle
if (message.Msg == WM_DESTROY)
SetupMessageInterceptor();
return false;
if (message.Msg == WM_MOUSEACTIVATE)
var topLevelWindowHandle = message.WParam;
PostMessage(topLevelWindowHandle, WM_NCLBUTTONDOWN, IntPtr.Zero, IntPtr.Zero);
if(message.Msg == WM_MOUSEWHEEL)
int rawDelta = (int)message.WParam.ToInt64();
int delta = rawDelta >> 16;
MouseWheelEvent?.Invoke(delta);
return false;
break;
await Task.Delay(10);
catch
View Code
WM_MOUSEACTIVATE 消息,它模拟在非客户区按下鼠标左键的操作。
WM_DESTROY 消息,说明窗口即将被销毁,它调用 SetupMessageInterceptor 方法重新设置消息拦截器。
WM_MOUSEWHEEL 消息,它触发一个事件 (MouseWheelEvent),传递鼠标滚轮的滚动量。
WM_MOUSEWHEEL 为处理浏览器网页缩放的消息,这里增加了MouseWheelEvent当有WM_MOUSEWHEEL 时
触发MouseWheelEvent来处理浏览器缩放,浏览器缩放可以参考 基于CefSharp开发浏览器(六)浏览器网页缩放
四、使用KeyboardHandler处理键盘事件
public class CustomKeyboardHandler: KeyboardHandler
public Action<int> KeyboardCallBack;
protected override bool OnKeyEvent(IWebBrowser chromiumWebBrowser, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey)
if (chromiumWebBrowser.IsBrowserInitialized)
KeyboardCallBack?.Invoke(windowsKeyCode);
return base.OnKeyEvent(chromiumWebBrowser, browser, type, windowsKeyCode, nativeKeyCode, modifiers, isSystemKey);
public class CustomWebBrowser : ChromiumWebBrowser
public CustomWebBrowser()
this.KeyboardHandler = new CustomKeyboardHandler();
使用KeyboardHandler的OnKeyEvent方法处理键盘事件如F5,F11,F12等
五、F11全屏
由于程序的主体为一个自定义的TabControl进行的网页多开,直接处理TabControl令其全屏比较麻烦,
这里采用当按下F11时弹出一个WPF窗体来承载现有的CefSharp控件,当按下F11时,获取当前tab页的cefsharp控件,并将其填充到F11窗体中,
再次按下F11时将cefsharp控件 从新填充到tab页中,这样可以保证全屏和非全屏状态下使用的是同一个cefsharp实例。
窗体定义如下:
<Window x:Class="MWebBrowser.View.F11Window"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="F11Window" Height="450" Width="800"
WindowState="Maximized"
WindowStyle="None">
<Grid x:Name="Parent">
</Grid>
</Window>
public partial class F11Window : Window
public WindowsFormsHost WebFormsHost { get; }
public F11Window()
InitializeComponent();
WebFormsHost = new WindowsFormsHost();
InitData();
private void InitData()
Parent.Children.Add(WebFormsHost);
F11 处理代码如下:
public static void F11(BrowserUserControl browserUserControl, WindowsFormsHost orgWebFormsHost)
DispatcherHelper.UIDispatcher.Invoke(() =>
if (f11Window != null)
ExitFullscreen(browserUserControl, orgWebFormsHost);
EnterFullscreen(browserUserControl, orgWebFormsHost);
private static void EnterFullscreen(BrowserUserControl browserUserControl, WindowsFormsHost orgWebFormsHost)
originalBounds = new Rect(
browserUserControl.CefWebBrowser.Margin.Left,
browserUserControl.CefWebBrowser.Margin.Top,
browserUserControl.CefWebBrowser.Width,
browserUserControl.CefWebBrowser.Height
f11Window = new F11Window();
orgWebFormsHost.Child.Controls.Remove(browserUserControl);
f11Window.WebFormsHost.Child = browserUserControl;
f11Window.Show();
Application.Current.MainWindow.Hide();
private static void ExitFullscreen(BrowserUserControl browserUserControl, WindowsFormsHost orgWebFormsHost)
f11Window.WebFormsHost.Child.Controls.Remove(browserUserControl);
orgWebFormsHost.Child = browserUserControl;
f11Window.Close();
f11Window = null;
Application.Current.MainWindow.Show();
六、F12开发者工具
CefSharp提供了两种开发者工具展示方式
1、ShowDevTools
这种直接弹出一个新窗口
2、ShowDevToolsDocked
这种方式将DevTools控件嵌入到Winform的SplitContainer中,代码如下:
public void ShowDevToolsDocked()
this.Invoke(() =>
if (browserSplitContainer.Panel2Collapsed)
browserSplitContainer.Panel2Collapsed = false;
Control devToolsControl = GetDevToolsControl();
if (devToolsControl == null || devToolsControl.IsDisposed)
CefWebBrowser.ShowDevToolsDocked(browserSplitContainer.Panel2, nameof(devToolsControl), DockStyle.Fill);
七、F12开发者工具
gitee地址:https://gitee.com/sirius_machao/mweb-browser
github地址:https://github.com/sirius-chao/MWebBrowser
项目邀请:如对该项目有兴趣,欢迎联系我共同开发!!!
天行健,君子以自强不息;
地势坤,君子以厚德载物;