问题描述
在 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;
不幸的是,SVG 未显示在 TWebbrowser
中!我究竟做错了什么?我什至尝试过 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;
您需要在 uses 语句中添加单元 mshtml。
可以下载示例项目 (Delphi 10.3.3) here