如何在Gtk3中获取DrawingArea窗口句柄?
我在CEF Python 3上找到了这段代码(链接)
...
self.container = gtk.DrawingArea()
self.container.set_property('can-focus', True)
self.container.connect('size-allocate', self.OnSize)
self.container.show()
...
windowID = self.container.get_window().handle
windowInfo = cefpython.WindowInfo()
windowInfo.SetAsChild(windowID)
self.browser = cefpython.CreateBrowserSync(windowInfo,
browserSettings={},
navigateUrl=GetApplicationPath('example.html'))
...
这段代码中的self.container.get_window().handle在PyGI和GTK3中不起作用。
我想把这段代码从GTK2移植到GTK3,我该怎么做呢?
编辑:
经过一些搜索,我找到一个小窍门可以让get_window工作:我在调用self.container.get_window()之前,先调用self.container.realize()。但是我还是无法获取窗口句柄。
我需要把CEF3窗口放在一个DrawingArea或者其他元素里面。我该如何用PyGI做到这一点呢?
编辑:
我的环境是:
Windows 7
Python 2.7和Python 3.2
3 个回答
这个回答建议你使用 .handle
或 .get_xid()
,在 GTK2 上是有效的,但在 GTK3 或 Windows 系统上就不行了,这正是你提问的内容。
我查了很多资料,发现 GTK3 中有一个函数可以满足你的需求:gdk_win32_window_get_handle
,但遗憾的是,它在 gi 绑定中不可用。你可以尝试使用 ctypes 或 Cython 来访问这个函数(这也是我打算做的)。
你首先需要导入 GdkX11
,这样在返回的 GdkX11Window
上才能使用 get_xid()
这个功能。
from gi.repository import GdkX11
...
-windowID = self.container.get_window().handle
+windowID = self.container.get_window().get_xid()
很遗憾,目前在Python的gobject introspection方面没有进展,无法修复这个问题,也无法使用gdk_win32_window_get_handle
(我很早之前在gnome的bug追踪器上报告了这个问题)——这个功能对于Python GStreamer和Windows来说是非常需要的……
所以我按照totaam的建议,使用ctypes来访问gdk_win32_window_get_handle。这个过程花了我很长时间,因为我之前没有这方面的经验——而且这方法有点笨拙——但有时候就是需要这样做……
以下是代码:
Gdk.threads_enter()
#get the gdk window and the corresponding c gpointer
drawingareawnd = drawingarea.get_property("window")
#make sure to call ensure_native before e.g. on realize
if not drawingareawnd.has_native():
print("Your window is gonna freeze as soon as you move or resize it...")
ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object]
drawingarea_gpointer = ctypes.pythonapi.PyCapsule_GetPointer(drawingareawnd.__gpointer__, None)
#get the win32 handle
gdkdll = ctypes.CDLL ("libgdk-3-0.dll")
hnd = gdkdll.gdk_win32_window_get_handle(drawingarea_gpointer)
#do what you want with it ... I pass it to a gstreamer videosink
Gdk.threads_leave()