Получение WM_COPYDATA в Python - PullRequest
       52

Получение WM_COPYDATA в Python

4 голосов
/ 09 марта 2011

Я пытаюсь прочитать из Python сообщение WM_COPYDATA, которое некоторые приложения (я пытаюсь с помощью Spotify) отправить в WindowsLiveMessenger, чтобы обновить фразу «Что я слушаю ...».

Из того, что я смог найти, WM_COPYDATA сообщения приходят в COPYDATASTRUCT со следующей структурой:

  • dwData в нашем случае 0x547, так что он получает доступ к функции прослушивания сейчас
  • cbData с длиной полученной строки
  • lpData с указателем на саму строку, может включать символы Unicode

Строка должна иметь следующую строкуформат: \0Music\0status\0format\0song\0artist\0album\0 как указано ListeningNowTracker

То, что мы получаем в событии WM_COPYDATA, это указатель на lParam, который содержит COPYDATASTRUCT.

Я начал возиться с функциями pywin32 и вспомнил, что они не принимают символы Юникода из прошлого опыта, затем я переключился на ctypes.Несмотря на то, что для меня это был почти новый мир в Python, я попробовал с POINTER(), и все, что я получил, было неизвестными объектами для меня или нарушениями доступа.

Я думаю, что код должен создать COPYDATASTRUCT:

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

Затем сделайте lParam указателем на эту структуру, получите указатель строки из lpData и, наконец, получите строку с ctypes.string_at(lpData,cbData).

Любые подсказки?

ОБНОВЛЕНИЕ 1

Событие WM_COPYDATA получено скрытым окном, построенным с win32gui только для этой цели.Событие copydata связано с функцией с именем OnCopyData, и это ее заголовок:
def OnCopyData(self, hwnd, msg, wparam, lparam):
Значения, предоставляемые функцией, являются правильными по сравнению со значениями из журнала сообщений Spy ++.

ОБНОВЛЕНИЕ 2

Это должно быть близко к тому, что я хочу, но дает ошибку указателя NULL.

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)

1 Ответ

5 голосов
/ 10 марта 2011

Я написал следующее тривиальное приложение win32gui:

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()

Затем я отправил окну сообщение WM_COPYDATA из другого приложения (написанное на 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!

Так что, кажется, это работает тривиально, почти так же, как вы его закодировали.

Единственное, о чем я могу думать, это то, что текст в Spotify COPYDATASTRUCTне заканчивается нулем.Вы можете легко это проверить, считав данные.Воспользуйтесь cbData member.

...