ShowHTMLDialog with Python and ctypes
This python recipe demonstrates how to use the Win32 ShowHTMLDialog()
with Python, ctypes
and comtypes
on Windows.
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
- 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 in the Python Package Index (PyPI)
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:
- Handle to the parent of the dialog box
- Address of an IMoniker interface
- Address of VARIANT structure for the input data
- Dialog box options
- 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