我试图从Python中读取WM_COPYDATA
消息,一些应用程序(我正在尝试使用Spotify)发送到WindowsLiveMessenger来更新“我正在听的......”这句话。
根据我的能力,WM_COPYDATA
消息来自COPYDATASTRUCT
,具有以下结构:
dwData
在我们的案例中为0x547,以便它可以访问立即监听功能cbData
收到字符串的长度lpData
带有指向字符串本身的指针,可能包含Unicode字符字符串应采用以下格式:ListeningNowTracker
所述的\0Music\0status\0format\0song\0artist\0album\0
我们在WM_COPYDATA
事件中收到的内容是包含lParam
的{{1}}指针。
我开始修补pywin32函数,我记得他们不接受过去经验中的Unicode字符,然后我切换到ctypes。尽管对我来说这是一个几乎全新的Python世界,但我尝试使用COPYDATASTRUCT
,我得到的只是我的未知对象或访问违规。
我认为代码应该创建POINTER()
:
COPYDATASTRUCT
然后让class CopyDataStruct(Structure):
_fields_ = [('dwData', c_int),
('cbData', c_int),
('lpData', c_void_p)]
成为指向该结构的指针,从lParam
获取字符串指针,最后得到lpData
的字符串。
任何提示?
更新1
ctypes.string_at(lpData,cbData)
事件是由WM_COPYDATA
构建的隐藏窗口收到的,仅用于此目的。 copydata事件连接到一个名为win32gui
的函数,这是它的标题:
OnCopyData
与Spy ++消息日志中的值相比,函数提供的值是正确的。
更新2
这应该接近我想要的,但是会给出NULL指针错误。
def OnCopyData(self, hwnd, msg, wparam, lparam):
答案 0 :(得分:5)
我写了以下简单的win32gui app:
import win32con, win32api, win32gui, ctypes, ctypes.wintypes
class COPYDATASTRUCT(ctypes.Structure):
_fields_ = [
('dwData', ctypes.wintypes.LPARAM),
('cbData', ctypes.wintypes.DWORD),
('lpData', ctypes.c_void_p)
]
PCOPYDATASTRUCT = ctypes.POINTER(COPYDATASTRUCT)
class Listener:
def __init__(self):
message_map = {
win32con.WM_COPYDATA: self.OnCopyData
}
wc = win32gui.WNDCLASS()
wc.lpfnWndProc = message_map
wc.lpszClassName = 'MyWindowClass'
hinst = wc.hInstance = win32api.GetModuleHandle(None)
classAtom = win32gui.RegisterClass(wc)
self.hwnd = win32gui.CreateWindow (
classAtom,
"win32gui test",
0,
0,
0,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
0,
0,
hinst,
None
)
print self.hwnd
def OnCopyData(self, hwnd, msg, wparam, lparam):
print hwnd
print msg
print wparam
print lparam
pCDS = ctypes.cast(lparam, PCOPYDATASTRUCT)
print pCDS.contents.dwData
print pCDS.contents.cbData
print ctypes.wstring_at(pCDS.contents.lpData)
return 1
l = Listener()
win32gui.PumpMessages()
然后我从另一个应用程序(用Delphi编写)发送了一个WM_COPYDATA
消息窗口:
Text := 'greetings!';
CopyData.cbData := (Length(Text)+1)*StringElementSize(Text);
CopyData.lpData := PWideChar(Text);
SendMessage(hwnd, WM_COPYDATA, Handle, NativeInt(@CopyData));
输出结果为:
461584
461584
74
658190
2620592
42
22
greetings!
所以看起来它很简单,就像你编码它一样。
我唯一能想到的是Spotify的COPYDATASTRUCT
中的文本不是以空值终止的。您应该能够通过读取数据来轻松检查。使用cbData
成员。