|
| 1 | +From here: |
| 2 | +http://www.daa.com.au/pipermail/pygtk/2005-June/010461.html |
| 3 | +(google cache) |
| 4 | + |
| 5 | +--------------------------------------------------------------------------------------------------------- |
| 6 | + |
| 7 | +To jest kopia z pamięci podręcznej Google adresu http://www.daa.com.au/pipermail/pygtk/2005-June/010461.html. Zdjęcie przedstawia stan strony z 4 Sie 2012 16:58:27 GMT. Aktualna strona może wyglądać inaczej. Więcej informacji |
| 8 | +Wskazówka: aby szybko znaleźć wyszukiwane hasło na stronie, naciśnij Ctrl+F lub ⌘-F (Mac) i użyj paska wyszukiwania. |
| 9 | + |
| 10 | +Wersja tekstowa |
| 11 | + |
| 12 | +[pygtk] Embedding a Win32 window or ActiveX control in a pygtk application |
| 13 | + |
| 14 | +Richie Hindle richie at entrian.com |
| 15 | +Thu Jun 9 07:23:41 WST 2005 |
| 16 | +Previous message: [pygtk] Embedding a Win32 window or ActiveX control in a pygtk application |
| 17 | +Next message: [pygtk] Embedding a Win32 window or ActiveX control in a pygtk application |
| 18 | +Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] |
| 19 | +[Guillaume] |
| 20 | +> I don't remember all details but I did embed a Flash file into a GTK |
| 21 | +> window some time ago: |
| 22 | +> [...] |
| 23 | +> axcontainer=gtk.DrawingArea() |
| 24 | + |
| 25 | +Aha! Parenting the control to a DrawingArea was the step I was missing. |
| 26 | +Thanks! |
| 27 | + |
| 28 | +I've now got this working, and an example application (a poor man's webbrowser, |
| 29 | +embedding IE in pygtk via AtlAxWin and ctypes) is below. There are a few things |
| 30 | +I couldn't make work: |
| 31 | + |
| 32 | + o My keyboard accelerator (Alt+A to focus the address box) doesn't work |
| 33 | + when IE has the focus. Any ideas? How do pygtk accelerators work under the |
| 34 | + surface? |
| 35 | + |
| 36 | + o Clicking a Gtk control when the IE control has the focus doesn't focus |
| 37 | + the Gtk control. I worked around this by putting an event handler on the |
| 38 | + Gtk controls for "button-press-event", but it would need to be done for |
| 39 | + every Gtk control - is there a better solution? |
| 40 | + |
| 41 | + o IE's accelerator keys (eg. Tab and Alt+Left) don't work. In a pure Win32 |
| 42 | + app, I'd fix this by calling IOleInPlaceActiveObject::TranslateAccelerator() |
| 43 | + in the message pump, but can I get access to the message pump in pygtk? |
| 44 | + |
| 45 | + o Pressing Enter in the address box should have the same effect as pressing |
| 46 | + the Go button - I've done this, but it's a hack. Is there a better way? |
| 47 | + |
| 48 | + o I'm using 65293 as the code for the Enter key - does pygtk have a constant |
| 49 | + for this? |
| 50 | + |
| 51 | +This is my first pygtk program, so any criticism or suggestions will be |
| 52 | +gratefully received! |
| 53 | + |
| 54 | +-------------------------------- snip snip -------------------------------- |
| 55 | + |
| 56 | +"""A poor man's webbrowser, embedding IE in pygtk via AtlAxWin and ctypes.""" |
| 57 | + |
| 58 | +import win32con |
| 59 | + |
| 60 | +from ctypes import * |
| 61 | +from ctypes.wintypes import * |
| 62 | +from ctypes.com import IUnknown |
| 63 | +from ctypes.com.automation import IDispatch, VARIANT |
| 64 | +from ie6_gen import IWebBrowser2 # Copy ie6_gen from ctypes\win32\com\samples |
| 65 | +kernel32 = windll.kernel32 |
| 66 | +user32 = windll.user32 |
| 67 | +atl = windll.atl # If this fails, you need atl.dll |
| 68 | + |
| 69 | +import pygtk |
| 70 | +pygtk.require("2.0") |
| 71 | +import gtk |
| 72 | + |
| 73 | +class GUI: |
| 74 | + def __init__(self): |
| 75 | + # Create the main GTK window. |
| 76 | + self.main = gtk.Window(gtk.WINDOW_TOPLEVEL) |
| 77 | + self.main.set_title("Poor man's browser [TM]") |
| 78 | + self.main.connect("destroy", gtk.main_quit) |
| 79 | + self.main.set_size_request(750, 550) |
| 80 | + self.main.realize() |
| 81 | + |
| 82 | + # Create a VBox to house the address bar and the IE control. |
| 83 | + self.mainVBox = gtk.VBox() |
| 84 | + self.main.add(self.mainVBox) |
| 85 | + self.mainVBox.show() |
| 86 | + |
| 87 | + # Create the address bar. |
| 88 | + self.addressEntry = gtk.Entry() |
| 89 | + self.addressEntry.show() |
| 90 | + self.addressEntry.connect("key-press-event", self.on_addressEntry_key) |
| 91 | + self.addressLabel = gtk.Label() |
| 92 | + self.addressLabel.set_text_with_mnemonic("_Address: ") |
| 93 | + self.addressLabel.set_mnemonic_widget(self.addressEntry) |
| 94 | + self.addressLabel.show() |
| 95 | + self.goButton = gtk.Button(" Go ") |
| 96 | + self.goButton.show() |
| 97 | + self.goButton.connect("clicked", self.on_goButton_clicked) |
| 98 | + self.addressHbox = gtk.HBox() |
| 99 | + self.addressHbox.show() |
| 100 | + self.addressHbox.add(self.addressLabel) |
| 101 | + self.addressHbox.add(self.addressEntry) |
| 102 | + self.addressHbox.add(self.goButton) |
| 103 | + self.addressHbox.set_child_packing(self.addressLabel, |
| 104 | + False, True, 2, gtk.PACK_START) |
| 105 | + self.addressHbox.set_child_packing(self.goButton, |
| 106 | + False, True, 0, gtk.PACK_END) |
| 107 | + self.mainVBox.add(self.addressHbox) |
| 108 | + self.mainVBox.set_child_packing(self.addressHbox, |
| 109 | + False, True, 0, gtk.PACK_START) |
| 110 | + |
| 111 | + # Create a DrawingArea to host IE and add it to the hbox. |
| 112 | + self.container = gtk.DrawingArea() |
| 113 | + self.mainVBox.add(self.container) |
| 114 | + self.container.show() |
| 115 | + |
| 116 | + # Make the container accept the focus and pass it to the control; |
| 117 | + # this makes the Tab key pass focus to IE correctly. |
| 118 | + self.container.set_property("can-focus", True) |
| 119 | + self.container.connect("focus", self.on_container_focus) |
| 120 | + |
| 121 | + # Resize the AtlAxWin window with its container. |
| 122 | + self.container.connect("size-allocate", self.on_container_size) |
| 123 | + |
| 124 | + # Create an instance of IE via AtlAxWin. |
| 125 | + atl.AtlAxWinInit() |
| 126 | + hInstance = kernel32.GetModuleHandleA(None) |
| 127 | + parentHwnd = self.container.window.handle |
| 128 | + self.atlAxWinHwnd = \ |
| 129 | + user32.CreateWindowExA(0, "AtlAxWin", "http://www.pygtk.org", |
| 130 | + win32con.WS_VISIBLE | win32con.WS_CHILD | |
| 131 | + win32con.WS_HSCROLL | win32con.WS_VSCROLL, |
| 132 | + 0, 0, 100, 100, parentHwnd, None, hInstance, 0) |
| 133 | + |
| 134 | + # Get the IWebBrowser2 interface for the IE control. |
| 135 | + pBrowserUnk = POINTER(IUnknown)() |
| 136 | + atl.AtlAxGetControl(self.atlAxWinHwnd, byref(pBrowserUnk)) |
| 137 | + self.pBrowser = POINTER(IWebBrowser2)() |
| 138 | + pBrowserUnk.QueryInterface(byref(IWebBrowser2._iid_), |
| 139 | + byref(self.pBrowser)) |
| 140 | + |
| 141 | + # Create a Gtk window that refers to the native AtlAxWin window. |
| 142 | + self.gtkAtlAxWin = gtk.gdk.window_foreign_new(long(self.atlAxWinHwnd)) |
| 143 | + |
| 144 | + # By default, clicking a GTK widget doesn't grab the focus away from |
| 145 | + # a native Win32 control. |
| 146 | + self.addressEntry.connect("button-press-event", self.on_widget_click) |
| 147 | + |
| 148 | + def on_goButton_clicked(self, widget): |
| 149 | + v = byref(VARIANT()) |
| 150 | + self.pBrowser.Navigate(self.addressEntry.get_text(), v, v, v, v) |
| 151 | + |
| 152 | + def on_addressEntry_key(self, widget, event): |
| 153 | + if event.keyval == 65293: # "Enter"; is there a constant for this? |
| 154 | + self.on_goButton_clicked(None) |
| 155 | + |
| 156 | + def on_widget_click(self, widget, data): |
| 157 | + self.main.window.focus() |
| 158 | + |
| 159 | + def on_container_size(self, widget, sizeAlloc): |
| 160 | + self.gtkAtlAxWin.move_resize(0, 0, sizeAlloc.width, sizeAlloc.height) |
| 161 | + |
| 162 | + def on_container_focus(self, widget, data): |
| 163 | + # Pass the focus to IE. First get the HWND of the IE control; this |
| 164 | + # is a bit of a hack but I couldn't make IWebBrowser2._get_HWND work. |
| 165 | + rect = RECT() |
| 166 | + user32.GetWindowRect(self.atlAxWinHwnd, byref(rect)) |
| 167 | + ieHwnd = user32.WindowFromPoint(POINT(rect.left, rect.top)) |
| 168 | + user32.SetFocus(ieHwnd) |
| 169 | + |
| 170 | +# Show the main window and run the message loop. |
| 171 | +gui = GUI() |
| 172 | +gui.main.show() |
| 173 | +gtk.main() |
| 174 | + |
| 175 | +-------------------------------- snip snip -------------------------------- |
| 176 | + |
| 177 | +-- |
| 178 | +Richie Hindle |
| 179 | +richie at entrian.com |
| 180 | + |
| 181 | +Previous message: [pygtk] Embedding a Win32 window or ActiveX control in a pygtk application |
| 182 | +Next message: [pygtk] Embedding a Win32 window or ActiveX control in a pygtk application |
| 183 | +Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] |
| 184 | +More information about the pygtk mailing list |
0 commit comments