python win32api sendmessage_Python的Win32Gui自动化 – 发送WM_COPYDATA从BSPlayer获取数据

I am desperately trying to automate BSPlayer from my script.

I was successful in sending simple command ids to the BSPlayer window(volume up/down, play/pause, etc.), however I am not able to get the file name back.

Here is the BSPlayer API.

I was able to emulate in python the first parts, however the WM_COPYDATA doesn't work.

Here is my Python code:

copyDataCmd = COPYDATASTRUCT()

copyDataCmd.dwData = self.BSP_GetFileName

copyDataCmd.lpData = ""

copyDataCmd.cbData = 4

win32gui.SendMessage(self.playerWindowHandler, win32con.WM_COPYDATA,

ownHandler, copyDataCmd);

Obviously .lpData returns "" ...

What I am trying to emulate:

cds:TCOPYDATASTRUCT;

buf:array[0..MAX_PATH-1] of char;

adr:pointer; //

adr:=@buf;

cds.dwData:=BSP_GetFileName;

cds.lpData:=@adr;

cds.cbData:=4;

SendMessage(bsp_hand,WM_COPYDATA,appHWND,lParam(@cds));

// available in BSPlayer version 0.84.484+ //

// appHWND is calling application window handle

// File name will be copied to buf //

// Get open file name

BSP_GetFileName = $1010B;

To be more verbose, I am trying to get the filename from a BSPlayer window. For this I am trying to emulate the code above. I expect a buffer of some sort to be filled with my desired string, but it comes up empty.

So, again, I want the Python equivalent of the code just above.

For example this code was emulated succesfully:

status := SendMessage(bsp_hand,WM_BSP_CMD,BSP_GetStatus,0);

// available in BSPlayer version 0.84.484+ //

// Return player status // 0 - STOP // 1 - PAUSE

// 2 - PLAY // 4 - No movie open

BSP_GetStatus = $10102;

Thanks in advance!

解决方案

You cannot replicate that WM_COPYDATA in your Python code. It can only be used in-proc, for example for plugins.

The example Delphi code is written under the assumption that the call to WM_COPYDATA is made from the same process as the window which receives the message. That's because the WM_COPYDATA is used to copy a pointer, and pointers are only valid inside the process which allocated the memory. You cannot send a pointer across a process boundary.

In my opinion, the designers of the interface are abusing WM_COPYDATA. It is meant to be used to solve the exact problem of transferring data between processes. It is the simplest most lightweight inter-process communication available. To then use it to transfer a pointer rather defeats the process.