Figure 2   Pseudocode for a WSH Dialog

 //////////////////////////////////////////////////
 //
 // JScript pseudo-code that illustrates how the 
 // COM-based dialog provider will work.
 //
 
 // Creates an instance of the object.
 var dlg = new ActiveXObject( "Dialog.Provider" );
 
 // Create the dialog template.
 dlg.Create( "template.htm" );
 
 // Initializes some of the page elements. Each
 // element is identified via ID and updated 
 // through DHTML.
 dlg.SetDlgItemImg( "logo", "mycompany.gif" );
 dlg.SetDlgItemText( "companyName", "Expoware Soft" );
 dlg.SetDlgItemLink( "companySite", "http://www.expoware.com" );
 
 // display the dialog
 dlg.Show();

Figure 4   Programming Interface of the
      Dialog-provider COM Server

Method Description
Create ( htmlFile ) Creates a dialog window that hosts a WebBrowser control, a status bar, and an OK button, and makes it navigate to the specified HTML page. The dialog is up and running but not visible yet.
SetDlgItemText( id, value ) Sets the innerHTML property of the object with the given ID.
GetDlgItemText( id ) Reads the innerHTML property of the object with the given ID.
SetDlgItemImg( id, value) Sets the src attribute of the IMG tag with the given ID.
GetDlgItemImg( id ) Reads the src attribute of the IMG tag with the given ID.
SetDlgItemLink( id, value) Sets the href attribute of the A tag with the given ID.
GetDlgItemLink( id ) Reads the href attribute of the A tag with the given ID.
SetDlgItemInput( id, value) Sets the value attribute of the INPUT tag with the given ID.
GetDlgItemInput( id ) Reads the value attribute of the INPUT tag with the given ID.
Show() Displays the dialog modally.
GetObject( id ) Returns a reference to the object inside the page with the given ID.


Figure 5   Source Code of the Dialog-provider COM Server


 ' It lets you get/set the HTML content of a given
 ' text-based tag.
 ' ------------------------------------------------------------------
 Public Sub SetDlgItemText(ByVal sID As String, ByVal sText As String)
 On Error Resume Next
     g_doc.All(sID).innerText = sText
 End Sub
 
 Public Function GetDlgItemText(ByVal sID As String) As String
 On Error Resume Next
     GetDlgItemText = g_doc.All(sID).innerHTML
 End Function
 
 
 ' It lets you get/set the image source for an IMG tag
 ' ------------------------------------------------------------------
 Public Sub SetDlgItemImg(ByVal sID As String, ByVal sSrc As String)
 On Error Resume Next
     g_doc.All(sID).src = sSrc
 End Sub
 
 Public Function GetDlgItemImg(ByVal sID As String) As String
 On Error Resume Next
     GetDlgItemImg = g_doc.All(sID).src
 End Function
 
 
 ' It lets you get/set the reference of an hyperlink
 ' ------------------------------------------------------------------
 Public Sub SetDlgItemLink(ByVal sID As String, ByVal sHref As String)
 On Error Resume Next
     g_doc.All(sID).href = sHref
 End Sub
 
 Public Function GetDlgItemLink(ByVal sID As String) As String
 On Error Resume Next
     GetDlgItemLink = g_doc.All(sID).href
 End Function
 
 
 ' It lets you get/set the HTML content of a given INPUT text element.
 ' -------------------------------------------------------------------
 Public Sub SetDlgItemInput(ByVal sID As String, ByVal sText As String)
 On Error Resume Next
     g_doc.All(sID).Value = sText
 End Sub
 
 Public Function GetDlgItemInput(ByVal sID As String) As String
 On Error Resume Next
     GetDlgItemInput = g_doc.All(sID).Value
 End Function

Figure 7   Custom Attributes for the Embedded Form

Attributes Description
RetVal Used to store the return value from the dialog. True if you closed it through the OK button, False otherwise.
Methods Description
SetHtmlPage Navigates to the specified page and makes sure to return only when the document has been completely downloaded. It also inserts a hidden ActiveX control to look for and reflect DHTML events.
DoCallback Public function that the inserted ActiveX control calls when it catches a DHTML event on the page. The control gets a reference to the form as an argument to one of its methods.
Events Description
GotHTMLEvent The form raises this event to let the COM object know about a DHTML event that occurred.


Figure 8   frmWshUI

 Option Explicit
 
 ' --------------------------------------------
 Private Declare Function IsIconic Lib "user32" ( _
     ByVal hwnd As Long _
 ) As Long
 
 ' --------------------------------------------
 Private Const DLG_PADDING = 100
 Private Const DLG_CAPTION = 500
 Private Const DLG_2BORDER = 100
 
 ' --------------------------------------------
 Private g_bIsReady As Boolean
 
 '---------------------------------------------
 Private Const STR_HTMLSPY = "<object id=hook style='display:none' 
classid='clsid:4939263D-4D80-11D2-BC00-AC6805C10E27'></object>"
 
 
 '---------------------------------------------
 Event GotHTMLEvent(ByVal evName As String, ByVal srcID As String)
 
 
 ' --------------------------------------------
 Public RetVal As Boolean        ' return value: F is canceled
 
 
 ' Move the dialog outside the screen, display
 ' the dialog and navigate to the page
 '---------------------------------------------
 Public Function SetHtmlPage(ByVal htmlPage As String) As HTMLDocument
     Dim doc As HTMLDocument
     
     ' navigate to the page
     GotoPage htmlPage
     
     ' wait for the document to be completely loaded
     g_bIsReady = False
     While Not g_bIsReady
         DoEvents
     Wend
     
     ' add the spy ActiveX control
     Set doc = wb.Document
     doc.body.insertAdjacentHTML "AfterBegin", STR_HTMLSPY
     
     ' return the reference to the document object model
     Set SetHtmlPage = wb.Document
     
     ' initialize the spy ActiveX control
     Dim obj As Object
     Set obj = doc.All("hook")
     obj.Activate Me
     
     ' set the status bar
     sb.Caption = htmlPage
 End Function
 
 
 ' Callback function invoked by the Spy
 ' ActiveX control
 ' --------------------------------------------
 Public Sub DoCallback(ByVal evName As String, ByVal srcID As String, _
                       ByVal param As String)
     If Len(param) Then
         sb.Caption = param
     End If
     RaiseEvent GotHTMLEvent(evName, srcID)
 End Sub
 
 
 ' Initializes some global form's attributes
 ' --------------------------------------------
 Private Sub Form_Load()
     RetVal = False
 End Sub
 
 
 ' Arranges properly the controls on the form
 ' --------------------------------------------
 Private Sub Form_Resize()
     Dim frmRealWidth, frmRealHeight As Integer
 
     ' skip if minimizing...
     If IsIconic(frmWshUI.hwnd) Then
         Exit Sub
     End If
 
     ' get the form real width and height by removing
     ' twips for borders and caption
     frmRealWidth = frmWshUI.Width - DLG_2BORDER
     frmRealHeight = frmWshUI.Height - DLG_CAPTION
     
     wb.Move DLG_PADDING, _
             DLG_PADDING, _
             frmRealWidth - 2 * DLG_PADDING, _
             frmRealHeight - 2 * DLG_PADDING - sb.Height
 
     sb.Move DLG_PADDING, _
             wb.Top + wb.Height + DLG_PADDING, _
             frmRealWidth - ok.Width - 3 * DLG_PADDING
 
     ok.Move sb.Left + sb.Width + DLG_PADDING, _
             wb.Top + wb.Height + DLG_PADDING
 End Sub
 
 
 ' Navigate to the specified page
 ' --------------------------------------------
 Private Sub GotoPage(ByVal htmlPage As String)
     wb.Navigate htmlPage
 End Sub
 
 
 ' The form is being unloaded now. RetVal indicates
 ' whether the user closed it through OK or Cancel.
 ' --------------------------------------------
 Private Sub Form_Unload(Cancel As Integer)
     UnloadedNow = True
 End Sub
 
 
 ' The user closed the dialog by clicking on OK
 ' so return True.
 ' --------------------------------------------
 Private Sub ok_Click()
     RetVal = True
     Unload Me
 End Sub
 
 
 ' Fired when the document loading completed
 ' --------------------------------------------
 Private Sub wb_DocumentComplete(ByVal pDisp As Object, URL As Variant)
      g_bIsReady = True
 End Sub
 
 
 ' Fired when the browser has a message to display
 ' --------------------------------------------
 Private Sub wb_StatusTextChange(ByVal text As String)
     sb.Caption = text
 End Sub

Figure 9   HTML Template

 <html>
 <head>
 <title>Create Shortcut...</title>
 <style>
 .Normal {
     background-color: white;
     color: black
  }
 .Highlight {
     background-color: lightblue;
     font-Weight: bold;
     color: white
  }
 </style>
 </head>
 
 <body onload="init()" onclick="rollon()">
 
 <img src="windows.gif" id="logo" style="FILTER: alpha(opacity=0)" 
         width="30%" height="30%" align="middle"> 
 
 <a id="site" href="http://www.server.com">
         <font face="Verdana"><strong>Company Web Site</strong></font>
 </a>
 
 <font face="Verdana" size="6"><strong>
         <span id="company">Company Name</span>
 </strong></font>
 
 <hr>
 
 <strong><font face="Verdana"><font color="#FF0000">
 <big>I</big></font>nsert <big>HERE</big>
 all the data required to <font color="#0000FF">
 <big>C</big>reate</font> a <big>
 <big>s</big></big>hortcut...</font></strong>
 
 <br>
 
 <table border="0" width="68%">
     <tr>
         <td width="21%"><strong><font face="Verdana">Target</font></strong></td>
         <td width="79%">
             <input class="Normal" type="text" id="target" size="48" 
                 tip="Type here the target" style="border: medium none" 
                 value="Type here the target">
         </td>
     </tr>
     <tr>
         <td width="21%"><strong><font face="Verdana">Save</font></strong></td>
         <td width="79%">
             <input class="Normal" type="text" id="saveas" size="48" 
                 tip="Type here the shortcut's name" style="border: medium none" 
                 value="Type here the shortcut's name">
         </td>
     </tr>
 </table>
 </body>
 
 
 <script>
 function init()
 {
     logo.flashTimer = setInterval("fade()", 100)
 }
 
 function fade()
 {
     if (logo.filters.alpha.opacity < 100)
         logo.filters.alpha.opacity = logo.filters.alpha.opacity + 5
     else
         clearInterval(logo.flashTimer)
 }
 
 function rollon() {
     obj = window.event.srcElement;
     objID = window.event.srcElement.id;
 
     if( objID=="target" || objID=="saveas" ) {
         if( obj.className == "Normal" ) {
             obj.className = "Highlight";
             if( objID=="target" )
                 saveas.className = "Normal";
             if( objID=="saveas" )
                 target.className = "Normal";
         }
     }
     else {
         target.className = "Normal";
         saveas.className = "Normal";
     }
 }
 </script>
 </html> 

Figure 11   A Sample VBScript Module

 ' ---------------------------------------------
 ' VBScript demo for using the WshUI object
 
 ' constants
 TEMPLATE = "E:\ARTICLES\MIND\WshUI\source\VB\shortcut.htm"
 IMGLOGO  = "E:\ARTICLES\MIND\WshUI\source\VB\cpnylogo.gif"
 
 
 ' create the WSH object
 Set o = CreateObject( "WshUI2.HtmlDialog" )
 
 ' define the HTML-based template    
 o.Create( TEMPLATE )
     
 ' initialize the dialog
 o.SetDlgItemLink "site", "http://www.expoware.com"
 o.SetDlgItemText "site", "Get in touch with Expoware Soft"
 o.SetDlgItemImg "logo", IMGLOGO
 o.SetDlgItemText "company", "Expoware Soft"
 
 Set t1 = o.GetObject("target")
 t1.Value = "c:\windows"
 Set t2 = o.GetObject("saveas")
 t2.Value = "myShortcut.lnk"
     
 ' executes the dialog
 bResult = o.Show()
     
 ' displays return values
 If bResult = True Then
      MsgBox t1.Value + "  " + t2.Value
 End If

Figure 13   Spy ActiveX Control


' our CLSID is {4939263D-4D80-11D2-BC00-AC6805C10E27}
 
 ' --------------------------------------------------
 Private WithEvents g_document As HTMLDocument
 Private g_window As HTMLWindow2
 Private g_form As Form
 
 ' --------------------------------------------------
 Public Function Activate(ByVal f As Object) As Boolean
     ' Actually f is treated as a Visual Basic form exposing a
     ' DoCallback method
     
     Set g_form = f
     Activate = True
 End Function
 
 
 '//////////////////////////////////////////////////
 '//
 '// PRIVATE Event Handlers
 '//
 
 ' --------------------------------------------------
 Private Sub UserControl_InitProperties()
     Set g_window = UserControl.Parent.Script
     Set g_document = g_window.document
 End Sub
 
 ' --------------------------------------------------
 Private Sub g_document_onmouseover()
 On Error Resume Next
     Dim obj As IHTMLElement
     Dim sHelpText As String
     
     Set obj = g_window.event.srcElement
     sHelpText = obj.getAttribute("tip")
     g_form.DoCallback "onmouseover", obj.id, sHelpText
 End Sub
 
 ' --------------------------------------------------
 Private Function g_document_onclick() As Boolean
 
 End Function
 
 ' --------------------------------------------------
 Private Function g_document_ondblclick() As Boolean
 
 End Function
 
 ' --------------------------------------------------
 Private Sub g_document_onmousemove()
 
 End Sub
 
 ' --------------------------------------------------
 Private Sub g_document_onmouseout()
 
 End Sub

Figure 14   The Modified WSH Shortcut

 ' ---------------------------------------------
 ' VBScript demo for using the WshUI object
 ' ---------------------------------------------
 
 ' constants
 TEMPLATE = "E:\ARTICLES\MIND\WshUI\source\VB\shortcut.htm"
 IMGLOGO  = "E:\ARTICLES\MIND\WshUI\source\VB\cpnylogo.gif"
 
 
 ' get the command line arguments
 if WScript.Arguments.Length > 0 Then
    for i=0 to WScript.Arguments.Length-1 
        DoCreateShortcut( WScript.Arguments.Item(0) )       
    next    
 else
    DoCreateShortcut( "" )       
 end if 
 WScript.Quit
 
 
 ' ---------------------------------------------
 '  DoCreateShortcut procedure
 ' ---------------------------------------------
 Sub DoCreateShortcut( sTargetFile )
 
   ' create the WSH object
   Set o = CreateObject( "WshUI2.HtmlDialog" )
 
   ' define the HTML-based template    
   o.Create( TEMPLATE )
     
   ' initialize the dialog
   o.SetDlgItemLink "site", "http://www.expoware.com"
   o.SetDlgItemText "site", "Get in touch with Expoware Soft"
   o.SetDlgItemImg "logo", IMGLOGO
   o.SetDlgItemText "company", "Expoware Soft"
 
   Set t1 = o.GetObject("target")
   t1.Value = sTargetFile
   Set t2 = o.GetObject("saveas")
   t2.Value = "MyShortcut.lnk" 
     
   ' executes the dialog
   bResult = o.Show()
     
   ' check the result
   If bResult = False Then
      Exit Sub
   End If
 
   ' create the shell object
   Set shell = WScript.CreateObject( "WScript.Shell" )
   path = shell.SpecialFolders( "Desktop" )
   Set s = shell.CreateShortcut( path & "\" & t2.Value )
   s.TargetPath = t1.Value
   s.Save
 
 End Sub

Figure 15   DropHandler Shell Extension

 // WshUIDrop.cpp : Implementation of CWshUIDrop
 #include "stdafx.h"
 #include "VbsDrop.h"
 #include "WshUIDrop.h"
 #include <ShellAPI.h>
 #include <ShlObj.h>
 #include <ShlwAPI.h>
 #pragma comment( lib, "shlwapi.lib" )
 
 /////////////////////////////////////////////////////////////////////////////
 // CWshUIDrop
 
 HRESULT CWshUIDrop::Drop( LPDATAOBJECT pDO, DWORD dwKeyState,
     POINTL pt, LPDWORD pdwEffect )
 {
     //CHAR szMsg[MAX_PATH];
     
 
     // get the Shell memory handler
     LPMALLOC pMalloc;
     SHGetMalloc( &pMalloc );
 
     // get the CF_HDROP data object
     HDROP hdrop;
     hdrop = GetHDrop( pDO );
 
     // allocate enough memory
     LPSTR pszBuf;
     INT iNumOfFiles = DragQueryFile( hdrop, -1, NULL, 0 );
     pszBuf = (LPSTR) pMalloc->Alloc( (1+MAX_PATH)*iNumOfFiles );
     LPSTR psz = pszBuf;
     if( !pszBuf ) {
         pMalloc->Release();
         return E_FAIL;
     }
     ZeroMemory( pszBuf, (1+MAX_PATH)*iNumOfFiles );
 
     // get the dropped file names
     for( INT i=0; i<iNumOfFiles; i++ )  {
         CHAR s[MAX_PATH];
         DragQueryFile( hdrop, i, s, MAX_PATH );
         PathQuoteSpaces( s );
         lstrcat( pszBuf, s );
         lstrcat( pszBuf, " " );
     }
     DragFinish( hdrop );
 
     // message to the world...
     //wsprintf( szMsg, "%s \ndropped on \n%s", szSrc, m_szFile );
     //::MessageBox(0, szMsg, 0, 0); 
 
     // run the script file passing the dropped file as 
     // a command line argument.
     ShellExecute( GetFocus(), "open", m_szFile, pszBuf, NULL, SW_SHOW );
     
     pMalloc->Release();
     return S_OK;
 }
 
 
 //////////////////////////////////////////////
 //  
 //   Private Helper Functions 
 //
 
 
 // Extracts an HDROP from a LPDATAOBJECT
 HDROP CWshUIDrop::GetHDrop( LPDATAOBJECT pDO )
 {
     STGMEDIUM sm;
     FORMATETC fe;
 
     // check for CF_HDROP data
     ZeroMemory( (LPVOID)&sm, sizeof(STGMEDIUM) );
     ZeroMemory( (LPVOID)&fe, sizeof(FORMATETC) );
     fe.tymed = TYMED_HGLOBAL;            
     fe.lindex = -1;            
     fe.dwAspect = DVASPECT_CONTENT;
     fe.cfFormat = CF_HDROP; 
     if( FAILED(pDO->GetData( &fe, &sm )) )
         return NULL;
     else
         return (HDROP) sm.hGlobal;
 }