Site hosted by Angelfire.com: Build your free website today!

Home
DelphiZeus
HTML Dialog Boxes
Use Dialog Boxes that are IE windows
and display HTML files

Home



HTML Dialog Boxes are produced with the API ShowHTMLDialog( ) function
What does an HTML Dialog Box look like?
When the ShowHTMLDialog( ) function is used, Internet Explorer shows an IE Browser window with only a dialog type Title bar (no menu or tool bars, or status). This browser window will read the HTML in a file, and display it like a browser window. If you need user input (buttons, edit, radio buttons), you will use JScript or VBScript as the code language for functions to read or change these inputs, using methods a HTML web page would use.

You might consider using a HTML Dialog if you are good with HTML and Java-Script and are using a Web Browser Interface in your program. The HTML Dialog does not offer many advantages over normal programming methods in Delphi, however, if you use IE as your GUI, then you can display anything thats availible in HTML IE display. You can display Jpeg, Gif, and Png images without adding any Jpeg, Gif or Png units to your uses clause.


Where is the ShowHTMLDialog( ) function? In a Delphi  .pas unit?
No. The ShowHTMLDialog() function is in the MSHTML.dll library, and you will need to use

hLib := LoadLibrary('MSHTML.DLL');

to access this DLL, and then use

ShowHTMLDialog := GetProcAddress(hLib, 'ShowHTMLDialog');

to get the address for this function. You can use this function only if Internet Explorer version 4 and above is installed.

Using the ShowHTMLDialog( ) function
Since the HTML Dialog is an Internet Explorer browser window, COM is used to comunicate between your program and IE, with variants, IMoniker and IHTMLDialog interfaces. And the ShowHTMLDialog function will implement these interfaces for you. The ShowHTMLDialog fuction is defined below -
function ShowHTMLDialog(
  hwndParent: Cardinal;   // parent's handle
  UrlMnk: IMoniker;       // IMoniker which has the HTML source file
  PvarArgIn: PVariantArg; // Variant address that contains PWChar sent
                          // to dialog
  PWCHOptions: PWChar;    // pointer to WideChar with Dialog Options
  PvarArgOut: PVariantArg // Variant address receives the data placed
                          // in the IHTMLDialog::returnValue
  ): HRESULT; // function Result is an OLE HRESULT (Integer)
The Result Value will Return S_OK if successful, or an error value.
This function has five parameters defined below -
• hwndParent -
Handle to the parent of the dialog box, can be zero.
• UrlMnk -
An IMoniker interface containing the URL from which the HTML file for the dialog box is loaded, file can be in app's resources.
• PvarArgIn -
Pointer to a VariantArg record that contains the data sent to the dialog box. The data passed in this VariantArg is placed in the dialog window object's IHTMLDialog::dialogArguments property. This is mostly set as a VT_BSTR, with a PWChar for text the dialog will use for display. This parameter can be set as an empty VariantArg (VT_EMPTY).
• PWCHOptions -
Window options for the dialog box. This parameter can be NIL or the address of a PWChar that contains a combination of values for the Height, Width, Resizable, Help and Center options, each separated by a semicolon  ; .
 POptions := 'dialogHeight:13;dialogWidth:21;resizable:no;help:no;center:yes'
• PvarArgOut -
Pointer to a VariantArg record that contains the data sent from the dialog box when it closes. This VariantArg gets the data that was placed in the dialog window object's IHTMLDialog::returnValue property. This parameter can be an empty VariantArg.

The IMoniker Type
The second parameter in ShowHTMLDialog is an IMoniker type. The IMoniker interface is used for naming COM objects. You can think of an IMoniker as a generalized COM usage of a pathname, in the same way that a pathname identifies a unique file in the file system, a moniker identifies a COM object. Monikers are more flexable than pathnames, a pathname can only identify files, monikers can identify any kind of object. In order to use an IMoniker, you would need to Create the IMoniker COM Object using the CreateURLMoniker function in the UrlMon.pas, This also places information into the IMoniker. It is defined below -
function CreateURLMoniker(
  MkCtx: IMoniker; // moniker to use as the base context, can be NIL
  szURL: PWChar;   // contains the text of URL to be parsed
  out mk: IMoniker // moniker with URL created from MkCtx and szURL.
  ): HResult; // function Result is an OLE HRESULT (Integer)
This URL string (szURL) needs to be prefixed with "file://" to signify a disk file location, or with "res://" to signify a program's resource location, and in the case of a resource it should be followed by the path and file name, and a "/#" preceeding the resource number, like this for file -

  UrlStr := 'file://C:\Program Files\HtmlDlg1.htm';

or

  UrlStr := 'file://' + ExtractFilePath(ParamStr(0)) + 'HtmlDlg1.htm';

and like this for a resource -

  UrlStr := 'res://MyProgram.exe/#101';

or

  UrlStr := 'res://' + ExtractFileName(ParamStr(0)) + '/#101';
      • the #101 is defined in your resource creation .rc file

The PVariantArg Type
The third and fifth parameters (PvarArgIn, PvarArgOut) in ShowHTMLDialog( ) are of PVariantArg type a pointer to a TVariantArg, that is, a Variant type that Delphi does not automatically "decode" for you, so you will need to read or set the variant data type .vt (VarArgs.vt) yourself and then use that data "Type" when using the data in the Variant. I will use the TVariantArg variable type and pass the address of this as the PVariantArg parameter.
For the PvarArgIn parameter, I will only use a TVariantArg with the variable type set to VT_BSTR. You will need to set the variant type first and then set the Data for that type, like this -
  ArugStr := 'HTML Dialog String Data';
  VarArgs.vt := VT_BSTR;  // a PWideChar type
  VarArgs.bstrVal := StringToOleStr(ArugStr);
For the PvarArgOut parameter, I use two different variant types, a 4 byte integer VT_I4, and a PWideChar VT_BSTR. . These Return variant types are NOT set by your programming code, but it is set by the type of variable used to set the window.returnValue in the JavaScript of the HTML page in the Dialog Box.


Sample Code

Code for a Button Click using ShowHTMLDialog( )
Here is a button click event that will show an HTML dialog box. I do not check for Internet Explorer version, since this does not use DHTML or COM objects that are only in higher versions (5, 6) of IE. This uses an HTML file on disk HtmlDlg1.htm, in the application's folder. A text string (VarArgs.bstrVal) is sent to the dialog with a delimited string containing the dialog title, an information text string, and text items to put in the combo box. You will need to have the HTML page code use JavaScript (or VBScript) to read the data passed to the dialog and set the data returned to the ShowHTMLDialog function. The code for the HtmlDlg1.htm web page is below this button click code. There are comments in the code to help you understand some of what I am doing here.

  uses ActiveX, ComObj, UrlMon;

  procedure TForm1.button_FileHtmlDlgClick(Sender: TObject);
  type
    TShowHTMLDialog = function(hwndParent: Cardinal;
      UrlMnk: IMoniker; PvarArgIn: PVariantArg;
      PWCHOptions: PWChar; PvarArgOut: PVariantArg): HRESULT; stdcall;
  var
    hLib2: Integer;
    ShowHTMLDialog: TShowHTMLDialog;
    URLMoniker: IMoniker;
    VarArgs, VarReturn: TVariantArg;
    ArugStr, UrlStr, Return: String;
    POptions: PWChar;
  begin
    Return := 'ERROR, IE version is Below 4 or does not support HTML '
            + 'dialogs';
    hLib2 := LoadLibrary('MSHTML.DLL');
    if hLib2 <> 0 then
    try
      ShowHTMLDialog := GetProcAddress(hLib2, 'ShowHTMLDialog');
      if Assigned(ShowHTMLDialog) then
        begin
        // The PvarArgIn is used to Pass Data To the HTML Dialog.
        // The VarArgs Variant will be used here as a PWChar, with the
        // ^ being used as a Delimiter for the seven sub Strings, that
        // are sent to the Dialog
        ArugStr := 'HTML Dialog Top Title^This is Information text '
                 + 'passed to the Dialog^Type your Name Below^'
                 + 'Small^Medium^Large^My Size^One size fits all';
        // The first sub string is the dialog Title, the next substring
        // is the text (and HTML) that will be written to the html with
        // JScript  document.write(ArgArray[1]) , notice that I have
        // HTML tags in this Text, this allows you to customize the
        // dialog from your programs data, all of the sub strings that
        // follow are placed in the Combo Box
        VarArgs.vt := VT_BSTR;
        VarArgs.bstrVal := StringToOleStr(ArugStr);

        // the UrlStr is prefixed with the  file://  to signify a disk
        // file, use  res://  to sigify a resource
        UrlStr := 'file://'+ExtractFilePath(ParamStr(0))+'HtmlDlg1.htm';
        // the URLMoniker is set to the URL of the source of the htm
        // file used for the dialog box, it can be a disk file, a
        // program resource, or an Internet file address, if the html
        // file is not found, a blank dialog box is displayed
        OLECheck(CreateURLMoniker(nil, StringToOleStr(UrlStr),
          URLMoniker));

        POptions := 'dialogHeight:17;dialogWidth:23;resizable:no;'
                  + 'help:no;center:yes';
        // POptions can be omitted (set to nil), but it allows you to
        // set some options of the dialog, like width and height
        VariantInit(OleVariant(VarReturn));
        // VariantInit sets the VarReturn.vt to VT_EMPTY
        if ShowHTMLDialog(Handle, URLMoniker, @VarArgs, POptions,
           @VarReturn) = S_OK then
        begin
          // The JScript  window.returnValue  will automatically set the
          // VarReturn.vt to the data Type that is assigned to it, I only
          // use 2 data types for the window.returnValue  , a JScript
          // text string (VT_BSTR  - OLE wide string) and an integer
          // (VT_I4)  , so any other variant data type will indicate an
          // Error
          if VarReturn.vt = VT_BSTR then
          begin
            Return := VarReturn.bstrVal;
            // I use a  ^  to delimit the VarReturn.bstrVal, but the
            // first Char is the Radio Box number, which is below 9, so
            // I do not delimit it, since it will always be a single
            // Char Return[1]
            Return := 'OK was Clicked'#10'Radio was '+Return[1]+#10
                    + 'Combo1 was '+Copy(Return,2,Pos('^',Return)-2)
                    + #10'Edit Text was  '
                    + Copy(Return,Pos('^',Return)+1, 512);
          end else
            if VarReturn.vt = VT_I4 then
              Return := 'OK was NOT clicked'#10'the VarReturn is '
                      + IntToStr(VarReturn.lVal)
            else
              Return := 'Variant Data type is not integer or OLE '
                      + 'string, ERROR';
        end else
          Return := 'The ShowHTMLDialog FAILED';
      end;
    finally
      FreeLibrary(hLib2);
    end;
    ShowMessage(Return);
  end;


HTML Code for the HtmlDlg1.htm file
Below is the HTML code for the web page "HtmlDlg1.htm", to be displayed in the HTML Dialog box created by the Delphi code above. To get funtionality from your dialog box (button press, enter text, combo boxes) you will need to use an HTML script language. If you don't know HTML or any HTML scripting language (JScript, JavaScript, VBscript), then HTML dialog boxes are not for you.

The HTML window.dialogArguments is your access to the data passed to the dialog box. You will usually pass a Wide String or an Integer in your VarArgs parameter to the dialog box. If you want more than one data item in your VarArgs variant, you can use a delimited string and the Split method in

  ArgArray = window.dialogArguments.split("^");

The Split function will use it's single parameter as the delimiter charater, to divide up the string into an array. The only data that ShowHTMLDialog gets from the dialog box comes in the VarReturn (window.returnValue) variant that is passed back as the PvarArgOut parameter. If you need more than one data item returned, you can again use a delimited string, as I have done here.


<html id=dlg1 style="width: 25.9em; height: 22em">
  <!-- If you DO NOT use the PWCHOptions in the ShowHTMLDialog, you can
       put dialog window's width and height above -->
  <head>
  <title>HTML Dialog Test</title>

  <script language="JScript">
  var RBnum = 0;

  var ArgArray = new Array();
  // get the dialog arguments into an array with .split and the
  // delimiter
  ArgArray = window.dialogArguments.split("^");

  // the ArgArray check below is not nessary, but allows you to have a
  // Default dialog box with an empty  PvarArgIn  from ShowHTMLDialog
  if (ArgArray.length == 0) {ArgArray[0] = "Dialog Title";}
  if (ArgArray.length == 1) {ArgArray[1] = "No <b>Info</b> Text";}
  if (ArgArray.length == 2) {ArgArray[2] = "None";}

  // the first Array string is the Title// set the default return value
  window.returnValue = 0;

  function StartUp()
  {
  // clear selections in Combo1
  Combo1.options.length = 0;

  // add the ArgArray strings to the Combo1 selections
  var index;
  index = 2;
  // start with index of 2 because the first 2 strings are title and info
  while(index < ArgArray.length)
     {
     var tempOption = new Option(ArgArray[index]);
     Combo1.options[Combo1.options.length] = tempOption;
     index++;
     }

  // set the first Combo1 selection position
  Combo1.options[0].selected = true;
  }

  function OkClick()
  {
  // this return value means that the OK button was clicked
  window.returnValue = RBnum+Combo1.options[Combo1.selectedIndex].text+
                       "^"+Edit1.value;
  // since the window.returnValue is a variant, it can get text or
  // numbers or objects
  // The integer RBnum is automatically converted to text
  // close the dialog window
  window.close();
  }

  function CancelClick()
  {
  // this -1 return value means that the Cancel button was clicked
  window.returnValue = -1;
  window.close();
  }

  function RadioClick(num)
  {
  RBnum = num;
  // check and UnCheck the Radios
  RB1.checked = (num == 0);
  RB2.checked = (num == 1);
  RB3.checked = (num == 2);
  }

  </script>
  </head>
  <!-- IMPORTANT, have a JScript onload in your Body tag 
  to Initialize your variables from the window.dialogArguments -->
  <body onload="StartUp()" BGCOLOR="#A0E2F2" TEXT="Black">
  <center>
  <font size="5"><b>A HTML Dialog Box</b></font>
  <!-- I use Fixed Font sizes because IE may have it's default font
  size as large or small, throwing off your sizing, but you could
  use style sheet settings to define fonts, colors, borders -->
  <font size="3">
  <br><script language="JScript">
  // a very usefull operation - document.write( )
  // the second array string is the INFO text written here
  document.write(ArgArray[1])
  </script>
  <br><input type=text name="Edit1" value="No Name" size="24"
   title="Type your Name Here"><p>
  <table border="2" cellpadding="8" cellspacing="0">
  <tr><td><font size="3"><input type=radio name="RB1" checked=1
     onClick="RadioClick(0)">Howdy<br>
    <input type=radio name="RB2" onClick="RadioClick(1)">Late<br>
    <input type=radio name="RB3" onClick="RadioClick(2)">Goomba</font>
   </td><td><font size="3">Pick your Size - <select
    name="Combo1"></select></font>
   </td></tr></table>
  <P><input type=button value="OK" id="OkBut" onClick="OkClick()"
   title="Click to use the Entries above">
  <input type=button value="Cancel" id="CancelBut"
   onClick="CancelClick()">
  </font></center>
  </body></html>
There are seven sub-strings in the VarArgs of the ShowHTMLDialog parameter, the first string is used as the Dialog Title. The second as the "info" text written to the HTML page with JScript. And all of the remaining sub-strings are added to the combo box.

Using a resource for the HTML file source
You can use the same code above for a program's resource HTML file, except you will need to place a Resource URL Moniker instead of a File Moniker. You must change the UrlStr to

  UrlStr := 'res://' + ExtractFileName(ParamStr(0)+'/#101');
  OLECheck(CreateURLMoniker(nil, StringToOleStr(UrlStr), URLMoniker));
and add a resource to your program where you will need to define the HTML file as number 23 and define the call for that resource as a number, like this for HtmDlg.rc:
  #define RT_HTML 23
  #define Dlg1 101

  Dlg1 RT_HTML "HtmlDlg1.htm"
You will need to define the RT_HTML as the number 23 (you could use any other designation beside RT_HTML, but that's the MS name), and then give your HTML files a number definition like 101. If you do not want to use the "C" code #define, you can have a more simple RC declaration with -

  101 23 "HtmlDlg1.htm"

Resource HTML Images - Here is some info for you if you are more experienced in HTML, but I do not think that IE version 4 will do this. . . I think in some sub-version of Internet Explorer Version 5 you can load html Images from an executable resource. To the IMG HTML tag to can have the res:// instead of the file://, and you need to have the executable file name (path) and two number resource ID for the resource with the image file. Maybe like -

<IMG src="file://MyApp.exe/#21/#105">

In your HTML dialog code you might make the first arrArgs array element your program's file name 'MyApp.exe'. And place a jpg or gif image in it's resources. Next have a JavaScript variable and use some code like this -

var Title_Img = '<img src="res://'+arrArgs[0]+'/#701/#201">';

<SCRIPT language="JScript">document.write(Title_Img)</script>
In your RC file code you might have -
201 701 "title.gif"


Advanced Methods

For more advanced HTML dialog boxes it is also possible to set up a COM "Interface" IDispatch link between the dialog box and your program, so the dialog box could call code in in your Delphi program through IDispatch. The VarArgs is a TVariantArg type, and has a "Variant Type" of VT_DISPATCH for an IDispatch Interface. However, My JavaScript programming knowledge is not so advanced, I do NOT know of a way to pass an interface reference in the ShowHTMLDialog( ) PvarArgIn parameter, and then in the HTML JavaScript use the window.dialogArguments to get a working COM Interface (IDispatch) for JavaScript. I could NOT find any JavaScript code that does this, or even mentions a method for this. But there may be one? The only way that I know to get a working COM Interface variable in javaScript is with some kind of "ActiveX" object creation. One way to do this in HTML is -

<OBJECT ID="MyInterface" width=0 height=0
 CLASSID="CLSID:D45FD81B-5C2E-11D1-9EC8-00C04FD1081F"
 CODEBASE="#VERSION=1,0,0,0">
</OBJECT>
Which gives you a javaScript object called "MyInterface", that you can use object oriented code to use functions and variables of that Interface object. . . And you would need to create and register a COM Interface in your Delphi program to get the CLSID number ID, for that Interface, to place in the -

  CLASSID="CLSID:YourInterfaceGUID"

reference of the HTML Object. I can not explain the complex workings of the Delphi COM Inteface creation and methods code here, I just mention this to let you know of the posibility for interaction between the HTML dialog and your program.



       

Lesson -     One  Two  Three  Four  Five  Six  Seven  Eight  Nine  Ten  Eleven




H O M E