I initially used the TWebBrowser component to display help sections in my applications. This approach is quite straightforward—we store standard HTML files in a folder and call them as needed, like WebBrowser.Navigate(HelpDir + ‘index.html’);
The HTML file can include everything you need: images, cross-references, and scripts compatible with Internet Explorer.
Things became much more interesting when I wanted to display database information through it and programmatically modify the displayed content. It turns out this is entirely possible.
Adding CSS styling: CSS insertion follows standard web conventions. For example, you can add styling before the body tag:
<style type="text/css">
table {
border-collapse: collapse;
border-color: #E0E0E0;
font-size: x-small;
}
td {
border: 1px solid;
padding: 2px;
}
</style>
Displaying custom HTML content: To pass any HTML string to TWebBrowser, you can do the following:
var
Doc: Variant;
begin
if NOT Assigned(wBrowser.Document) then
wBrowser.Navigate('about:blank');
Doc := wBrowser.Document;
Doc.Clear;
Doc.Write('Hello <b>World</b>');
Doc.Close;
end;
Scrolling to the bottom after page load: You can automatically scroll to the end of the page by adding JavaScript just before the closing body tag:
<script>window.scrollTo(0,document.body.scrollHeight);</script>
Executing JavaScript code from Delphi: You can execute arbitrary JavaScript using this approach:
var
Doc: Variant;
begin
if NOT Assigned(wBrowser.Document) then
wBrowser.Navigate('about:blank');
Doc := wBrowser.Document;
Doc.parentWindow.execScript('alert("Hello World");', 'JavaScript');
end;
Reading element attributes: You can extract attribute values from HTML elements like this:
function GetElementIdValue(WebBrowser: TWebBrowser; TagName, TagId, TagAttrib: string): string;
var
Document: IHTMLDocument2;
Body: IHTMLElement2;
Tags: IHTMLElementCollection;
Tag: IHTMLElement;
I: Integer;
begin
Result := '';
if not Supports(WebBrowser.Document, IHTMLDocument2, Document) then
raise Exception.Create('Invalid HTML document');
if not Supports(Document.body, IHTMLElement2, Body) then
raise Exception.Create('Cannot find element');
Tags := Body.getElementsByTagName(UpperCase(TagName));
for I := 0 to Pred(Tags.length) do begin
Tag := Tags.item(I, EmptyParam) as IHTMLElement;
if Tag.id = TagId then
Result := Tag.getAttribute(TagAttrib, 0);
end;
end;
// Usage example:
Result := GetElementIdValue(WebBrowser1, 'input', 'result', 'value');
Communicating from JavaScript to Delphi: The most interesting part—how to send data or trigger events from JavaScript code back to your Delphi application. You can accomplish this by intercepting link navigation through the OnBeforeNavigate2 event handler. Parse the URL to extract the required information, and use Cancel := true; to prevent actual navigation if needed. It’s best to use a special prefix in the URL to distinguish these calls from regular navigation. Here’s an example handler:
procedure TMyForm.WebBrowserBeforeNavigate2(Sender: TObject; const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData, Headers: OleVariant; var Cancel: WordBool);
var
prefix: string;
colonPos: Integer;
begin
colonPos := Pos(':', URL);
if colonPos > 0 then begin
prefix := Copy(URL, 1, colonPos - 1);
if prefix = 'event' then begin
ShowMessage(Copy(URL, colonPos + 1, Length(URL) - colonPos));
Cancel := TRUE;
end;
end;
end;
The HTML code triggering this event handler might look like:
<input id="testButton" type="button" value="test" />
Note: One limitation of this approach appears when running on Terminal Server environments with strict security policies. Users may encounter an Internet Explorer warning dialog during window initialization, though it’s often possible to add the application to security exceptions.
