Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimize painting of TWebBrowser to reduce total CPU usage

I have a form that has a TWebBrower component that loads an HTML document. The data on the HTML document is updated every few seconds, sometimes multiple times every second and I update the value in Delphi using:

DOMDocument.getElementById(elementID).innerHTML := someValue;

The problem is I want to lock the window/webbrowser to prevent it from painting/updating until all my updates are complete. Is there any way to do this? Would a call to

SendMessage(WebBrowser.Handle,WM_SETREDRAW,0,0);

I would like some help in optimizing this code so that my total CPU usage isn't continuously high.

like image 390
Wilbert Chua Avatar asked Apr 18 '12 09:04

Wilbert Chua


2 Answers

Since your main problem is update frequency, then you need to decrease it. For this you can simply store the last time you've updated the HTML document and at next data change check if a certain period elapsed since that time.

Here is the code that shows how to do this. The FUpdatePeriod in the following example is the update period in milliseconds. Then if you call the UpdateChanges periodically, the innerHTML (pseudo-code here) will be updated only when at least 1000 ms elapsed since its last change.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, MSHTML, OleCtrls, SHDocVw;

type
  TForm1 = class(TForm)
    WebBrowser1: TWebBrowser;
    procedure FormCreate(Sender: TObject);
  private
    FLastUpdate: Cardinal;
    FUpdatePeriod: Cardinal;
    procedure UpdateChanges(const AData: WideString);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  FUpdatePeriod := 1000;
end;

procedure TForm1.UpdateChanges(const AData: WideString);
begin
  if (GetTickCount - FLastUpdate > FUpdatePeriod) then
  begin
    (WebBrowser1.Document as IHTMLDocument2).body.innerHTML := AData;
    FLastUpdate := GetTickCount;
  end;
end;

// now remains to call the UpdateChanges periodically

end.
like image 132
TLama Avatar answered Oct 20 '22 05:10

TLama


This is a sideways answer; But when we had flicker issues with TWebBrowser we fixed them by switching to using Google Chrome (DCEF) embedded into our application.

While I too originally felt that I could "optimize" TWebBrowser, and reduce it's flicker, I found out that the problem is just native to Internet Explorer. Aside from installing a new version of Internet Explorer, or rewriting all your JavaScript so your web page never flickers, because it has no active elements in the HTML layout (100% javascript free = no flicker) the only fix is to stop using Internet Explorer, and thus stop using TWebbrowser.

Secondly, flicker can also be caused if your TWebBrowser web page is accessing Delphi native methods as callbacks from the javascript. These callbacks, if they take a lot of time, will also always cause flicker in the embedded TWebBrowser, even if the only javascript that is being executed is the invocation of the delphi callback. The technique I am talking about (callbacks) is documented here.

like image 24
Warren P Avatar answered Oct 20 '22 04:10

Warren P