我对Delphi和WebBrowser组件感到疯狂。
我创建了一个简单的应用程序,在Memo中键入HTML并在WebBrowser组件中显示结果。
但是,当我在WebBrowser中单击时,每个HTML代码更新(在备忘录中)都会导致WebBrowser组件窃取焦点。
以下是重现问题的逐步步骤:
在Memo1.OnChange上插入事件:
if WebBrowser1.Document = nil then
begin
WebBrowser1.Navigate('about:blank');
while WebBrowser1.ReadyState <> READYSTATE_COMPLETE do
Application.ProcessMessages;
end;
ms := TMemoryStream.Create;
try
Memo1.Lines.SaveToStream(ms);
ms.Seek(0, 0);
(WebBrowser1.Document as IPersistStreamInit).Load(TStreamAdapter.Create(ms)) ;
finally
ms.Free;
end;
运行应用程序
在备忘录中输入HTML
<html>
<body>
Hello WebBrowser
</body>
</html>
点击WebBrowser内容
我如何解决这个问题,并防止焦点的掠夺&#34;吗
Ps。唯一的解决方法是在WebBrowser上单击后按TAB键,这可以防止webbrowser在通过备忘录对html代码进行新的更改后窃取焦点。
解决了此解决方法。
将Memo1.OnChange代码更改为:
procedure TForm1.Memo1Change(Sender: TObject);
var
ms: TMemoryStream;
begin
LockWindowUpdate(panel1.Handle); // fix: lock webbrowser parent updates
// fix: re-set the webbrowser parent to prevent focus stealing
TControl(WebBrowser1).Parent := nil;
TControl(WebBrowser1).Parent := panel1;
// fix:eof
if WebBrowser1.Document = nil then
begin
WebBrowser1.Navigate('about:blank');
while WebBrowser1.ReadyState <> READYSTATE_COMPLETE do
Application.ProcessMessages;
end;
ms := TMemoryStream.Create;
try
Memo1.Lines.SaveToStream(ms);
ms.Seek(0, 0);
(WebBrowser1.Document as IPersistStreamInit).Load(TStreamAdapter.Create(ms)) ;
finally
ms.Free;
end;
LockWindowUpdate(0); // fix: unlock webbrowser parent updates to prevent flicking!!
end;
答案 0 :(得分:1)
在表单中添加一个复选框和另一个备忘录Memo2,并将其OnChange指向 你的Memo1的处理程序。然后,更改您的处理程序,如下所示。你应该找到 即使在使用Memo1引发焦点窃取之后,当你输入时它也不会发生 Memo2(当然选中了复选框)。
我意识到我用Memo2做的事与你的完全不同,但是 可能优选的是,备忘录不需要包含外部结构 HTML文档。根据您正在做的事情,这可能是一个优势 或者是一个劣势。
Fwiw,在点击WB后调用ShowCaret(Memo1.Handle)返回false - GetLastError / SysErrorMsg报告5 /拒绝访问,所以我猜测在WB中点击某些垃圾邮件Memo1&#39; s caret - 我的意思不仅仅是你期望转移焦点。我仍在调查。
procedure TForm1.Memo1Change(Sender: TObject);
var
ms : TMemoryStream;
begin
if WebBrowser1.Document = nil then
begin
WebBrowser1.Navigate('about:blank');
while WebBrowser1.ReadyState <> READYSTATE_COMPLETE do
Application.ProcessMessages;
end;
try
if CheckBox1.Checked then begin
(WebBrowser1.Document as IHtmlDocument2).Body.innerHtml := Memo2.Lines.Text;
end
else begin
ms := TMemoryStream.Create;
try
Memo1.Lines.SaveToStream(ms);
ms.Seek(0, 0);
(WebBrowser1.Document as IPersistStreamInit).Load(TStreamAdapter.Create(ms)) ;
finally
ms.Free;
end;
end;
except
// silence any exceptions raised when using CheckBox1.Checked = True
end;
end;
更新
如果您比我上面的建议更喜欢与您的原件更接近的东西,请执行以下操作 更紧凑,似乎运行得更快:
procedure TForm1.HandleMemo1ChangeNew(Sender : TObject);
var
Doc : IHtmlDocument2;
V : OleVariant;
begin
if WebBrowser1.Document = nil then
WebBrowser1.Navigate('about:blank');
Doc := WebBrowser1.Document as IHTMLDocument2;
V := VarArrayCreate([0, 0], varVariant);
V[0] := Memo1.Lines.Text;
Doc.Write(PSafeArray(TVarData(v).VArray));
Doc.Close;
end;
procedure TForm1.WebBrowser1NavigateComplete2(Sender: TObject;
const pDisp: IDispatch; var URL: OleVariant);
begin
WebBrowser1.Enabled := False;
end;