This python recipe demonstrates how to use the Win32 ShowHTMLDialog() with Python, ctypes and comtypes on Windows.

HTML dialog screenshot

I initially published this recipe in the ctypes wiki that is not maintained anumore. During the rewrite I revisited the code and made some adjustments to get the sample running with both Python 2.6 and Python 3.1.

Requirements

Install comtypes

To run the examples below, I installed comtypes directly from the source downloaded from the comtypes Sourceforge repository. Installing comtypes with Python 2.6 required to perform the following in the comtypes directory:

C:\> python setup.py install

With Python 3.1, an additional step needs to be performed. To help overcome the burden of converting Python 2.6 and above to version 3.1 Python 3.1 includes the conversion script 2to3.py. You can find this script in your Python 3 directory, under Tools/Scripts. Prior installing comtypes for Python 3.1, convert comtypes code by executing the following command in the directory where you checked out comtypes:

C:\> python C:\Python31\Tools\Scripts\2to3.py -w .

This generates some errors that can be ignored to run ShowHTMLDialog code under Python 3. After conversion, install comtypes using the same command as with Python 2.6:

C:\> python setup.py install

ShowHTMLDialog

ShowHTMLDialog is a Win32 function which creates a modal dialog box that displays HTML. In the context of a Python program targeting the Windows platform, it is an easy way to write a simple dialog box, such an About Box for example. ShowHTMLDialog() allows for some more advanced mechanisms like handling parameters and data entered in the dialog box, but this is not addressed in this article. ShowHTMLDialog() is implemented in MSHTML.DLL. This DLL contains related methods with slight differences: ShowHTMLDialogEx() and ShowModelessHTMLDialog(). Those two methods may address particular requirements that would not be met by ShowHTMLDialog (e.g. displaying a modeless dialog).

ShowHTMLDialog() takes 5 parameters:

  1. Handle to the parent of the dialog box
  2. Address of an IMoniker interface
  3. Address of VARIANT structure for the input data
  4. Dialog box options
  5. Address of Variant structure for the output data

For more details about those parameters consult the ShowHTMLDialog documentation. Using ctypes to invoke a basic version of a ShowHTMLDialog call can be implemented with the following lines of Python 3.1 code:

options = "dialogWidth:350px;dialogHeight:140px;center:yes;help:no"
moniker = POINTER(IUnknown)()
windll.urlmon.CreateURLMonikerEx(0, url, byref(moniker), 1)
windll.mshtml.ShowHTMLDialog(None, moniker, None, options, None)

url in the code example above is the full path of a file containing some HTML content. See the next section for a complete example.

Complete Example

This is a full example of working code demonstrating a simple usage of ShowHTMLDialog(). You will notice that in order to make it compliant with both Python 2.6 and Python 3.1, especially to handle url in Unicode format, there is the introduction of wstr allowing to call unicode() in Python 2.6 and str() in Python 3.1. str() is not necessary for Python 3.1, this is just for the purpose of this example and to maintain a unique file for this article.

"""ShowHTMLDialog

Creates a modal dialog box to display HTML (Win32).
Tested with Python 2.6 and Python 3.0

$Id: ShowHTMLDialog.py 540 2009-07-01 00:46:57Z andre $

"""

from ctypes import windll, byref, POINTER
from comtypes import IUnknown
import os
import tempfile
import sys

# From urlmon.h
URL_MK_UNIFORM = 1

# Dialog box properties
DLG_OPTIONS = "dialogWidth:350px;dialogHeight:140px;center:yes;help:no"

# HTML content
HTML_DLG = """
<html>
<head>
<title>ShowHTMLDialog in Python %(python_ver)s</title>
</head>
</script>
<body bgcolor="lightyellow">
<center>
<br/>
<p>
Simple example demonstrating the usage of<br/>
<b>ShowHTMLDialog</b><br/>
with <a href="http://www.python.org/" target="_blank">Python</a> %(python_ver)s
 and <a href="http://starship.python.net/crew/theller/ctypes/" target="_blank">
ctypes</a>.
</p>
<input type="button" value="OK" onClick="window.close();" />
</center>
</body>
</html>""" % {'python_ver': sys.version.split()[0] }

# Create temp HTML file
def create_html_file(html):
  """Create temporary HTML file from HTML template."""
  tmp_fd, url = tempfile.mkstemp(suffix='.html')
  tmp_file = os.fdopen(tmp_fd, 'w')
  tmp_file.write(html)
  tmp_file.close()
  return url

def show_html_dialog(url, dlg_options):
  """Prepare moniker. Invoke ShowHTMLDialog."""

  # Helper for Python 2.6 and 3.0 compatibility
  if sys.version_info > (3, 0):
    wstr = str
  else:
    wstr = unicode

  moniker = POINTER(IUnknown)()
  windll.urlmon.CreateURLMonikerEx(0, wstr(url),
                                   byref(moniker), URL_MK_UNIFORM)

  windll.mshtml.ShowHTMLDialog(None, moniker, None, wstr(dlg_options), None)

if __name__ == '__main__':
  show_html_dialog(create_html_file(HTML_DLG), DLG_OPTIONS)

Release Notes

  • July, 23 2009: Initial publication of this article