WPF/WinForm中加载网页的几种方式及如何加载Flash库(WebBrowser/CEF)

2022-06-12 12:39:05 浏览数 (1)

前言

Webview2官方文档:

https://docs.microsoft.com/zh-cn/microsoft-edge/webview2/get-started/wpf

WPF加载网页的三种方式

  • WebBrowser IE内核
  • CEFSharp Chrome内核(三方库)
  • Webview2 Chrome内核(官方库)

CEFSharp:

https://cloud.tencent.com/developer/article/1895623

Webview2 :

WebView2未来应该是要替代WebBrowser的,虽然需要依赖本机自带的Edge chromium内核,但相信未来的windows 更新肯定会以Edge chromium内核代替IE内核,并且不需要重新下载Chrome浏览器,使用Edge也会有一样的浏览体验。而作为桌面开发人员来说,使用WebView2直接加载网页会比使用CefSharp来得更舒服,不再需要引入一堆的CEF类库,同时安装文件也会缩小很多。

Flash支持测试页面

https://sc.chinaz.com/donghua/220315391630.htm

准备工作

FlashPlayer

https://www.flash.cn/download-wins

其实我们不同的浏览器使用到的DLL是不同的

Windows

Chrome

FireFox

所以我们可以根据自己的需求去安装,不用全部安装到PC上。

Flash的现状

  • IE安装插件还可以使用
  • 360极速及QQ浏览器等,这些浏览器一般都是双内核,其中的Chromium内核版本一般都比较低,所以还可以继续加载Flash Player来使用,啥时候这些国产浏览器升级内核到88及以上版本,就彻底不支持了

获取系统IE版本

获取浏览器内核版本

https://www.psvmc.cn/zjtools/z/browserinfo/index.html

不要用下面这个地址,测试的不准确

https://ie.icoa.cn/

网上有这么个说法

WebBrowser使用的浏览器版本是IE7,这个说法其实是不太准确的。

应该这样说

WebBrowser使用的是系统版本的IE对应的兼容模式。 比如Win10的是IE11,对应的兼容模式是IE7。 所以我在Win10上用下面两种方式获取到的IE版本都是11。

方式1

代码语言:javascript复制
/// <summary>
/// 获取IE版本号
/// </summary>
/// <returns>
/// </returns>
public static int GetMajorVersion()
{
  //通过WebBrowser方案获取版本号
  return new WebBrowser().Version.Major;
}

方式2

代码语言:javascript复制
/// <summary>
/// IE浏览器版本号帮助类
/// </summary>
public static class IEVersionHelper
{
  /// <summary>
  /// 获取IE主版本号
  /// </summary>
  /// <returns>
  /// </returns>
  public static string GetMajorVersion()
  {
    var majorVersion = string.Empty;

    var detailVersion = GetDetailVersion();
    if (!string.IsNullOrWhiteSpace(detailVersion))
    {
      if (detailVersion.IndexOf(".", StringComparison.Ordinal) is int connectedCharFirstIndex && connectedCharFirstIndex > -1)
      {
        majorVersion = detailVersion.Substring(0, connectedCharFirstIndex);
      }
      else
      {
        majorVersion = detailVersion;
      }
    }

    return majorVersion;
  }

  /// <summary>
  /// 获取IE详细版本号
  /// </summary>
  /// <returns>
  /// </returns>
  public static string GetDetailVersion()
  {
    string text = @"SOFTWAREMicrosoftInternet Explorer";
    //通过注册表获取用户IE版本号
    RegistryKey mainKey = Registry.LocalMachine;
    RegistryKey subKey = mainKey.OpenSubKey(text);

    var versionNumber = subKey?.GetValue("svcVersion")?.ToString() ?? string.Empty;
    if (string.IsNullOrEmpty(versionNumber))
    {
      versionNumber = subKey?.GetValue("svcUpdateVersion")?.ToString() ?? string.Empty;
      if (string.IsNullOrEmpty(versionNumber))
      {
        versionNumber = subKey?.GetValue("Version")?.ToString() ?? string.Empty;
      }
    }
    return versionNumber;
  }
}

或者

代码语言:javascript复制
public static int GetCurrSystemIEVersion()
{
  try
  {
    RegistryKey mreg;
    mreg = Registry.LocalMachine;
    mreg = mreg.OpenSubKey(@"SoftwareMicrosoftInternet Explorer");
    string IEVersion = (string)mreg.GetValue("svcVersion");
    if (IEVersion == null)
    {
      IEVersion = (string)mreg.GetValue("Version");
    }
    mreg.Close();
    if (IEVersion.StartsWith("8"))
    {
      return 8;
    }
    if (IEVersion.StartsWith("9"))
    {
      return 9;
    }
    if (IEVersion.StartsWith("10"))
    {
      return 10;
    }
    if (IEVersion.StartsWith("11"))
    {
      return 11;
    }
    return 0;
  }
  catch (Exception)
  {
    return 0;
  }
}

注册表的生效规则

设置IE版本

当前用户配置

代码语言:javascript复制
# 32位
HKEY_CURRENT_USERSOFTWAREMicrosoftInternet ExplorerMAINFeatureControlFEATURE_BROWSER_EMULATION
# 64位
HKEY_CURRENT_USERSOFTWAREWow6432NodeMicrosoftInternet ExplorerMAINFeatureControlFEATURE_BROWSER_EMULATION

本机配置

代码语言:javascript复制
# 32位
HKEY_LOCAL_MACHINESOFTWAREMicrosoftInternet ExplorerMAINFeatureControlFEATURE_BROWSER_EMULATION
# 64位
HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoftInternet ExplorerMAINFeatureControlFEATURE_BROWSER_EMULATION

设置IE GPU加速

当前用户配置

代码语言:javascript复制
# 32位
HKEY_CURRENT_USERSOFTWAREMicrosoftInternet ExplorerMAINFeatureControlFEATURE_GPU_RENDERING
# 64位
HKEY_CURRENT_USERSOFTWAREWow6432NodeMicrosoftInternet ExplorerMAINFeatureControlFEATURE_GPU_RENDERING

本机配置

代码语言:javascript复制
# 32位
HKEY_LOCAL_MACHINESOFTWAREMicrosoftInternet ExplorerMAINFeatureControlFEATURE_GPU_RENDERING
# 64位
HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoftInternet ExplorerMAINFeatureControlFEATURE_GPU_RENDERING

32位和64位注册表的生效规则

系统

软件

生效的注册表

32 位

32 位

HKEY_CURRENT_USERSOFTWAREMicrosoftInternet ExplorerMAINFeatureControlFEATURE_BROWSER_EMULATION

64 位

64 位

HKEY_CURRENT_USERSOFTWAREMicrosoftInternet ExplorerMAINFeatureControlFEATURE_BROWSER_EMULATION

64 位

32 位

HKEY_CURRENT_USERSOFTWAREWow6432NodeMicrosoftInternet ExplorerMAINFeatureControlFEATURE_BROWSER_EMULATION

32 位

64 位

无法将 64 位版本的 Office 安装在 32 位版本的 Windows

注意

  1. HKEY_LOCAL_MACHINE 中设置的优先级要高于 HKEY_CURRENT_USER
  2. 建议配置HKEY_CURRENT_USERHKEY_LOCAL_MACHINE可能没有权限而报错。

注册表修改的两种方式

方式1

代码语言:javascript复制
string fileName = System.IO.Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName);
string fcRegKey32 = @"HKEY_CURRENT_USERSoftwareMicrosoftInternet ExplorerMainFeatureControlFEATURE_GPU_RENDERING";
Registry.SetValue(fcRegKey32, fileName, version, RegistryValueKind.DWord);

方式2

代码语言:javascript复制
string fileName = System.IO.Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName);
RegistryKey mreg;
mreg = Registry.CurrentUser;
mreg = mreg.OpenSubKey(@"SOFTWAREMicrosoftInternet ExplorerMAINFeatureControl");
RegistryKey m = mreg.OpenSubKey("FEATURE_GPU_RENDERING", true);
if (m != null)
{
  m.SetValue(fileName, version, RegistryValueKind.DWord);
  m.Close();
}
mreg.Flush();
mreg.Close();

注意

推荐方式1

注册表设置IE版本

记录WebBrowser控件使用IE渲染版本的路径:

注意

注册表不要修改HKEY_LOCAL_MACHINE下的,因为可能没有权限而导致修改失败。

工具类1

代码语言:javascript复制
public class WebBrowserHelper
{
  public static int GetCurrSystemIEVersion()
  {
    try
    {
      RegistryKey mreg;
      mreg = Registry.LocalMachine;
      mreg = mreg.OpenSubKey(@"SoftwareMicrosoftInternet Explorer");
      string IEVersion = (string)mreg.GetValue("svcVersion");
      if (IEVersion == null)
      {
        IEVersion = (string)mreg.GetValue("Version");
      }
      mreg.Close();
      if (IEVersion.StartsWith("8"))
      {
        return 8;
      }
      if (IEVersion.StartsWith("9"))
      {
        return 9;
      }
      if (IEVersion.StartsWith("10"))
      {
        return 10;
      }
      if (IEVersion.StartsWith("11"))
      {
        return 11;
      }
      return 0;
    }
    catch (Exception)
    {
      return 0;
    }
  }

  /// <summary>
  /// 32系统32位程序或64位系统上64位程序的注册表
  /// </summary>
  /// <param name="version"></param>
  /// <returns></returns>
  public static bool SetIEVersionInSys32(int version)
  {
    try
    {
      if (version < 8)
      {
        return false;
      }
      int v = 8888;
      if (version == 9)
      {
        v = 9999;
      }
      if (version >= 10)
      {
        v = 10001;
      }
      if (version >= 11)
      {
        v = 11001;
      }

      string fileName = System.IO.Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName);
      string rkIEVersion32 = @"HKEY_CURRENT_USERSoftwareMicrosoftInternet ExplorerMainFeatureControlFEATURE_BROWSER_EMULATION";
      string rkIEGPU32 = @"HKEY_CURRENT_USERSoftwareMicrosoftInternet ExplorerMainFeatureControlFEATURE_GPU_RENDERING";
      Registry.SetValue(rkIEVersion32, fileName, v, RegistryValueKind.DWord);
      Registry.SetValue(rkIEGPU32, fileName, 1, RegistryValueKind.DWord);
      return true;
    }
    catch (Exception)
    {
    }
    return false;
  }

  /// <summary>
  /// 64位系统上32程序的注册表
  /// </summary>
  /// <param name="version"></param>
  /// <returns></returns>
  public static bool SetIEVersionInSys64(int version)
  {
    if (version < 8)
    {
      return false;
    }
    try
    {
      int v = 8888;
      if (version == 9)
      {
        v = 9999;
      }
      if (version >= 10)
      {
        v = 10001;
      }

      if (version >= 11)
      {
        v = 11001;
      }
      string fileName = System.IO.Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName);
      string rkIEVersion = @"HKEY_CURRENT_USERSOFTWAREWow6432NodeMicrosoftInternet ExplorerMainFeatureControlFEATURE_BROWSER_EMULATION";
      string rkIEGPU = @"HKEY_CURRENT_USERSOFTWAREWow6432NodeMicrosoftInternet ExplorerMainFeatureControlFEATURE_GPU_RENDERING";
      Registry.SetValue(rkIEVersion, fileName, v, RegistryValueKind.DWord);
      Registry.SetValue(rkIEGPU, fileName, 1, RegistryValueKind.DWord);
      return true;
    }
    catch (Exception) { }
    return false;
  }

  /// <summary>
  /// 设置为计算机上的最新IE版本
  /// </summary>
  /// <returns></returns>
  public static bool SetWebBrowserLastVersion()
  {
    int version = GetCurrSystemIEVersion();
    bool f1 = SetIEVersionInSys32(version);
    bool f2 = SetIEVersionInSys64(version);

    if (f1 || f2)
    {
      return true;
    }

    return false;
  }

  /// <summary>
  /// 设置WebBrowser对应的IE版本
  /// </summary>
  /// <param name="version"></param>
  /// <returns></returns>
  public static bool SetWebBrowserVersion(int version)
  {
    bool f1 = SetIEVersionInSys32(version);
    bool f2 = SetIEVersionInSys64(version);

    if (f1 || f2)
    {
      return true;
    }

    return false;
  }
}

工具类2

代码语言:javascript复制
public class IEHelper
{
  /// <summary>
  /// 定义IE版本的枚举
  /// </summary>
  public enum IeVersion
  {
    ie11强制,//11001 (0x2AF9) IE11
    ie11,//11000 (0x2AF8) IE11
    ie10强制,//10001 (0x2711) IE10
    ie10,//10000 (0x02710) IE10
    ie9强制,//9999 (0x270F) IE9
    ie9,//9000 (0x2328) IE9.
    ie8强制,//8888 (0x22B8) IE8. 强制IE8标准模式显示,忽略!DOCTYPE指令
    ie8,//8000 (0x1F40) IE8. 默认设置,在IE8标准模式中按照网页上!DOCTYPE指令展示网页
    ie7//7000 (0x1B58) 使用WebBrowser Control控件的应用程序所使用的默认值,在IE7标准模式中按照网页上!DOCTYPE指令来展示网页
  }

  /// <summary>
  /// 设置WebBrowser的默认版本
  /// </summary>
  /// <param name="ver">
  /// IE版本
  /// </param>
  public static void SetIE(IeVersion ver)
  {
    //获取程序名称
    //string productName = AppDomain.CurrentDomain.SetupInformation.ApplicationName;
    string productName = System.IO.Path.GetFileName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
    object version;
    switch (ver)
    {
      case IeVersion.ie7:
        version = 0x1B58;
        break;

      case IeVersion.ie8:
        version = 0x1F40;
        break;

      case IeVersion.ie8强制:
        version = 0x22B8;
        break;

      case IeVersion.ie9:
        version = 0x2328;
        break;

      case IeVersion.ie9强制:
        version = 0x270F;
        break;

      case IeVersion.ie10:
        version = 0x2710;
        break;

      case IeVersion.ie10强制:
        version = 0x2711;
        break;

      case IeVersion.ie11:
        version = 0x2AF8;
        break;

      case IeVersion.ie11强制:
        version = 0x2AF9;
        break;

      default:
        version = 0x1F40;
        break;
    }
    string fcRegKey32 = @"HKEY_CURRENT_USERSoftwareMicrosoftInternet ExplorerMainFeatureControlFEATURE_BROWSER_EMULATION";
    string fcRegKey64 = @"HKEY_CURRENT_USERSOFTWAREWOW6432NodeMicrosoftInternet ExplorerMainFeatureControlFEATURE_BROWSER_EMULATION";
    Registry.SetValue(fcRegKey32, productName, version, RegistryValueKind.DWord);
    if (Environment.Is64BitOperatingSystem)
    {
      Registry.SetValue(fcRegKey64, productName, version, RegistryValueKind.DWord);
    }
  }
}

调用

代码语言:javascript复制
int version = GetMajorVersion();
Console.WriteLine("version:"   version);

if (version >= 9)
{
  IEHelper.SetIE(IEHelper.IeVersion.ie9);
}

注意

网上有这么个说法,把版本设置为非IE的版本号,会使用Edge,这个说法是错误的。 虽然更改后加载检测浏览器内核的网页上显示是Edge,但是其实上并不是使用的Edge。 WOW6432Node其实不是64位程序的配置,而是64位系统32位程序使用到的配置。 Registry.SetValue方法会自动创建不存在的路径和值。

WebBrowser

WPF下的WebBrowser存在内存泄漏的问题,所以这里用WinForm实现。

WebBrowser调用的就是本机IE浏览器,并且WebBrowser默认就是运行在IE7 mode下。

添加Falsh插件

有些老的系统必须用IE执行的,就只能用WebBrowser了。

保证IE上能运行Flash只需要安装flashplayerax_install_cn.exe就可以了。

首先我们要判断Flash有没有安装

代码语言:javascript复制
private bool checkFlashInstall()
{
  Type type = Type.GetTypeFromProgID("ShockwaveFlash.ShockwaveFlash");
  if (type == null)
  {
    return false;
  }

  object flashObject = Activator.CreateInstance(type);
  string versionString = flashObject
    .GetType()
    .InvokeMember("GetVariable", BindingFlags.InvokeMethod, null, flashObject, new object[] { "$version" }) as string;

  Console.WriteLine("Flash版本:"   versionString);
  Marshal.ReleaseComObject(flashObject);
  return true;
}

安装EXE程序

代码语言:javascript复制
private void installEXE(string fileName, string arguments)
{
  string result = "";
  try
  {
    using (Process process = new Process())
    {
      process.StartInfo.FileName = fileName;
      process.StartInfo.Arguments = arguments;
      process.StartInfo.CreateNoWindow = true;
      process.StartInfo.UseShellExecute = false; // 要获取输出,此值必须为 false。
      process.StartInfo.RedirectStandardOutput = true;
      process.StartInfo.RedirectStandardError = true;

      process.Start();
      process.WaitForExit(); // 等待执行完毕
      result = process.StandardError.ReadToEnd(); // 获取输出值
      process.Close();
    }
  }
  catch (Exception ex)
  {
    result = ex.Message;
  }

  Console.WriteLine("result:"   result);
}

注意

安装成功或退出,result返回的字符串都是空字符串。

判断并安装

代码语言:javascript复制
private void Form1_Load(object sender, EventArgs e)
{
    bool isInstallFlash = checkFlashInstall();
    if (!isInstallFlash)
    {
        installEXE("./Libs/flashplayerax_install_cn.exe", "");
    }

    extendedWebBrowser1.Url = new Uri(url);
}

窗口弹出

当页面中打开新页面的方式是window.open的时候,默认的行为是调用系统的IE打开,这样就会出现一个问题,打开的IE页面是读取不到我们页面的cookie数据的,导致登录失效。

所以解决的方法是

  1. 获取弹出页面的网址
  2. 本窗口打开或者新窗口打开

那么怎么获取到弹出页面的网址呢?

默认的WebBrowser新打开的窗口会用系统默认的IE打开,并且我们也没法获取新窗口的地址自行处理。

所以我们自定义WebBrowser保证能获取新窗口的地址。

自定义ExtendedWebBrowser

代码语言:javascript复制
using System;

namespace WinFormWebFlash.Views
{
  public class ExtendedWebBrowser : System.Windows.Forms.WebBrowser
  {
    private System.Windows.Forms.AxHost.ConnectionPointCookie cookie;
    private WebBrowserExtendedEvents events;

    public event EventHandler BeforeNavigate;

    public event EventHandler BeforeNewWindow;

    [System.Runtime.InteropServices.ComImport(), System.Runtime.InteropServices.Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D"),
     System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIDispatch),
     System.Runtime.InteropServices.TypeLibType(System.Runtime.InteropServices.TypeLibTypeFlags.FHidden)]
    public interface DWebBrowserEvents2
    {
      [System.Runtime.InteropServices.DispId(250)]
      void BeforeNavigate2(
        [System.Runtime.InteropServices.In,
         System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.IDispatch)] object pDisp,
        [System.Runtime.InteropServices.In] ref object URL,
        [System.Runtime.InteropServices.In] ref object flags,
        [System.Runtime.InteropServices.In] ref object targetFrameName, [System.Runtime.InteropServices.In] ref object postData,
        [System.Runtime.InteropServices.In] ref object headers,
        [System.Runtime.InteropServices.In,
         System.Runtime.InteropServices.Out] ref bool cancel);

      [System.Runtime.InteropServices.DispId(273)]
      void NewWindow3(
        [System.Runtime.InteropServices.In,
         System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.IDispatch)] object pDisp,
        [System.Runtime.InteropServices.In, System.Runtime.InteropServices.Out] ref bool cancel,
        [System.Runtime.InteropServices.In] ref object flags,
        [System.Runtime.InteropServices.In] ref object URLContext,
        [System.Runtime.InteropServices.In] ref object URL);
    }

    //This method will be called to give you a chance to create your own event sink
    protected override void CreateSink()
    {
      //MAKE SURE TO CALL THE BASE or the normal events won't fire
      base.CreateSink();
      events = new WebBrowserExtendedEvents(this);
      cookie = new System.Windows.Forms.AxHost.ConnectionPointCookie(this.ActiveXInstance, events, typeof(DWebBrowserEvents2));
    }

    protected override void DetachSink()
    {
      if (null != cookie)
      {
        cookie.Disconnect();
        cookie = null;
      }
      base.DetachSink();
    }

    protected void OnBeforeNavigate(string url, string frame, out bool cancel)
    {
      EventHandler h = BeforeNavigate;
      WebBrowserExtendedNavigatingEventArgs args = new WebBrowserExtendedNavigatingEventArgs(url, frame);
      if (null != h)
      {
        h(this, args);
      }
      //Pass the cancellation chosen back out to the events
      cancel = args.Cancel;
    }

    protected void OnBeforeNewWindow(string url, out bool cancel)
    {
      EventHandler h = BeforeNewWindow;
      WebBrowserExtendedNavigatingEventArgs args = new WebBrowserExtendedNavigatingEventArgs(url, null);
      if (null != h)
      {
        h(this, args);
      }
      cancel = args.Cancel;
    }

    //This class will capture events from the WebBrowser
    private class WebBrowserExtendedEvents : System.Runtime.InteropServices.StandardOleMarshalObject, DWebBrowserEvents2
    {
      private ExtendedWebBrowser _Browser;

      public WebBrowserExtendedEvents(ExtendedWebBrowser browser)
      { _Browser = browser; }

      //Implement whichever events you wish
      public void BeforeNavigate2(object pDisp, ref object URL, ref object flags, ref object targetFrameName, ref object postData, ref object headers, ref bool cancel)
      {
        _Browser.OnBeforeNavigate((string)URL, (string)targetFrameName, out cancel);
      }

      public void NewWindow3(object pDisp, ref bool cancel, ref object flags, ref object URLContext, ref object URL)
      {
        _Browser.OnBeforeNewWindow((string)URL, out cancel);
      }
    }
  }

  public class WebBrowserExtendedNavigatingEventArgs : System.ComponentModel.CancelEventArgs
  {
    private string _Frame;
    private string _Url;

    public WebBrowserExtendedNavigatingEventArgs(string url, string frame)
      : base()
      {
        _Url = url;
        _Frame = frame;
      }

    public string Frame
    {
      get { return _Frame; }
    }

    public string Url
    {
      get { return _Url; }
    }
  }
}

回到Form1.cs[设计]窗口,在菜单生成中,点生成解决方案

一会之后在工具箱的最上方就会出现一个新的组件ExtendedWebBrowser,把ExtendedWebBrowser拖进来。

ExtendedWebBrowser的事件里双击BeforeNewWindow并添加代码:

本窗口打开

代码语言:javascript复制
private void extendedWebBrowser1_BeforeNewWindow(object sender, EventArgs e)
{
  WebBrowserExtendedNavigatingEventArgs eventArgs = e as WebBrowserExtendedNavigatingEventArgs;
  eventArgs.Cancel = true;
  ((ExtendedWebBrowser)sender).Navigate(eventArgs.Url);
}

或者

新窗口打开

代码语言:javascript复制
private void extendedWebBrowser1_BeforeNewWindow(object sender, EventArgs e)
{
  WebBrowserExtendedNavigatingEventArgs eventArgs = e as WebBrowserExtendedNavigatingEventArgs;
  eventArgs.Cancel = true;
  Form1 form1 = new Form1();
  form1.url = eventArgs.Url;
  form1.Show();
}

WinForm显示模糊的解决办法

WinForm 对高分辨率屏幕的适配并不是很好,当分辨率较高时,Windows 系统会将程序里面的字体进行缩放,在 Windows 10 系统尤其严重,这将导致程序的界面大小变化,字体也会变得模糊。

以下两种方法任选其一即可。

方法1

我们用WebBrowser加载的网页,会看起来有点模糊,设置DPI设置的问题,解决方法如下:

Form的属性设置如下

将 Form 的 AutoScaleMode 属性设置为 DPI

在 Program.cs 中添加以下代码:

代码语言:javascript复制
internal static class Program
{
  /// <summary>
  /// 应用程序的主入口点。
  /// </summary>
  [STAThread]
  private static void Main()
  {
    //添加的代码
    if (Environment.OSVersion.Version.Major >= 6)
    {
      SetProcessDPIAware();
    }

    //原代码
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
  }

  //添加的代码
  [System.Runtime.InteropServices.DllImport("user32.dll")]
  private static extern bool SetProcessDPIAware();
}

方法2

知道了导致程序模糊的原因,找到相应的解决方法就很简单了,我们只需要让程序感知 DPI ,当 DPI 较高时禁止 Windows 对其进行自动缩放。

注意事项:该方法适用于 .NET Framework 版本大于等于4.5的程序。

右键项目,添加应用程序清单文件

把其中的下面的代码部分解除注释:

代码语言:javascript复制
<application xmlns="urn:schemas-microsoft-com:asm.v3">
  <windowsSettings>
    <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
  </windowsSettings>
</application>

在程序配置文件(app.config)的appSettings节点下添加如下代码

代码语言:javascript复制
<add key="EnableWindowsFormsHighDpiAutoResizing" value="true" />

结果大致如下

代码语言:javascript复制
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
  </startup>
  <appSettings>
    <add key="EnableWindowsFormsHighDpiAutoResizing" value="true" />
  </appSettings>
</configuration>

CEF加载Flash

找到本地flash的dll(pepflashplayer.dll)

项目中新建plugins,添加pepflashplayer.dll,右击属性,改为始终复制

CEF初始化配置

代码语言:javascript复制
CefSettings settings = new CefSharp.CefSettings()
settings.CefCommandLineArgs["enable-system-flash"] = "1";
settings.CefCommandLineArgs.Add("ppapi-flash-version", "32.0.0.171");
settings.CefCommandLineArgs.Add("ppapi-flash-path", @"pluginspepflashplayer.dll");
Cef.Initialize(settings);

0 人点赞