I'm going crazy with Delphi and WebBrowser component.
I created a simple application, to type HTML in a Memo and display the result inside the WebBrowser component.
But, when I click inside the WebBrowser, each HTML code update (in memo) results in the steal of the focus by the WebBrowser component.
Here is the step-by-step to reproduce the problem:
insert on Memo1.OnChange event this:
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;
run the application
type the HTML inside the Memo
<html>
<body>
Hello WebBrowser
</body>
</html>
click inside the WebBrowser content
How can I solve this and prevent the "steal of the focus" ?
Ps.: the only workaround is pressing the TAB key after clicking on WebBrowser, this prevent the webbrowser the steal the focus after new changes in html code via memo.
Solved with this workaround.
Change the Memo1.OnChange code to this:
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;
Add a checkbox and another memo, Memo2, to your form, and point its OnChange at your handler for Memo1. Then, change your handler as shown below. You should find that even after provoking the focus-stealing using Memo1, it doesn't happen when you type into Memo2 (with the checkbox checked, of course).
I realise that what I'm doing with Memo2 isn't quite the same as what you are, but it may be preferable in that the memo isn't required to contain the outer structure of the HTML document. Depending on what you're doing, that may be an advantage or a disadvantage.
Fwiw, calling ShowCaret(Memo1.Handle) after clicking in the WB returns false - GetLastError/SysErrorMsg report 5/Access Denied, so I'm guessing that clicking in the WB somehow clobbers Memo1's caret - I mean more than you'd expect just from shifting focus. I am still looking into that.
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;
Update:
If you'd prefer something closer to your original than my suggestion above, the following is more compact and seems to run a bit faster:
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With