I am using RAD Studio Rio which has support for High DPI.
But it doesn't seem to work on TWebBrowser
, at least not by default like it does on other VCL components.
So when I drag the app from Low-DPI to High-DPI monitor, the user interface and all components resize (including the web browser container), but not the content inside web browser which stays the same.
I am sure it can be enabled, because moving Internet Explorer between monitors does change the content size automatically.
So the question is how to enable it for TWebBrowser
too?
I noticed that when dragging IE window the "Zoom" setting changes automatically (from 100% to 200% - 200% is the DPI scaling value of the High DPI monitor) so it may be done through the use of zoom, or somehow else. But there is also a question of scroll-bar sizes too.
I also noted the existance of DOCHOSTUIFLAG_DPI_AWARE
flag which might be useful but I don't know how to utilize it yet.
EDIT: I've created a IDocHostUIHandler
descendant class which contains GetHostInfo
function where I can control the flags, among others add DOCHOSTUIFLAG_DPI_AWARE
which automatically zooms TWebBrowser to the system DPI (if system DPI is set to 150%, web browser will automatically also zoom to 150%). There is no need to use FEATURE_BROWSER_EMULATION
registry key for this.
I have found two ways how to do this:
Solution 1
Enable IE's FEATURE_96DPI_PIXEL
for your application via Registry key and value:
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;
Solution 2
Implement a descendant class of TWebBrowser
that reimplements the IDocHostUIHandler
interface (like mentioned in the edit of 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 = $40000000;
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.
Both ways do the same thing.
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.