Printing frameworks and wxPython

As hard as I have tried to find, there's no good printing framework for wxPython. wxEasyPrinting sucks so much for anything more then simple text (for example, the table cells don't support specifying a height). Generating PDF files with a toolkit such as ReportLab (even with Platypus) is harder then it should be, especially when there's no ready made higher level framework. This page explores some of the common printing solutions on Windows.

My own solution to all these is a single-platform hack. Based on my previous experience of creating a "zope based desktop application" using an embeded Internet Explorer, I'm using Internet Explorer through ActiveX as a rendering and print preview engine. Building a new "form" is easy with any HTML GUI builder such as NVU or Dreamweaver and SimpleTAL bridges the gap between the application data and the presentation for printing. The trick is to display only the Print Preview dialog, which can't be done without going through Internet Explorer's back door.

In my generated HTML files I have the following snippet, which automatically calls the Print Preview dialog from Internet Explorer when the file is loaded.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script>
function printpr()
{
var OLECMDID = 7;
/* OLECMDID values:
* 6 - print
* 7 - print preview
* 1 - open window
* 4 - Save As
*/
var PROMPT = 1; // 2 DONTPROMPTUSER
var WebBrowser = "<OBJECT ID='WebBrowser1' WIDTH=0 HEIGHT=0 CLASSID='CLSID:8856F961-340A-11D0-A96B-00C04FD705A2' />";
document.body.insertAdjacentHTML('beforeEnd', WebBrowser);
WebBrowser1.ExecWB(OLECMDID, PROMPT);
WebBrowser1.outerHTML = "";
}
</script>
</head>
<body onload="printpr(); return false;">
</body>
</html>

Next, I have a frame with the IE ActiveX control embeded.

# -*- coding: ISO-8859-1 -*-
# generated by wxGlade 0.4.1 on Sun Apr 30 20:43:52 2006

import wx
import wx.lib.iewin as iewin

# begin wxGlade: dependencies
# end wxGlade

def ieWidget(parent, id):
ie = iewin.IEHtmlWindow(parent, -1)
return ie

class dlgIEFrame(wx.Frame):
def __init__(self, *args, **kwds):
# begin wxGlade: dlgIEFrame.__init__
kwds["style"] = wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.window_4 = ieWidget(self, -1)

self.__set_properties()
self.__do_layout()
# end wxGlade
self.ie = self.window_4
self.ie.SetClientSizeWH(300, 400)

def __set_properties(self):
# begin wxGlade: dlgIEFrame.__set_properties
self.SetTitle("frame_1")
self.SetSize((792, 755))
# end wxGlade

def __do_layout(self):
# begin wxGlade: dlgIEFrame.__do_layout
sizer_59 = wx.BoxSizer(wx.VERTICAL)
sizer_59.Add(self.window_4, 1, wx.EXPAND, 0)
self.SetAutoLayout(True)
self.SetSizer(sizer_59)
self.Layout()
self.Centre()
# end wxGlade

# end of class dlgIEFrame

To display the printing dialog I'm just dumping the generated HTML file to a temporary file and loading it into the IE control.

Comments