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).
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.
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.)
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.
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);
[...]
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);
}
}