«« Site Rescued »»

While the site is still going to move from its current host, a new site will now take its place. More Info.

The new site may have less content, but the core will now remain. And it will now play nicely with phones! Keep an eye on the DelphiDabbler Blog for news.

How to customise the TWebBrowser user interface (part 5 of 6)

A sample application

Exercising the code – a sample application

One of the problems that motivated this exploration was my need to use a TWebBrowser to display some HTML in a dialog box. The HTML needed to look and behave as if it was part of the dialog box, which could be using themes. The dialog box would also need to display a custom pop-up menu.

This sample application will emulate such a dialog box. It will use our custom TWBContainer to take control over the appearance of a TWebBrowser control. This will not be production code – for example we load the HTML from a file and we wouldn't do that in released code – but it should suffice to demonstrate that the customization class works.

The application will be developed in two stages. Stage one will be the bare application with no TWebBrowser customization code. We will run the program to check what it looks like in its natural state before we intervene. In stage two we'll apply the classes we've developed here and see the difference.

Stage 1

Open a new Delphi project and select the main form, then:

  • Give the form a BorderStyle of bsDialog.
  • Place a TButton centred at the bottom of the form, set its Caption to 'Close' and create an OnClick event handler for it containing just the code shown in Listing 18:
    procedure TForm1.Button1Click(Sender: TObject);
      Close;  // close the application
  • Add a TPopupMenu and give it a single menu item with Caption set to 'Show the CSS'.
  • Drop a TWebBrowser control, set its Align property to alTop and size it to take up most of the form. Leave room for the 'Close' button below it. Set its PopupMenu property to PopupMenu1.
  • Add the XPMan unit (Delphi 7 and later) to the form's uses clause to ensure the application displays themes if available. Note: This may not be necessary with later Delphis that can enable themes by default in the project resource file.

Now, double-click the form to open a new OnCreate event handler and enter the code shown in Listing 19. This loads the HTML file into the browser:

procedure TForm1.FormCreate(Sender: TObject);
  // load content
    ExtractFilePath(ParamStr(0)) + 'DlgContent.html'

Finally create the HTML file, DlgContent.html, that is loaded in FormCreate above. This file will provide the content of our dialog box. Listing 20 shows the HTML.

    <title>Demo Dialog Content</title>
    <script type="text/javascript">
      function ViewArticle() {
      	wdw = window.open();
        wdw.document.location =
      About this demo
      This demo relates to the DelphiDabbler.com article &quot;How to
      customise the TWebBrowser user interface&quot;.
        value="View article..."
      &copy; Copyright P D Johnson
      (<a href="http://www.delphidabbler.com/"
      target="_blank">delphidabbler.com</a>), 2004-2006.
    <p class="ruled">
      Right click above the line to see the custom pop-up menu.

This code defines a document which has:

  • Some plain text including a paragraph styled using a CSS class named .ruled that is not defined in the document.
  • A button that, when clicked, runs some JavaScript that opens a new window and displays this article in it.
  • Some clickable text that opens a new browser window and navigates to the DelphiDabbler.com home page.

If you compile and run this application then right click in the browser control you should see something like this:

Picture of demo program

Doesn't look much like a dialog box does it? There are numerous problems:

  1. The browser control is displaying its default border and scroll bar.
  2. The HTML is being displayed in the default style.
  3. The form's 'Close' button is themed while the 'View article' button displayed by the browser control is not.
  4. Despite setting the PopupMenu property, the standard browser's context menu is still displayed.
  5. Although it can't be seen here, you could select the text in the HTML document.

Let us now adapt the program to correct all these problems.

Stage 2

We will now utilize the classes we have developed in this article. To begin with add the units containing IDocHOstUIHandler, TNulWBContainer and TWBContainer to the project and refer to them in the main form's uses clause. Also add the ActiveX and SysUtils units to the uses clause.

It's now time to set up and use the container object. Switch to the form unit we developed in Stage 1 and add a field named fWBContainer of type TWBContainer to the form's class declaration. Now rewrite the form's OnCreate event handler as shown in Listing 21.

procedure TForm1.FormCreate(Sender: TObject);
  // Template for default CSS style
  cCSSTplt = 'body {'#13#10
    + '    background-color: %0:s;'#13#10
    + '    color: %1:s;'#13#10
    + '    font-family: "%2:s";'#13#10
    + '    font-size: %3:dpt;'#13#10
    + '    margin: 4px;'#13#10
    + '}'#13#10
    + 'h1 {'#13#10
    + '    font-size: %3:dpt;'#13#10
    + '    font-weight: bold;'#13#10
    + '    text-align: center;'#13#10
    + '}'#13#10
    + 'input#button {'#13#10
    + '    color: %1:s;'#13#10
    + '    font-family: "%2:s";'#13#10
    + '    font-size: %3:dpt;'#13#10
    + '}'#13#10
    + '.ruled {'#13#10
    + '    border-bottom: %4:s solid 2px;'#13#10
    + '    padding-bottom: 6px;'#13#10
    + '}';
  FmtCSS: string;  // Stores default CSS
  // Create the CSS from system colours
  FmtCSS := Format(
    [ColorToHTML(Self.Color), ColorToHTML(Self.Font.Color),
    Self.Font.Name, Self.Font.Size,
  // Create web browser container and set required properties
  fWBContainer := TWBContainer.Create(WebBrowser1);
  fWBContainer.UseCustomCtxMenu := True;    // use our popup menu
  fWBContainer.Show3DBorder := False;       // no border
  fWBContainer.ShowScrollBars := False;     // no scroll bars
  fWBContainer.AllowTextSelection := False; // no text selection
  fWBContainer.CSS := FmtCSS;               // CSS to be used
  // load content
    ExtractFilePath(ParamStr(0)) + 'DlgContent.html'

Key points to note in this method are:

A couple more things remain to be done. The first is to handle the form's OnDestroy event to free the container object, as shown in Listing 23.

procedure TForm1.FormDestroy(Sender: TObject);
  fWBContainer.Free;  // free the container pbject

Finally we need to handle the OnClick event of our single context menu item. All we do here is display the default CSS in a message box, as Listing 24 illustrates.

procedure TForm1.ShowtheCSS1Click(Sender: TObject);
  ShowMessage(fWBContainer.CSS);  // display the CSS code

The moment of truth arrives. Let's run the revised application and see if it all works. Here's what we see on Windows XP with themes enabled:

Picture of demo program

Notice that:

Just to show that the browser control correctly adopts the current dialog box style, here is the same application running unchanged in on Windows XP using its classic style with the Spruce colour scheme:

Picture of demo program

All the code has now been completed. In the final section we will wrap up the article and provide a download containing all the source code for the sample application.