如何在 运行 时间手动将 SVG 文档文本插入到 TWebBrowser 中?
How to insert an SVG document text manually into a TWebBrowser at run-time?
在 Delphi 10.4.2 Win32 VCL 应用程序中,我需要在 运行 时手动将 SVG 文档插入到 TWebBrowser
(wb1.SelectedEngine := IEOnly;
) 中:
procedure TForm1.btnLoadSVGDocClick(Sender: TObject);
var
Doc: Variant;
slSVG: TStringList;
begin
slSVG := TStringList.Create;
try
slSVG.LoadFromFile('C:\DELPHI\_test\BrowserSVGViewer\steamreactor.svg');
// Todo: Make corrections to the SVG document text
if NOT Assigned(wb1.Document) then
wb1.Navigate('about:blank');
Doc := wb1.Document;
Doc.Clear;
Doc.Write(slSVG.Text);
Doc.Close;
//wb1.Refresh;
finally
slSVG.Free;
end;
end;
很遗憾,TWebBrowser
中未显示 SVG!我究竟做错了什么?我什至试过 wb1.Refresh;
,但没有用。
Internet Explorer 控件的设计不适合动态提供内容。因此,我的标准做法是将我的内容保存到一个临时文件中:
type
TForm1 = class(TForm)
WebBrowser1: TWebBrowser;
btnLoadSvg: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure btnLoadSvgClick(Sender: TObject);
private
FTempFiles: TList<TFileName>;
public
end;
implementation
uses
IOUtils;
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
FTempFiles := TList<TFileName>.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if Assigned(FTempFiles) then
for var TempFile in FTempFiles do
Winapi.Windows.DeleteFile(PChar(TempFile));
end;
procedure TForm1.btnLoadSvgClick(Sender: TObject);
begin
var SvgText := TFile.ReadAllText('K:\flower.svg', TEncoding.UTF8);
var TempFileName := ChangeFileExt(TPath.GetTempFileName, '.svg');
FTempFiles.Add(TempFileName);
TFile.WriteAllText(TempFileName, SvgText, TEncoding.UTF8);
WebBrowser1.Navigate(TempFileName);
end;
这很稳健。例如,即使用户在控件具有焦点时按 F5,文档仍会存在。
您可以将空框架加载到 WebBrowser1
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>SVG Frame</title>
</head>
<body>
<svg>
</svg>
</body>
</html>
并通过设置 svg 标签的 outerHTML 添加 SVG 代码,如下所示:
var
Elem: IHTMLElement;
..
Elem := GetElementByTag(WebBrowser1.Document, 'svg');
Elem.outerHTML := slSVG.Text;
函数 GetElementByTag 应定义如下:
function GetElementByTag(const Doc: IDispatch; const TagName: string): IHTMLElement;
var
Document: IHTMLDocument2; // IHTMLDocument2 interface of Doc
Body: IHTMLElement2; // document body element
Tags: IHTMLElementCollection; // all tags in document body
Tag: IHTMLElement; // a tag in document body
I: Integer; // loops thru tags in document body
begin
Result := nil;
// Check for valid document: require IHTMLDocument2 interface to it
if not Supports(Doc, IHTMLDocument2, Document) then
raise Exception.Create('Invalid HTML document');
// Check for valid body element: require IHTMLElement2 interface to it
if not Supports(Document.body, IHTMLElement2, Body) then
raise Exception.Create('Can''t find <body> element');
// Get all tags in body element ('*' => any tag name)
if Tags.length > 0 then
Result := Tags.item(0, EmptyParam) as IHTMLElement
else
raise Exception.Create('no <svg> element found!');
end;
您需要将单元 mshtml 添加到 uses 语句。
可以下载示例项目(Delphi 10.3.3)here
在 Delphi 10.4.2 Win32 VCL 应用程序中,我需要在 运行 时手动将 SVG 文档插入到 TWebBrowser
(wb1.SelectedEngine := IEOnly;
) 中:
procedure TForm1.btnLoadSVGDocClick(Sender: TObject);
var
Doc: Variant;
slSVG: TStringList;
begin
slSVG := TStringList.Create;
try
slSVG.LoadFromFile('C:\DELPHI\_test\BrowserSVGViewer\steamreactor.svg');
// Todo: Make corrections to the SVG document text
if NOT Assigned(wb1.Document) then
wb1.Navigate('about:blank');
Doc := wb1.Document;
Doc.Clear;
Doc.Write(slSVG.Text);
Doc.Close;
//wb1.Refresh;
finally
slSVG.Free;
end;
end;
很遗憾,TWebBrowser
中未显示 SVG!我究竟做错了什么?我什至试过 wb1.Refresh;
,但没有用。
Internet Explorer 控件的设计不适合动态提供内容。因此,我的标准做法是将我的内容保存到一个临时文件中:
type
TForm1 = class(TForm)
WebBrowser1: TWebBrowser;
btnLoadSvg: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure btnLoadSvgClick(Sender: TObject);
private
FTempFiles: TList<TFileName>;
public
end;
implementation
uses
IOUtils;
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
FTempFiles := TList<TFileName>.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if Assigned(FTempFiles) then
for var TempFile in FTempFiles do
Winapi.Windows.DeleteFile(PChar(TempFile));
end;
procedure TForm1.btnLoadSvgClick(Sender: TObject);
begin
var SvgText := TFile.ReadAllText('K:\flower.svg', TEncoding.UTF8);
var TempFileName := ChangeFileExt(TPath.GetTempFileName, '.svg');
FTempFiles.Add(TempFileName);
TFile.WriteAllText(TempFileName, SvgText, TEncoding.UTF8);
WebBrowser1.Navigate(TempFileName);
end;
这很稳健。例如,即使用户在控件具有焦点时按 F5,文档仍会存在。
您可以将空框架加载到 WebBrowser1
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>SVG Frame</title>
</head>
<body>
<svg>
</svg>
</body>
</html>
并通过设置 svg 标签的 outerHTML 添加 SVG 代码,如下所示:
var
Elem: IHTMLElement;
..
Elem := GetElementByTag(WebBrowser1.Document, 'svg');
Elem.outerHTML := slSVG.Text;
函数 GetElementByTag 应定义如下:
function GetElementByTag(const Doc: IDispatch; const TagName: string): IHTMLElement;
var
Document: IHTMLDocument2; // IHTMLDocument2 interface of Doc
Body: IHTMLElement2; // document body element
Tags: IHTMLElementCollection; // all tags in document body
Tag: IHTMLElement; // a tag in document body
I: Integer; // loops thru tags in document body
begin
Result := nil;
// Check for valid document: require IHTMLDocument2 interface to it
if not Supports(Doc, IHTMLDocument2, Document) then
raise Exception.Create('Invalid HTML document');
// Check for valid body element: require IHTMLElement2 interface to it
if not Supports(Document.body, IHTMLElement2, Body) then
raise Exception.Create('Can''t find <body> element');
// Get all tags in body element ('*' => any tag name)
if Tags.length > 0 then
Result := Tags.item(0, EmptyParam) as IHTMLElement
else
raise Exception.Create('no <svg> element found!');
end;
您需要将单元 mshtml 添加到 uses 语句。
可以下载示例项目(Delphi 10.3.3)here