如何在Gtk3中获取DrawingArea窗口句柄?

5 投票
3 回答
2660 浏览
提问于 2025-04-18 02:24

我在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 个回答

0

这个回答建议你使用 .handle.get_xid(),在 GTK2 上是有效的,但在 GTK3 或 Windows 系统上就不行了,这正是你提问的内容。

我查了很多资料,发现 GTK3 中有一个函数可以满足你的需求:gdk_win32_window_get_handle,但遗憾的是,它在 gi 绑定中不可用。你可以尝试使用 ctypes 或 Cython 来访问这个函数(这也是我打算做的)。

0

你首先需要导入 GdkX11,这样在返回的 GdkX11Window 上才能使用 get_xid() 这个功能。

from gi.repository import GdkX11

...

-windowID = self.container.get_window().handle
+windowID = self.container.get_window().get_xid()
5

很遗憾,目前在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()

撰写回答