VCL component to render and show HTML in Delphi or C++ builder

I came across this nice set of VCL components, now free and open (MIT-style license I guess), which allows you to render and show a relatively extensive set of html constructs inside a C++ builder application. It can even do some CSS. Using HTML in Delphi or c++ Builder has always been cumbersome (with the TCppBrowser components delivered in the Borland/Codegear/Embarcadero VCL package that actually mask Internet Explorer which then starts stealing your keyboard shortcuts).

Rendering HTML in a VCL application and handle links either in your application or in your preferred browser

With this component, you can assemble a string with HTML-code and show it (or show a page from an external URL of course). Below I describe how you can compile this Delphi-source code for use in a C++ builder application, and also how you can display a page in your application which can contain links to external pages, but which can also trigger actions in your own application.

THTMLViewer : versions and maintenance

The software by Dave Baldwin consists of HTML Display Components: THTMLViewer, TFrameViewer, and TFrameBrowser. It is available (but not maintained anymore) on www.pbear.com . When searching on google, you can find a followup-project on google code (which has at the time of this writing no files yet). And it has been ported for use in Lazarus  : http://wiki.lazarus.freepascal.org/THtmlPort . A quick search resulted in this link for a C++ Builder 2009 (and 2010 ?) version of THTMLViewer : http://www.songbeamer.com/delphi/ (I did not test this yet.)

Use in C++ builder

In order to compile the www.pbear.com -components (version 9.45) with Borland Developer Studio 2006, for use in a C++ builder project, the following steps should be performed. Below a workaround is provided for a compilation problem with the generated hpp-files.

  • Started BDS 2006 (all personalities, not just delphi!)
  • Opened the project FrameViewer2006.bdsproj
  • In project options, i set the linker option "Generate all C++ files"
  • Build, Install
  • Closed the project FrameViewer2006.bdsproj
  • Opened the C++ project (in this case MFS, GPL-software with usage range from simple invoicing to ERP (only in Dutch)), It seems that BDS 2006 does not like to have a delphi and a C++builder project open at the same time. The new components are in the "Sample" tab in the panel.
  • Added the ...\thtml\packages directory to the include search path in project options (C++ options, directories and conditionals)
  • Added the ....\thtml\packages directory to the library search path in project options (linker, directories and conditionals). (Note : I use static linking, not the .bpl-files. By including this in the linker search path, the linker finds the .lib file)
  • Included a THTMLViewer component in a form. I had to manually change the include directive from <xxxxxx.h> to <xxxxxx.hpp>

Upon compilation, the compiler emits an error [C++ Error] Htmlun2.hpp(574): E2091 Functions cannot return arrays or functions for 2 different lines in the delphi-generated .hpp-header file. Since I did not want to use those functions declared in the .hpp file, I have just commented them out :

[...]

//extern PACKAGE htBorderStyleArray __fastcall htStyles(Styleun::BorderStyleType P0, Styleun::BorderStyleType P1, Styleun::BorderStyleType P2, Styleun::BorderStyleType P3);

[...]

//extern PACKAGE htColorArray __fastcall htColors(Graphics::TColor C0, Graphics::TColor C1, Graphics::TColor C2, Graphics::TColor C3);

[...]

Use THTMLViewer and either handle links in your application or send them to a browser : OnHotspotClick.

Drag a THTMLViewer component from the palette to your form. Then you can assemble a string with HTML code in it, and show it with :

HTMLViewer1->LoadFromString(asHtml);
 

Furthermore, I use the OnHotspotClick event to detect clicks on links in the page, which I then handle in my application (or send to Internet Explorer if they are external). I define a "custom" protocol (like http:, I called it 'app:') for events which should be handled by the application itself. An example link which opens quote nr. 123 is then formed as : <a href="app:quote?123">Quote 123</a>. The event handler code :

void __fastcall TMfsMainForm::HTMLViewer1HotSpotClick(TObject *Sender,
      const AnsiString SRC, bool &Handled)
{
AnsiString asUrl = SRC;
if (asUrl.SubString(1,4)=="app:")
    {
    int offPos = asUrl.Pos("quote?");
    int custPos = asUrl.Pos("cust?");
    int prosPos = asUrl.Pos("pros?");
    if (offPos > 0)
        {
        AnsiString nrSub = asUrl.SubString(offPos+6, asUrl.Length()-offPos-6+1);
        long offNr = nrSub.ToInt();
        OffOpvForm->ShowOffNr(offNr);
        }
    if (custPos > 0)
        {
        long custNr = asUrl.SubString(custPos+5, asUrl.Length()-custPos-5+1).ToInt();
        KlEditForm->ShowKlNr(custNr);
        }
    if (prosPos > 0)
        {
        long prosNr = asUrl.SubString(prosPos+5, asUrl.Length()-prosPos-5+1).ToInt();
        ProsEdit->ShowProsNr(prosNr);
        }
    }
else
    {

    // Open default browser (IE or Firefox or ...)
    ShellExecute(this->Handle, "open", asUrl.c_str(), NULL, NULL  ,SW_SHOWNORMAL);
    }
}