ShowHTMLDialog with Python and ctypes

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

HTML dialog screenshot

As for a recent post, I initially published this recipe in the, now defunct, ctypes wiki. 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

  • Python 2.6 or 3.1 on windows
  • ctypes created by Thomas Heller is included in the above versions of Python
  • comypes also created by Thomas is available as a separate library and hosted on Sourceforge. For the purpose of this article, comtypes version 0.6.0 available as a binary did not work, therefore I checked out the source code from Subversion.

Install comtypes

After checking out the code from the Sourceforge subversion repository, installing comtypes with Python 2.6 is straight forward. In the comtypes working directory, simply execute:

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 a conversion script named 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:

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:

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 MSDN ShowHTMLDialog web page. 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)

Resources

Release Notes

  • July, 23 2009: Initial publication of this blog post.
Go Top
comments powered by Disqus