fredag den 6. marts 2015

Sending a WM_COPYDATA from C++ to Python

The following code shows how to send a WM_DATACOPY message from C++ and how to recede it in Python.

The code is based on the code in these posts: http://stackoverflow.com/questions/2451103/use-wm-copydata-to-send-data-between-processes, and http://stackoverflow.com/questions/5249903/receiving-wm-copydata-in-python.

Sending in C++:

1
2
3
4
5
6
7
LPTSTR lpszString = L"Not ready";
COPYDATASTRUCT cds;
cds.dwData = 1;
size_t count_t = sizeof(TCHAR) * (_tcslen(lpszString) + 1);
cds.cbData = static_cast<DWORD>(count_t);
cds.lpData = lpszString;
SendMessage(hwnd, WM_COPYDATA, (WPARAM)hwnd, (LPARAM)(LPVOID)&cds);


Recieving in Python:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import win32api
import win32process

import struct
import win32con
import win32gui
import array
import win32ui
from ctypes import *


class ACOPYDATASTRUCT(Structure):
    _fields_ = [
        ('dwData', c_ulong),
        ('cbData', c_ulong),
        ('lpData', c_void_p)
    ]
PCOPYDATASTRUCT = POINTER(ACOPYDATASTRUCT)


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 = cast(lparam, PCOPYDATASTRUCT)
        print pCDS.contents.dwData
        print pCDS.contents.cbData
        status = wstring_at(pCDS.contents.lpData)
        print status
        win32gui.PostQuitMessage(0)
        return 1

l = Listener()

win32gui.PumpMessages()


As an additional bonus one can send the hwnd of the receiving python program to the C++ program using a WM_COPYDATA message:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class COPYDATATYPE(Structure):
    _fields_ = [("cmd",   c_ulong),
                ("hwnd",  c_ulong)]

class COPYDATASTRUCT(Structure):
    _fields_ = [("dwData", c_ulong),
                ("cbData", c_ulong),
                ("lpData", POINTER(COPYDATATYPE))]

cpyData = COPYDATATYPE(1, l.hwnd)
cds = COPYDATASTRUCT(c_ulong(8888),
                     c_ulong(sizeof(cpyData)),
                     pointer(cpyData))

# try to send a message
win32api.SendMessage(target_hwnd,
                     win32con.WM_COPYDATA,
                     0,
                     addressof(cds))


See also my previous post here: http://blog.fagidiot.dk/2015/03/send-wmcopydata-from-python-partial.html

Ingen kommentarer:

Send en kommentar