温故知新,遇见WPF/WinForms,托管控件WebBrowser按本机浏览器版本修正仿真配置,提高运行兼容性
背景
使用WinForms或者WPF里面自带的WebBrowser控件来加载网页时,该控件会默认使用IE7的标准模式加载网页,但是有些网页可能要求在特定的模式下运行才有较好的兼容性,但是微软提供了一个注册表方法,只需要将程序名称添加到对应注册表位置,那么它将不以兼容视图模式运行以便提高对访问网站的兼容性。
Webpages containing standards-based !DOCTYPE directives are displayed in IE7 Standards mode. Default value for applications hosting the WebBrowser Control
原理
浏览器仿真
Windows Internet Explorer 8及以后的版本FEATURE_BROWSER_EMULATION
特性定义了Internet Explorer的默认仿真模式,支持以下数值:
数值 | 描述 |
---|---|
11001 (0x2AF9) |
Internet Explorer 11, 网页在IE 11的Edge模式下显示,不管是否声明了!DOCTYPE 指令。如果没有声明!DOCTYPE 指令,会导致网页在Quirks 中加载。 |
11000 (0x2AF8) |
Internet Explorer 11, 包含基于标准的!DOCTYPE 指令的网页在IE 11 Edge模式下显示。Internet Explorer 11的默认值。 |
10001 (0x2711) |
Internet Explorer 10, 网页在IE 10的标准模式下显示,与!DOCTYPE 指令无关。 |
10000 (0x02710) |
Internet Explorer 10, 包含基于标准的!DOCTYPE 指令的网页在IE 10标准模式下显示。Internet Explorer 10的默认值。 |
9999 (0x270F) |
Internet Explorer 9, 网页在IE 9标准模式下显示,不管是否声明了!DOCTYPE 指令。如果没有声明!DOCTYPE 指令,就会导致页面以Quirks 模式加载。 |
9000 (0x2328) |
Internet Explorer 9, 包含基于标准的!DOCTYPE 指令的网页在IE 9模式下显示。Internet Explorer 9的默认值。在Internet Explorer 10中,包含基于标准的 !DOCTYPE 指令的网页会在IE 10标准模式下显示。 |
8888 (0x22B8) |
Internet Explorer 8, 网页在IE 8标准模式下显示,不管是否声明了!DOCTYPE 指令。如果没有声明!DOCTYPE 指令,就会导致页面以Quirks模式加载。 |
8000 (0x1F40) |
Internet Explorer 8, 包含基于标准的!DOCTYPE 指令的网页在IE 8模式下显示。Internet Explorer 8的默认值。在Internet Explorer 10中,包含基于标准的 !DOCTYPE 指令的网页会在IE10标准模式下显示。 |
7000 (0x1B58) |
Internet Explorer 7, 包含基于标准的!DOCTYPE 指令的网页在IE 7标准模式下显示。托管WebBrowser控件的应用程序的默认值。 |
要通过使用注册表来控制该功能的值,请将你的可执行文件的名称添加到以下设置中,并将其值设置为与所需设置相匹配。
HKEY_LOCAL_MACHINE (or HKEY_CURRENT_USER)
SOFTWARE
Microsoft
Internet Explorer
Main
FeatureControl
FEATURE_BROWSER_EMULATION
contoso.exe = (DWORD) 00009000
子窗口剪裁
Internet Explorer 9,Internet Explorer 9优化了窗口绘制程序的性能,这些程序涉及与子窗口相关的剪切区域。这有助于提高某些窗口绘制操作的性能。然而,某些承载WebBrowser控件的应用程序依赖于以前的行为,当这些优化被启用时,不能正常工作。FEATURE_ENABLE_CLIPCHILDREN_OPTIMIZATION
功能可以禁用这些优化。
默认情况下,该功能在Internet Explorer和承载WebBrowser控件的应用程序中被启用。要通过使用注册表禁用该功能,请将你的可执行文件的名称添加到以下设置中。
HKEY_LOCAL_MACHINE (or HKEY_CURRENT_USER)
SOFTWARE
Microsoft
Internet Explorer
Main
FeatureControl
FEATURE_ENABLE_CLIPCHILDREN_OPTIMIZATION
contoso.exe = (DWORD) 00000000
当值设置为00000001
(DWORD)时,该功能被启用,当值为00000000
(DWORD)时,该功能被禁用。
效果对比
我们可以利用演示程序中访问https://ie.icoa.cn来验证。
未添加注册表之前,显示的内核版本为Trident 7.0(IE 11.0的兼容视图)
添加注册表之后,显示的内核版本为Trident 7.0(IE 11.0)
,没有了兼容视图字眼。
实施策略
定义常量
/// <summary>
/// 浏览器仿真
/// </summary>
const string FEATURE_BROWSER_EMULATION = @"\FEATURE_BROWSER_EMULATION";
/// <summary>
/// 子窗口剪裁优化
/// </summary>
const string FEATURE_ENABLE_CLIPCHILDREN_OPTIMIZATION = @"\FEATURE_ENABLE_CLIPCHILDREN_OPTIMIZATION";
/// <summary>
/// Microsoft Internet Explorer 特性控制
/// </summary>
const string MicrosoftInternetExplorerMainFeatureControl = @"HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl";
/// <summary>
/// 获取组件文件名
/// </summary>
/// <param name="hModule"></param>
/// <param name="lpFilename"></param>
/// <param name="nSize"></param>
/// <returns></returns>
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
static extern int GetModuleFileName(IntPtr hModule, StringBuilder lpFilename, int nSize);
获取本地浏览器版本
/// <summary>
/// 获取本地浏览器版本
/// </summary>
/// <returns></returns>
private int GetLocalBrowserVersion()
{
var systemDir = Environment.GetFolderPath(Environment.SpecialFolder.System);
var localBrowserFilePath = Path.Combine(systemDir, "mshtml.dll");
if (!string.IsNullOrEmpty(localBrowserFilePath) && File.Exists(localBrowserFilePath))
{
try
{
var fileVersionInfo = FileVersionInfo.GetVersionInfo(localBrowserFilePath);
return fileVersionInfo.FileMajorPart;
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
}
return -1;
}
获取浏览器仿真数值
/// <summary>
/// 获取浏览器仿真数值
/// </summary>
/// <param name="localBrowserVersion"></param>
/// <returns></returns>
private uint GetBrowserEmulationValue(int localBrowserVersion)
{
uint emulationValue;
switch (localBrowserVersion)
{
// Internet Explorer 7, 包含基于标准的!DOCTYPE指令的网页在IE 7标准模式下显示。托管WebBrowser控件的应用程序的默认值。
case 7:
emulationValue = 7000;
break;
// Internet Explorer 8, 包含基于标准的!DOCTYPE指令的网页在IE 8模式下显示。Internet Explorer 8的默认值。
case 8:
emulationValue = 8000;
break;
// Internet Explorer 9, 包含基于标准的!DOCTYPE指令的网页在IE 9模式下显示。Internet Explorer 9的默认值。
case 9:
emulationValue = 9000;
break;
// Internet Explorer 10, 包含基于标准的!DOCTYPE指令的网页在IE 10标准模式下显示。Internet Explorer 10的默认值。
case 10:
emulationValue = 10000;
break;
// Internet Explorer 11, 包含基于标准的!DOCTYPE指令的网页在IE 11 Edge模式下显示。Internet Explorer 11的默认值。
case 11:
default:
emulationValue = 11000;
break;
}
return emulationValue;
}
获取应用运行程序名称
/// <summary>
/// 获取应用运行程序名称
/// </summary>
/// <returns></returns>
private string GetAppExecutableName()
{
var appExecutablePath = string.Empty;
var sb = new StringBuilder(1024);
var len = GetModuleFileName(IntPtr.Zero, sb, sb.Capacity);
if(len > 0)
{
appExecutablePath = sb.ToString(0, len);
}
var appExecutableName = Path.GetFileName(appExecutablePath);
return appExecutableName;
}
初始化本机浏览器仿真设置
/// <summary>
/// 初始化本机浏览器仿真设置
/// </summary>
private void InitLocalBrowserEmulation()
{
// 获取本地浏览器版本
var browserVersion = GetLocalBrowserVersion();
// 获取浏览器仿真数值
var emulationValue = GetBrowserEmulationValue(browserVersion);
// 获取应用运行程序名称
var appExecutableName = GetAppExecutableName();
// 判断执行合法性
if (browserVersion > 0 && !string.IsNullOrEmpty(appExecutableName))
{
// 注册表设置浏览器仿真值
var FEATURE_BROWSER_EMULATION_KEY = $"{MicrosoftInternetExplorerMainFeatureControl}{FEATURE_BROWSER_EMULATION}";
Registry.SetValue(FEATURE_BROWSER_EMULATION_KEY, appExecutableName, emulationValue, RegistryValueKind.DWord);
// 注册表启用子窗口剪裁优化
var FEATURE_ENABLE_CLIPCHILDREN_OPTIMIZATION_KEY = $"{MicrosoftInternetExplorerMainFeatureControl}{FEATURE_ENABLE_CLIPCHILDREN_OPTIMIZATION}";
Registry.SetValue(FEATURE_ENABLE_CLIPCHILDREN_OPTIMIZATION_KEY, appExecutableName, 1, RegistryValueKind.DWord);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2021-08-23 温故知新,.Net Core遇见WinForms(Windows Form)客户端窗体框架,在DotNet Core大一统基础上老树发芽
2021-08-23 乘风破浪,遇见最美Windows 11之新微软商店(Microsoft Store)生态 - 官方应用集锦