ShowHTMLDialog( URL [, argIn, Options, hwndParent, Flags ] )
Creates a modal dialog box that displays HTML. (It does not return until the dialog is closed.)
Requires: COM Standard Library
Optional: DispatchObj allows JavaScript embedded in the HTML to interact with the AutoHotkey script.
Parameters
URL:
Any Internet Explorer-compatible URL. If the javascript: protocol is specified, the result of the JavaScript expression is used as the HTML content (see Example 2.)
dialogArguments:
A string or object to pass to the dialog. It is accessible in JavaScript as window.dialogArguments (usually just dialogArguments will do.) Pass an object by prefixing "+" (quotes included; see Example 2.)
Options:
A semicolon-delimited list of values, as described in the script.
hwndParent:
The unique ID/hwnd of the parent of the dialog box.
Flags:
If specified, ShowHTMLDialogEx is called instead of ShowHTMLDialog. See "Useful flags" at the bottom of this post.
returns: The value of
window.returnValue, if assigned by the dialog's script.
Code:
/* Flags: Search MSDN for ShowHTMLDialogEx.
#define HTMLDLG_NOUI 0x0010 // invisible
#define HTMLDLG_MODAL 0x0020 // normal behaviour
#define HTMLDLG_MODELESS 0x0040 // returns immediately
#define HTMLDLG_PRINT_TEMPLATE 0x0080
#define HTMLDLG_VERIFY 0x0100 // force into viewable portion of desktop
#define HTMLDLG_ALLOW_UNKNOWN_THREAD 0x0200 // IE7+
*/
/* Options: one or more of the following semicolon-delimited values:
dialogHeight:sHeight
Sets the height of the dialog window.
Valid unit-of-measure prefixes: cm, mm, in, pt, pc, em, ex, px
dialogLeft:sXPos
Sets the left position of the dialog window relative to the upper-left
corner of the desktop.
dialogTop:sYPos
Sets the top position of the dialog window relative to the upper-left
corner of the desktop.
dialogWidth:sWidth
Sets the width of the dialog window.
Valid unit-of-measure prefixes: cm, mm, in, pt, pc, em, ex, px
center:{ yes | no | 1 | 0 | on | off }
Specifies whether to center the dialog window within the desktop. Default: yes
dialogHide:{ yes | no | 1 | 0 | on | off }
Specifies whether the dialog window is hidden when printing or using print
preview. Default: no
edge:{ sunken | raised }
Specifies the edge style of the dialog window. Default: raised
resizable:{ yes | no | 1 | 0 | on | off }
Specifies whether the dialog window has fixed dimensions. Default: no
scroll:{ yes | no | 1 | 0 | on | off }
Specifies whether the dialog window displays scrollbars. Default: yes
status:{ yes | no | 1 | 0 | on | off }
Specifies whether the dialog window displays a status bar. Default: no
unadorned:{ yes | no | 1 | 0 | on | off }
Specifies whether the dialog window displays the window border.
*/
ShowHTMLDialog(URL, dialogArguments="", Options="", hwndParent=0, Flags=0)
{
; "Typically, the COM library is initialized on a thread only once. Subsequent
; calls to CoInitialize or CoInitializeEx on the same thread will succeed,..."
COM_CoInitialize()
hinstMSHTML := DllCall("LoadLibrary","str","MSHTML.DLL")
hinstUrlMon := DllCall("LoadLibrary","str","urlmon.dll") ; necessary to keep the URL moniker in memory.
if !hinstMSHTML or !hinstUrlMon
goto ShowHTMLDialog_Exit
pUrl := COM_SysAllocString(URL)
hr := DllCall("urlmon\CreateURLMonikerEx","uint",0,"uint",pUrl,"uint*",pUrlMoniker,"uint",1)
if (ErrorLevel) {
Error = DllCall(CreateURLMoniker)--%ErrorLevel%
goto ShowHTMLDialog_Exit
}
if (hr or !pUrlMoniker) {
Error = CreateURLMoniker--%hr%
goto ShowHTMLDialog_Exit
}
pOptions := Options!="" ? COM_SysAllocString(Options) : 0
VarSetCapacity(varArgIn,16,0), VarSetCapacity(varResult,16,0)
if dialogArguments is integer
{ ; int64 or +object (IDispatch)
NumPut(SubStr(dialogArguments,1,1)="+" ? 9:20,varArgIn,0)
NumPut(dialogArguments,varArgIn,8,"int64")
} else { ; string
NumPut(8,varArgIn,0)
NumPut(pArgIn:=COM_SysAllocString(dialogArguments),varArgIn,8)
}
if Flags
hr := DllCall("mshtml\ShowHTMLDialogEx","uint",hwndParent,"uint",pUrlMoniker,"uint",Flags,"uint",&varArgIn,"uint",pOptions,"uint",&varResult)
else
hr := DllCall("mshtml\ShowHTMLDialog","uint",hwndParent,"uint",pUrlMoniker,"uint",&varArgIn,"uint",pOptions,"uint",&varResult)
if (ErrorLevel) {
Error = DllCall(ShowHTMLDialog)--%ErrorLevel%
goto ShowHTMLDialog_Exit
}
if (hr) {
Error = ShowHTMLDialog--%hr%
goto ShowHTMLDialog_Exit
}
; based on a line from COM_Invoke(). returnValue = varResult as string;
InStr(" 0 4 5 6 7 14 "," " . NumGet(varResult,0,"Ushort") . " ") ? DllCall("oleaut32\VariantChangeTypeEx","Uint",&varResult,"Uint",&varResult,"Uint",0,"Ushort",0,"Ushort",8) : "", NumGet(varResult,0,"Ushort")=8 ? (returnValue:=COM_Ansi4Unicode(NumGet(varResult,8))) . COM_SysFreeString(NumGet(varResult,8)) : returnValue:=NumGet(varResult,8)
ShowHTMLDialog_Exit:
if pArgIn
COM_SysFreeString(pArgIn)
if pOptions
COM_SysFreeString(pOptions)
if pUrlMoniker
COM_Release(pUrlMoniker)
if pUrl
COM_SysFreeString(pUrl)
; "Each process maintains a reference count for each loaded library module.
; This reference count is incremented each time LoadLibrary is called and
; is decremented each time FreeLibrary is called."
; -- So FreeLibrary() will not unload these DLLs if they were loaded before
; the function was called. :)
if hinstMSHTML
DllCall("FreeLibrary","uint",hinstMSHTML)
if hinstUrlMon
DllCall("FreeLibrary","uint",hinstUrlMon)
; "To close the COM library gracefully, each successful call to CoInitialize
; or CoInitializeEx, including those that return S_FALSE, must be balanced
; by a corresponding call to CoUninitialize."
COM_CoUninitialize()
ErrorLevel := Error
return returnValue
}
Covered by Lexikos' default copyright license.Example 1:Code:
ShowHTMLDialog("http://www.autohotkey.com/forum/faq.php", "", "dialogWidth:800px;resizable:yes")
Example 2:Demonstrates how to use a Scripting.Dictionary object to load HTML from a variable and pass multiple named arguments to the dialog.
Code:
html =
(
<HEAD><TITLE>Example Dialog</TITLE></HEAD>
<BODY>
<INPUT TYPE=text ID="textbox"><BR>
<BUTTON ID="okButton">Okay</BUTTON><BR>
<SCRIPT FOR="window" EVENT="onload">
textbox.value = dialogArguments.Item('DefaultText');
textbox.select();
</SCRIPT>
<SCRIPT FOR="okButton" EVENT="onclick">
window.returnValue = textbox.value;
window.close();
</SCRIPT>
</BODY>
)
COM_Init()
args := COM_ActiveXObject("Scripting.Dictionary")
COM_Invoke(args, "Item=", "HTML", html)
COM_Invoke(args, "Item=", "DefaultText", "default text!")
text := ShowHTMLDialog("javascript:dialogArguments.Item('HTML')", "+" args, "dialogWidth:150px;dialogHeight:50px")
if text !=
MsgBox % text
COM_Release(args)
COM_Term()
Notes:
It isn't necessary to call COM_CoInitialize() (or COM_Init()) on script start-up, but doing so would probably improve performance (if you call ShowHTMLDialog more than once), since the function would otherwise initialize and free the COM libraries each time the function is called.
The same goes for urlmon.dll and mshtml.dll. (LoadLibrary is used inside the function because urlmon
must remain loaded for the URL moniker to persist in memory after CreateURLMonikerEx returns.)
Useful flags:
HTMLDLG_NOUI (0x10)
Quote:
Open the dialog box without a user interface. The dialog box is instantiated and can run scripts, and so on, but is not visible to the user.
This could be used for determining the size a dialog should be before showing it to the user. If the dialog should never be shown, specifying HTMLDLG_NOUI speeds up the call to ShowHTMLDialogEx considerably.
HTMLDLG_MODELESS (0x40) returns immediately without waiting for the dialog to close. The return value of ShowHTMLDialog (window.returnValue) is not usable in this context.
MSDN states that modeless dialogs are "created in a separate process." This does not seem to be the case.
Please note:Quote:
At least one of the flags HTMLDLG_MODELESS and HTMLDLG_MODAL must be included in dwDialogFlags. If both are declared, HTMLDLG_MODELESS takes precedence over HTMLDLG_MODAL.