在Python中接收WM_COPYDATA [英] Receiving WM_COPYDATA in Python

查看:414
本文介绍了在Python中接收WM_COPYDATA的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从Python中读取某些应用程序(我正在尝试使用Spotify)发送给WindowsLiveMessenger的 WM_COPYDATA 消息,以更新我正在听的内容。 ..短语。

I am trying to read from Python the WM_COPYDATA message some applications (I'm trying with Spotify) send to WindowsLiveMessenger to update the "What I'm listening to..." phrase.

根据我的发现, WM_COPYDATA 消息出现在 COPYDATASTRUCT 具有以下结构:

From what I have been able to find, WM_COPYDATA messages come in a COPYDATASTRUCT with the following structure:


  • dwData 在我们的示例中为0x547,以便它使用接收到的字符串的长度

  • cbData 来访问立即监听功能

  • lpData 带有指向字符串本身的指针,可能包含Unicode字符

  • dwData in our case 0x547 so that it access the listening now feature
  • cbData with the length of the string received
  • lpData with a pointer to the string itself, may include Unicode characters

字符串应具有以下格式: \0Music\0status\0format\0song\0artist\0album\0 如前所述通过 ListeningNowTracker

The string should have the following format: \0Music\0status\0format\0song\0artist\0album\0 as stated by ListeningNowTracker

我们在 WM_COPYDATA 事件是 lParam 的指针,其中包含 COPYDATASTRUCT

What we receive in a WM_COPYDATA event is a pointer for lParam that contains the COPYDATASTRUCT.

我开始修改pywin32函数,并记得他们不接受以往经验的Unicode字符,然后我改用了ctypes。尽管对于我来说,这对Python来说几乎是一个新世界,但我还是尝试了 POINTER(),对我来说,我得到的只是未知对象或访问冲突。

I started tinkering with pywin32 functions and I remembered that they do not accept Unicode characters from past experience, then I switched to ctypes. Despite this being an almost new world in Python for me, I tried with POINTER() and all I got was unknown objects for me or access violations.

我认为代码应创建 COPYDATASTRUCT

class CopyDataStruct(Structure):
    _fields_ = [('dwData', c_int),
                ('cbData', c_int),
                ('lpData', c_void_p)]

然后将 lParam 用作指针到该结构,从 lpData 获取字符串指针,最后使用 ctypes.string_at(lpData,cbData)获取字符串。

Then make the lParam be a pointer to that structure, get the string pointer from lpData and finally get the string with ctypes.string_at(lpData,cbData).

有什么提示吗?

更新1

WM_COPYDATA 事件由使用 win32gui 生成的隐藏窗口接收。 copydata事件连接到名为 OnCopyData 的函数,它是其标头:

def OnCopyData(self,hwnd,msg ,wparam,lparam):

与Spy ++消息日志中的值相比,该函数提供的值是正确的。

The WM_COPYDATA event is received by a hidden window built with win32gui just for this purpose. The copydata event is connected to a function called OnCopyData and this is its header:
def OnCopyData(self, hwnd, msg, wparam, lparam):
The values the function delivers are correct as compared with the ones from the Spy++ messages log.

更新2

这应该与我想要的接近,但是给出了NULL指针错误。

This should be close to what I want, but gives a NULL pointer error.

class CopyDataStruct(ctypes.Structure):
    _fields_ = [('dwData', c_int),
                ('cbData', c_int),
                ('lpData', c_wchar_p)]

PCOPYDATASTRUCT = ctypes.POINTER(CopyDataStruct)
pCDS = ctypes.cast(lparam,  PCOPYDATASTRUCT)
print ctypes.wstring_at(pCDS.contents.lpData)


推荐答案

以下琐碎的win32gui应用程序:

I wrote the following trivial 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 消息:

I then sent the window a WM_COPYDATA message from another app (written in Delphi):

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!

因此,它似乎微不足道,就像您编写的代码一样。

So it seems that it works trivially, pretty much as you coded it.

我唯一想到的是Spotify的 COPYDATASTRUCT 中的文本不是以空字符结尾的。您应该能够通过读取数据很容易地进行检查。利用 cbData 成员。

The only thing that I can think of is that the text in Spotify's COPYDATASTRUCT is not null-terminated. You should be able to check that quite easily by reading out the data. Make use of the cbData member.

这篇关于在Python中接收WM_COPYDATA的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆