启用 TWebBrowser 高 DPI 支持
Enabling TWebBrowser High DPI support
我正在使用支持高 DPI 的 RAD Studio Rio。
但它似乎在 TWebBrowser
上不起作用,至少在默认情况下不像在其他 VCL 组件上那样起作用。
因此,当我将应用程序从低 DPI 显示器拖到高 DPI 显示器时,用户界面和所有组件都会调整大小(包括网络浏览器容器),但网络浏览器内的内容不会保持不变。
我确信它可以启用,因为在显示器之间移动 Internet Explorer 确实会自动更改内容大小。
所以问题是如何也为 TWebBrowser
启用它?
我注意到当拖动 IE window 时,“缩放”设置会自动更改(从 100% 到 200% - 200% 是高 DPI 显示器的 DPI 缩放值),因此可以通过使用缩放,或以其他方式。但是还有一个滚动条大小的问题。
我还注意到 DOCHOSTUIFLAG_DPI_AWARE
标志的存在,它可能有用,但我还不知道如何使用它。
编辑:我创建了一个 IDocHostUIHandler
后代 class,其中包含 GetHostInfo
函数,我可以在其中控制标志,其中添加 DOCHOSTUIFLAG_DPI_AWARE
自动将 TWebBrowser 缩放到系统 DPI(如果系统 DPI 设置为 150%,Web 浏览器也会自动缩放到 150%)。不需要为此使用 FEATURE_BROWSER_EMULATION
注册表项。
TWebBrowser 包装了 InternetExplorer,因此控件的呈现不是由任何 VCL 代码完成的,而是由嵌入式 Internet Explorer 代码完成的。我们已经在各种项目中使用了它,设置兼容模式是获得所需显示的关键。
由于 IE 可以 正确缩放,您需要确保您在正确的模式下运行。 @Ondrej Kelle 的评论是 a useful article,应该向您展示如何执行此操作,因此我不会在这里重复。
我找到了两种方法:
解决方案 1
通过注册表项和值为您的应用程序启用 IE FEATURE_96DPI_PIXEL
:
uses
System.SysUtils,
System.Win.Registry,
Vcl.Forms,
Winapi.Windows;
procedure EnableDpiAwareness;
var
Reg: TRegistry;
App: string;
begin
Reg := TRegistry.Create;
try
App := ExtractFileName(Application.ExeName);
Reg.RootKey := HKEY_CURRENT_USER;
if Reg.OpenKey('Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_96DPI_PIXEL', True) then
begin
Reg.WriteInteger(App, 1);
Reg.CloseKey;
end;
finally;
Reg.Free;
end;
end;
解决方案 2
实现 TWebBrowser
的后代 class,重新实现 IDocHostUIHandler
接口(如 OP 编辑中所述):
unit DpiAwareWebBrowser;
interface
uses
Winapi.Mshtmhst,
SHDocVw;
type
TDpiAwareWebBrowser = class(TWebBrowser, IDocHostUIHandler)
strict private
// IDocHostUIHandler "override"
function GetHostInfo(var pInfo: TDocHostUIInfo): HRESULT; stdcall;
end;
implementation
const
DOCHOSTUIFLAG_DPI_AWARE = 000000;
function TDpiAwareWebBrowser.GetHostInfo(var pInfo: TDocHostUIInfo): HRESULT;
begin
// original code from TWebBrowser.GetHostInfo
pInfo.cbSize := SizeOf(pInfo);
pInfo.dwFlags := 0;
pInfo.dwFlags := pInfo.dwFlags or DOCHOSTUIFLAG_NO3DBORDER;
pInfo.dwFlags := pInfo.dwFlags or DOCHOSTUIFLAG_THEME;
pInfo.dwFlags := pInfo.dwFlags or DOCHOSTUIFLAG_DPI_AWARE; // NEW added flag
Result := S_OK;
// ResizeScrollBars; // will be called by subsequent routines anyway.
end;
end.
两种方式做同样的事情。
DOCHOSTUIFLAG_DPI_AWARE
Internet Explorer 8. Causes layout engine to calculate document pixels as 96 dpi. Normally, a document pixel is the same size as a screen pixel. This flag is equivalent to setting the FEATURE_96DPI_PIXEL
feature control key on a per-host basis.
我正在使用支持高 DPI 的 RAD Studio Rio。
但它似乎在 TWebBrowser
上不起作用,至少在默认情况下不像在其他 VCL 组件上那样起作用。
因此,当我将应用程序从低 DPI 显示器拖到高 DPI 显示器时,用户界面和所有组件都会调整大小(包括网络浏览器容器),但网络浏览器内的内容不会保持不变。
我确信它可以启用,因为在显示器之间移动 Internet Explorer 确实会自动更改内容大小。
所以问题是如何也为 TWebBrowser
启用它?
我注意到当拖动 IE window 时,“缩放”设置会自动更改(从 100% 到 200% - 200% 是高 DPI 显示器的 DPI 缩放值),因此可以通过使用缩放,或以其他方式。但是还有一个滚动条大小的问题。
我还注意到 DOCHOSTUIFLAG_DPI_AWARE
标志的存在,它可能有用,但我还不知道如何使用它。
编辑:我创建了一个 IDocHostUIHandler
后代 class,其中包含 GetHostInfo
函数,我可以在其中控制标志,其中添加 DOCHOSTUIFLAG_DPI_AWARE
自动将 TWebBrowser 缩放到系统 DPI(如果系统 DPI 设置为 150%,Web 浏览器也会自动缩放到 150%)。不需要为此使用 FEATURE_BROWSER_EMULATION
注册表项。
TWebBrowser 包装了 InternetExplorer,因此控件的呈现不是由任何 VCL 代码完成的,而是由嵌入式 Internet Explorer 代码完成的。我们已经在各种项目中使用了它,设置兼容模式是获得所需显示的关键。
由于 IE 可以 正确缩放,您需要确保您在正确的模式下运行。 @Ondrej Kelle 的评论是 a useful article,应该向您展示如何执行此操作,因此我不会在这里重复。
我找到了两种方法:
解决方案 1
通过注册表项和值为您的应用程序启用 IE FEATURE_96DPI_PIXEL
:
uses
System.SysUtils,
System.Win.Registry,
Vcl.Forms,
Winapi.Windows;
procedure EnableDpiAwareness;
var
Reg: TRegistry;
App: string;
begin
Reg := TRegistry.Create;
try
App := ExtractFileName(Application.ExeName);
Reg.RootKey := HKEY_CURRENT_USER;
if Reg.OpenKey('Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_96DPI_PIXEL', True) then
begin
Reg.WriteInteger(App, 1);
Reg.CloseKey;
end;
finally;
Reg.Free;
end;
end;
解决方案 2
实现 TWebBrowser
的后代 class,重新实现 IDocHostUIHandler
接口(如 OP 编辑中所述):
unit DpiAwareWebBrowser;
interface
uses
Winapi.Mshtmhst,
SHDocVw;
type
TDpiAwareWebBrowser = class(TWebBrowser, IDocHostUIHandler)
strict private
// IDocHostUIHandler "override"
function GetHostInfo(var pInfo: TDocHostUIInfo): HRESULT; stdcall;
end;
implementation
const
DOCHOSTUIFLAG_DPI_AWARE = 000000;
function TDpiAwareWebBrowser.GetHostInfo(var pInfo: TDocHostUIInfo): HRESULT;
begin
// original code from TWebBrowser.GetHostInfo
pInfo.cbSize := SizeOf(pInfo);
pInfo.dwFlags := 0;
pInfo.dwFlags := pInfo.dwFlags or DOCHOSTUIFLAG_NO3DBORDER;
pInfo.dwFlags := pInfo.dwFlags or DOCHOSTUIFLAG_THEME;
pInfo.dwFlags := pInfo.dwFlags or DOCHOSTUIFLAG_DPI_AWARE; // NEW added flag
Result := S_OK;
// ResizeScrollBars; // will be called by subsequent routines anyway.
end;
end.
两种方式做同样的事情。
DOCHOSTUIFLAG_DPI_AWARE
Internet Explorer 8. Causes layout engine to calculate document pixels as 96 dpi. Normally, a document pixel is the same size as a screen pixel. This flag is equivalent to setting theFEATURE_96DPI_PIXEL
feature control key on a per-host basis.