使用Python 3发送WM_COPYDATA

时间:2013-11-10 05:36:49

标签: python python-3.3 wm-copydata

我正在尝试编写一个与我的stickies副本交互的python脚本。我在Python与WM_COPYDATA结构的交互方式上遇到了麻烦,遗憾的是我无法在线找到很多例子。

使用代码:

import struct
import win32con
import win32gui

import struct, array
int_buffer = array.array("L", [0])
char_buffer = array.array('b', 'do new sticky')
int_buffer_address = int_buffer.buffer_info()[0]
char_buffer_address, char_buffer_size = char_buffer.buffer_info

copy_struct = struct.pack("pLp",
int_buffer_address,
char_buffer_size, char_buffer_address)

hwnd = win32gui.FindWindow("ZhornSoftwareStickiesMain", None)

win32gui.SendMessage(w, WM_COPYDATA, hwnd, copy_struct)

我收到以下错误:

C:\Users\%userprofile%\Desktop>python sender.py
Traceback (most recent call last):
  File "sender.py", line 7, in <module>
    char_buffer = array.array('b', 'do new sticky')
TypeError: an integer is required

我似乎无法弄清楚为什么我会收到这样的错误。有什么想法吗?

修改:部分正常运行的代码

import struct
import win32con
import win32gui
import struct, array


int_buffer = array.array("L", [0])
char_buffer = array.array('b', b"do manage open")
int_buffer_address = int_buffer.buffer_info()[0]

# Add () to buffer_info to call it.
char_buffer_address, char_buffer_size = char_buffer.buffer_info()

# Need P  type for the addresses.
copy_struct = struct.pack("PLP",int_buffer_address,char_buffer_size, char_buffer_address)

hwnd = win32gui.FindWindow(None, "ZhornSoftwareStickiesMain")
win32gui.SendMessage(hwnd, win32con.WM_COPYDATA, None, copy_struct)

2 个答案:

答案 0 :(得分:3)

使用ctypes更容易。此代码已使用简单的Delphi应用程序进行测试,该应用程序接收并显示通过WM_COPYDATA发送的字符串。

import win32con
import ctypes
import ctypes.wintypes

FindWindow = ctypes.windll.user32.FindWindowW
SendMessage = ctypes.windll.user32.SendMessageW

class COPYDATASTRUCT(ctypes.Structure):
    _fields_ = [
        ('dwData', ctypes.wintypes.LPARAM),
        ('cbData', ctypes.wintypes.DWORD),
        ('lpData', ctypes.c_wchar_p) 
        #formally lpData is c_void_p, but we do it this way for convenience
    ]

hwnd = FindWindow('TheNameOfMyWindowClass', None)
cds = COPYDATASTRUCT()
cds.dwData = 0
str = 'boo'
cds.cbData = ctypes.sizeof(ctypes.create_unicode_buffer(str))
cds.lpData = ctypes.c_wchar_p(str)

SendMessage(hwnd, win32con.WM_COPYDATA, 0, ctypes.byref(cds))

这假设接收方需要UTF-16编码的有效负载。如果收件人期望ANSI编码的有效负载,那么您需要使用此变体。

import win32con
import ctypes
import ctypes.wintypes

FindWindow = ctypes.windll.user32.FindWindowW
SendMessage = ctypes.windll.user32.SendMessageW

class COPYDATASTRUCT(ctypes.Structure):
    _fields_ = [
        ('dwData', ctypes.wintypes.LPARAM),
        ('cbData', ctypes.wintypes.DWORD),
        ('lpData', ctypes.c_char_p)
        #formally lpData is c_void_p, but we do it this way for convenience
]

hwnd = FindWindow('TheNameOfMyWindowClass', None)
cds = COPYDATASTRUCT()
cds.dwData = 0
str = b'boo'
cds.cbData = ctypes.sizeof(ctypes.create_string_buffer(str))
cds.lpData = ctypes.c_char_p(str)

SendMessage(hwnd, win32con.WM_COPYDATA, 0, ctypes.byref(cds))

现在,查看您发布的Stickies链接,您需要使用ANSI变体。如果要接收通知,则需要在SendMessage调用中传递窗口句柄,而不是如上所述。

答案 1 :(得分:2)

在Python 3中,字符串是Unicode。尝试使用字节字符串:

>>> import array
>>> array.array('b',b'do new sticky')
array('b', [100, 111, 32, 110, 101, 119, 32, 115, 116, 105, 99, 107, 121])

还有一些其他变化:

import struct, array
int_buffer = array.array("L", [0])
char_buffer = array.array('b', b'do new sticky')
int_buffer_address = int_buffer.buffer_info()[0]

# Add () to buffer_info to call it.
char_buffer_address, char_buffer_size = char_buffer.buffer_info()

# Need P  type for the addresses.
copy_struct = struct.pack("PLP",int_buffer_address,char_buffer_size, char_buffer_address)

我没有安装软件,但我认为下一行应该是:

hwnd = win32gui.FindWindow(None, "ZhornSoftwareStickiesMain")
win32gui.SendMessage(hwnd, win32con.WM_COPYDATA, None, copy_struct)

修改

我安装了软件。最初我无法使用任何命令,但API文档中不清楚的技巧是每个字符串必须以api开头:

import struct
import win32con
import win32gui
import array

char_buffer = array.array('B', b'api do new sticky hello, world')
char_buffer_address, char_buffer_size = char_buffer.buffer_info()
copy_struct = struct.pack("PLP", 12345, char_buffer_size, char_buffer_address)
hwnd = win32gui.FindWindow(None, "ZhornSoftwareStickiesMain")
win32gui.SendMessage(hwnd, win32con.WM_COPYDATA, None, copy_struct)

Stickies sample