WxPython 2.8.8.0 quietly introduces true ActiveX hosting for Windows

Version 2.8.8.0 of WxPython uses the new activex class to host ActiveX controls on Windows. This means that unlike previous implementations of the wrapper for the IE HTML ActiveX control, this version has full access to the browser events and DOM.

This is a huge advance for Windows GUI programming with WxPython. Now WxPython applications on Windows can host an IE window, and control the contents programmatically via the document property.

The WxPython team has been pretty quiet about it. The changes don't seem to have made it into the docs (although they're mentioned in the change log and the sample code has been updated).

Here's a simple example of a dialog box with an HTML window. The dialog intercepts clicks on the links, and uses them to set the color of the text by accessing its css property.

#coding: UTF8
"""
ColorWindow

Demonstrates controlling DOM of IEHtmlWindow
"""

import wx
from wx.lib import iewin
from wx.lib import sized_controls as sc

HTML_DOCUMENT = u"""<html>
    <body>
        <p id="
text">Change the color of the text</p>
        <p>Actions:</p>
        <ul>
            <li><a href="
/red">Make it red</a></li>
            <li><a href="
/blue">Make it blue</a></li>
            <li><a href="
/green">Make it green</a></li>
        </ul>
    </body>
</html>"
""

class ColorWindow(sc.SizedDialog):
    """Hosts an IEHtmlWindow, and responds to clicks on links
    by setting the color of the text.
    "
""

    def __init__(self, parent):
        self.ie = None
        flag = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER
        sc.SizedDialog.__init__(self,
                           parent,
                           -1,
                           "Color Window",
                           style=flag,
                           size=(300,300))

        self.layout()

    def layout(self):
        """Performs the layout of GUI widgets"""

        pane = self.GetContentsPane()

        self.ie = iewin.IEHtmlWindow(pane)
        self.ie.SetSizerProps(expand=True, proportion=1)
        self.ie.LoadString(HTML_DOCUMENT)
        self.ie.AddEventSink(self)

        self.SetButtonSizer(self.CreateStdDialogButtonSizer(wx.OK))
        pane.Fit()

    def BeforeNavigate2(self, this, pDisp, URL, Flags,
                        TargetFrameName, PostData, Headers,
                        Cancel):
        """
        This is a callback from the HTML window before
        navigating to a clicked link. We'll use it to set the
        color, then cancel.
        "
""

        color = URL[0].split("/")[-1]

        elem = self.ie.document.getElementById("text")
        elem.style.cssText = "color: %s;" % color
        # cancel it so it doesn't actually try to navigate there
        Cancel[0] = True

if __name__ == '__main__':
    application = wx.PySimpleApp()

    window = ColorWindow(None)
    window.ShowModal()
    window.Destroy()

    application.MainLoop()

Here's the code (htmlwin.zip).

The method BeforeNavigate2 intercepts clicks on links, and uses the link information to get the desired color. Then it finds the element in the DOM with an id of "text", and sets that element's color to the link color.

The possibilities of this technique are huge. Although it has the disadvantage of tying you to Windows, if your application is going to be Windows-only anyway, it lets you write an application with many of the benefits of a Web app, and very few of the drawbacks.

Here's a screenshot of the above code in action:
Screenshot of the HTML dialog

Comments

  1. August 22nd, 2008| 1:49 am

    Very interesting info … thanks for posting it.

    I can imagine the uses this can be put to - apps with web content in the component, etc …

    Now if only that was possible using Firefox instead of, or in addition to, IE … would be even better.

    - Vasudev Ram

  2. August 22nd, 2008| 9:08 am

    I very much agree about the Firefox browser. This would also allow a cross-platform solution.

    There is wxMozilla, but it appears to have been abandoned.

  3. astigmatik
    August 28th, 2008| 3:29 pm

    I wouldn’t use this. Python is multi-platform. WxPython SHOULD work towards being more multi-platform.

  4. August 28th, 2008| 3:40 pm

    @astigmatik

    Being multi-platform is a great goal — but I like having the choice. Having a multi-platform solution would be better, but I’ll take this for now!

    Or put it this way: until now, people developing a Windows application and needing ActiveX would have had to turn to an alternative (such as IronPython or native Win32 in Python). This support is going to actually increase the population of WxPython programmers, which is a good thing.

Leave a reply