[pygtk] Embedding a Win32 window or ActiveX control in a pygtk application

Alif Wahid alif.wahid at gmail.com
Thu Jun 9 11:01:44 WST 2005


for the "Enter" key, you can import gtk.keysyms module, which comes
with PyGtk. that has all the constants defined for keys. i tried you
code with gtk.keysyms.Return in place of that numeric constant you
used and it worked!

alif.

On 6/9/05, Richie Hindle <richie at entrian.com> wrote:
> 
> [Guillaume]
> > I don't remember all details but I did embed a Flash file into a GTK
> > window some time ago:
> > [...]
> > axcontainer=gtk.DrawingArea()
> 
> Aha!  Parenting the control to a DrawingArea was the step I was missing.
> Thanks!
> 
> I've now got this working, and an example application (a poor man's webbrowser,
> embedding IE in pygtk via AtlAxWin and ctypes) is below.  There are a few things
> I couldn't make work:
> 
>  o My keyboard accelerator (Alt+A to focus the address box) doesn't work
>    when IE has the focus.  Any ideas?  How do pygtk accelerators work under the
>    surface?
> 
>  o Clicking a Gtk control when the IE control has the focus doesn't focus
>    the Gtk control.  I worked around this by putting an event handler on the
>    Gtk controls for "button-press-event", but it would need to be done for
>    every Gtk control - is there a better solution?
> 
>  o IE's accelerator keys (eg. Tab and Alt+Left) don't work.  In a pure Win32
>    app, I'd fix this by calling IOleInPlaceActiveObject::TranslateAccelerator()
>    in the message pump, but can I get access to the message pump in pygtk?
> 
>  o Pressing Enter in the address box should have the same effect as pressing
>    the Go button - I've done this, but it's a hack.  Is there a better way?
> 
>  o I'm using 65293 as the code for the Enter key - does pygtk have a constant
>    for this?
> 
> This is my first pygtk program, so any criticism or suggestions will be
> gratefully received!
> 
> -------------------------------- snip snip --------------------------------
> 
> """A poor man's webbrowser, embedding IE in pygtk via AtlAxWin and ctypes."""
> 
> import win32con
> 
> from ctypes import *
> from ctypes.wintypes import *
> from ctypes.com import IUnknown
> from ctypes.com.automation import IDispatch, VARIANT
> from ie6_gen import IWebBrowser2  # Copy ie6_gen from ctypes\win32\com\samples
> kernel32 = windll.kernel32
> user32 = windll.user32
> atl = windll.atl                  # If this fails, you need atl.dll
> 
> import pygtk
> pygtk.require("2.0")
> import gtk
> 
> class GUI:
>     def __init__(self):
>         # Create the main GTK window.
>         self.main = gtk.Window(gtk.WINDOW_TOPLEVEL)
>         self.main.set_title("Poor man's browser [TM]")
>         self.main.connect("destroy", gtk.main_quit)
>         self.main.set_size_request(750, 550)
>         self.main.realize()
> 
>         # Create a VBox to house the address bar and the IE control.
>         self.mainVBox = gtk.VBox()
>         self.main.add(self.mainVBox)
>         self.mainVBox.show()
> 
>         # Create the address bar.
>         self.addressEntry = gtk.Entry()
>         self.addressEntry.show()
>         self.addressEntry.connect("key-press-event", self.on_addressEntry_key)
>         self.addressLabel = gtk.Label()
>         self.addressLabel.set_text_with_mnemonic("_Address: ")
>         self.addressLabel.set_mnemonic_widget(self.addressEntry)
>         self.addressLabel.show()
>         self.goButton = gtk.Button("  Go  ")
>         self.goButton.show()
>         self.goButton.connect("clicked", self.on_goButton_clicked)
>         self.addressHbox = gtk.HBox()
>         self.addressHbox.show()
>         self.addressHbox.add(self.addressLabel)
>         self.addressHbox.add(self.addressEntry)
>         self.addressHbox.add(self.goButton)
>         self.addressHbox.set_child_packing(self.addressLabel,
>                                            False, True, 2, gtk.PACK_START)
>         self.addressHbox.set_child_packing(self.goButton,
>                                            False, True, 0, gtk.PACK_END)
>         self.mainVBox.add(self.addressHbox)
>         self.mainVBox.set_child_packing(self.addressHbox,
>                                         False, True, 0, gtk.PACK_START)
> 
>         # Create a DrawingArea to host IE and add it to the hbox.
>         self.container = gtk.DrawingArea()
>         self.mainVBox.add(self.container)
>         self.container.show()
> 
>         # Make the container accept the focus and pass it to the control;
>         # this makes the Tab key pass focus to IE correctly.
>         self.container.set_property("can-focus", True)
>         self.container.connect("focus", self.on_container_focus)
> 
>         # Resize the AtlAxWin window with its container.
>         self.container.connect("size-allocate", self.on_container_size)
> 
>         # Create an instance of IE via AtlAxWin.
>         atl.AtlAxWinInit()
>         hInstance = kernel32.GetModuleHandleA(None)
>         parentHwnd = self.container.window.handle
>         self.atlAxWinHwnd = \
>             user32.CreateWindowExA(0, "AtlAxWin", "http://www.pygtk.org",
>                             win32con.WS_VISIBLE | win32con.WS_CHILD |
>                             win32con.WS_HSCROLL | win32con.WS_VSCROLL,
>                             0, 0, 100, 100, parentHwnd, None, hInstance, 0)
> 
>         # Get the IWebBrowser2 interface for the IE control.
>         pBrowserUnk = POINTER(IUnknown)()
>         atl.AtlAxGetControl(self.atlAxWinHwnd, byref(pBrowserUnk))
>         self.pBrowser = POINTER(IWebBrowser2)()
>         pBrowserUnk.QueryInterface(byref(IWebBrowser2._iid_),
>                                    byref(self.pBrowser))
> 
>         # Create a Gtk window that refers to the native AtlAxWin window.
>         self.gtkAtlAxWin = gtk.gdk.window_foreign_new(long(self.atlAxWinHwnd))
> 
>         # By default, clicking a GTK widget doesn't grab the focus away from
>         # a native Win32 control.
>         self.addressEntry.connect("button-press-event", self.on_widget_click)
> 
>     def on_goButton_clicked(self, widget):
>         v = byref(VARIANT())
>         self.pBrowser.Navigate(self.addressEntry.get_text(), v, v, v, v)
> 
>     def on_addressEntry_key(self, widget, event):
>         if event.keyval == 65293:   # "Enter"; is there a constant for this?
>             self.on_goButton_clicked(None)
> 
>     def on_widget_click(self, widget, data):
>         self.main.window.focus()
> 
>     def on_container_size(self, widget, sizeAlloc):
>         self.gtkAtlAxWin.move_resize(0, 0, sizeAlloc.width, sizeAlloc.height)
> 
>     def on_container_focus(self, widget, data):
>         # Pass the focus to IE.  First get the HWND of the IE control; this
>         # is a bit of a hack but I couldn't make IWebBrowser2._get_HWND work.
>         rect = RECT()
>         user32.GetWindowRect(self.atlAxWinHwnd, byref(rect))
>         ieHwnd = user32.WindowFromPoint(POINT(rect.left, rect.top))
>         user32.SetFocus(ieHwnd)
> 
> # Show the main window and run the message loop.
> gui = GUI()
> gui.main.show()
> gtk.main()
> 
> -------------------------------- snip snip --------------------------------
> 
> --
> Richie Hindle
> richie at entrian.com
> 
> _______________________________________________
> pygtk mailing list   pygtk at daa.com.au
> http://www.daa.com.au/mailman/listinfo/pygtk
> Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/
> 


-- 
"Heaven is the peaceful place on earth...New Zealand."
     -- Alif Wahid.


More information about the pygtk mailing list