Mar*_*ynA 4 html javascript delphi twebbrowser
本周末由几个SO q提示,我决定看看我是否可以解决如何将Html元素中的一些javascript添加到TWebBrowser中加载的文档中.这样做,我遇到了一个奇怪的问题,也许有人可以解释.
这是我的Html文档
<html>
<body>
Something
<br>
<div id="forscript">some more text</div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
和我要添加的javascript元素
<script type="text/javascript" defer="false">{alert('hello');}</script>
Run Code Online (Sandbox Code Playgroud)
我作为Script参数传递给下面的AddScript().
这是我的代码(doc2是从WebBrowser获得的IHtmlDocument2):
procedure TForm1.AddScript(const Script : String);
var
Element : IHtmlElement;
Doc3 : IHtmlDocument3;
begin
Doc2.QueryInterface(IHtmlDocument3, Doc3);
Element := Doc3.GetElementByID('forscript');
Element.innerHTML := Element.innerHTML + Script;
end;
Run Code Online (Sandbox Code Playgroud)
这很好,但......
分配RHS上的Element.innerHTML的原因很简单,我发现如果RHS 只包含脚本js,则js不会执行.我的问题是,为什么不,并且有一个更简单的替代方案,就像在某种程度上在代码中创建一个IHtmlScriptElement并将其插入DOM?显然,我简单易懂的解决方法只是在元素已经包含的文本前面添加,但我有点难以相信实际知道他们正在做什么的人会发现必要的.
FWIW#1:我尝试使用Element.insertAdjacentHtml来添加脚本但是得到了与我刚刚描述的相同的行为,就需要在脚本之外插入一些东西来获取脚本来执行时,所以我是想知道是否与在对其进行更改后如何处理DOM有关.
FWIW#2:我使用了Element.innerHtml路由,因为TWebBrowser/MSHTML.Pas拒绝了我在代码中创建IHtmlScriptElement的尝试; AFAICS,试图在MSHTML.Pas中使用任何CohtmlXXXElement例程引发"类未注册"例外,这似乎证实了我在这个教区的@kobik某处发现的评论.
(顺便说一句,在Win7 64位上使用D7 + IE11)
这是一个如何使用的完整示例IHtmlScriptElement.在应用程序启动时加载Html.下面的代码Button1Click将javascript添加到DOM并执行它:
unit u_frm_SO27091639;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, OleCtrls, SHDocVw, MsHtml, ActiveX;
type
TForm1 = class(TForm)
WebBrowser1: TWebBrowser;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure LoadDocFromString(Webbrowser : TWebbrowser);
var
Strm : TStringStream;
Adapter : TStreamAdapter;
begin
WebBrowser.Navigate('about:blank');
// warning - don't use this trick in production code, use the `OnDocumentComplete` event
while WebBrowser.ReadyState <> READYSTATE_INTERACTIVE do
Application.ProcessMessages;
// end of warning
Strm := TStringStream.Create;
try
Strm.WriteString('<html><body>Something<br></body></html>');
Strm.Seek(0, 0);
Adapter := TStreamAdapter.Create(Strm);
(WebBrowser.Document as IPersistStreamInit).Load(Adapter) ;
finally
Strm.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Doc2 : IHtmlDocument2;
Script : IHtmlDOMNode;
HTMLWindow: IHTMLWindow2;
begin
Doc2 := Webbrowser1.Document as IHtmlDocument2;
if Assigned(Doc2.body) then
begin
Script := Doc2.createElement('script') as IHTMLDOMNode;
(Script as IHTMLScriptElement).text := 'function helloWorld() { alert("hello world!") }';
(Doc2.body as IHtmlDomNode).appendChild(Script);
HTMLWindow := Doc2.parentWindow;
if Assigned(HTMLWindow) then
HTMLWindow.execScript('helloWorld()', 'JavaScript')
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
LoadDocFromString(Webbrowser1);
end;
end.
Run Code Online (Sandbox Code Playgroud)