如何将C语言中的结构转换为pywin32?

0 投票
1 回答
958 浏览
提问于 2025-04-16 02:02

我正在尝试通过 SendMessage 使用 TTM_GETTEXT,这是在 pywin32 中的一个功能。问题是,lparam 的结构需要是 TOOLINFO,这个结构在 MSDN 上有详细的说明,但在 pywin32 中没有对应的实现。我想知道有没有办法用 Python 和 pywin32 创建相同的结构?

编辑:这是我用 ctypes 写的代码。我为 TOOLINFO 创建了一个 Structure,然后从中生成一个缓冲区,以便传递给 pywin32 的 SendMessage,最后又把它转换回 TOOLINFOctypes Structure。唯一的问题是,这个方法没有成功:

# My TOOLINFO struct:
class TOOLINFO(Structure):
  _fields_ = [("cbSize", UINT),
              ("uFlags", UINT),
              ("hwnd", HWND),
              ("uId", POINTER(UINT)),
              ("rect", RECT),
              ("hinst", HINSTANCE),
              ("lpszText", LPWSTR),
              ("lpReserved", c_void_p)]

# send() definition from PythonInfo wiki FAQs
def send(self):
  return buffer(self)[:]

ti = TOOLINFO()
text = ""
ti.cbSize = sizeof(ti)
ti.lpszText = text                 # buffer to store text in
ti.uId = pointer(UINT(wnd))        # wnd is the handle of the tooltip
ti.hwnd = w_wnd                    # w_wnd is the handle of the window containing the tooltip
ti.uFlags = commctrl.TTF_IDISHWND  # specify that uId is the control handle
ti_buffer = send(ti)               # convert to buffer for pywin32

del(ti)

win32gui.SendMessage(wnd, commctrl.TTM_GETTEXT, 256, ti_buffer)

ti = TOOLINFO()              # create new TOOLINFO() to copy result to

# copy result (according to linked article from Jeremy)
memmove(addressof(ti), ti_buffer, sizeof(ti))

if ti.lpszText:
  print ti.lpszText          # print any text recovered from the tooltip

文本没有被打印出来,但我认为它应该包含我想从工具提示中提取的文本。我在使用 ctypes 的时候是不是哪里出错了?我很确定我的 wndw_wnd 的值是正确的,所以我一定是做错了什么。

1 个回答

1

这虽然看起来不太美观,但你可以使用 struct 模块把字段打包成一个字符串,并且可以设置合适的字节序、对齐方式和填充。这个过程有点复杂,因为你需要用一个格式字符串来定义结构,格式字符串里只能用对应的基本数据类型,并且要按正确的顺序排列。

你也可以使用 ctypes 来定义结构类型,或者直接与 DLL 进行交互(而不是使用 pywin32)。ctypes 的结构定义更接近 C 语言的定义,所以你可能会觉得这样更好用。

如果你选择在使用 pywin32 的同时使用 ctypes 来定义结构,下面的链接可以给你一些关于如何将结构序列化为字符串的提示: 如何使用 ctypes 进行打包和解包 (结构 <-> 字符串)

撰写回答