我正在努力将一些代码从c ++移植到c#,而我在使用PostMessage在c#app中工作时遇到了一些麻烦。我对MFC的东西不是很好(我),我认为我犯了一些基本的错误。 c ++代码中发生的是字节数组发布到窗口:
unsigned long result[5] = {0};
//Put some data in the array
unsigned int res = result[0];
Text winName = "window name";
HWND hWnd = FindWindow(winName.getConstPtr(), NULL);
BOOL result = PostMessage(hWnd, WM_COMMAND, 10, res);
我正在使用以下c#代码(基于代码here)尝试做同样的事情:
[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern Int32 FindWindow(String lpClassName, String lpWindowName);
[DllImport("User32.dll", EntryPoint = "PostMessage")]
public static extern int PostMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);
[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
[MarshalAs(UnmanagedType.SafeArray)]
public byte[] lpData;
}
public static int sendWindowsByteMessage(int hWnd, int wParam, byte[] data)
{
int result = 0;
if (hWnd > 0)
{
int len = data.Length;
COPYDATASTRUCT cds;
cds.dwData = (IntPtr)100;
cds.lpData = data;
cds.cbData = len + 1;
result = PostMessage(hWnd, WM_COPYDATA, wParam, ref cds);
}
return result;
}
byte[] result = getResults();
int hWnd = MessageHelper.FindWindow(null, "window name");
int status = MessageHelper.sendWindowsByteMessage(hWnd, 10, result);
status的值始终为0,根据PostMessage上的文档,这意味着失败。关于我正在制作的(可能是简单的)错误的任何指示?
答案 0 :(得分:1)
WM_ COPYDATA
必须发送而不是发布。
我不确定你的byte []封送是否正确。
答案 1 :(得分:1)
这是我成功使用的相同逻辑版本:
[StructLayout(LayoutKind.Sequential)]
internal class COPYDATASTRUCT
{
internal uint dwData;
internal uint cbData;
internal IntPtr lpData;
}
// send DATA packet
internal static void SendData(IntPtr hWnd, uint dwData, DATA infos)
{
// get pointer to DATA block
IntPtr infoMem = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(DATA)));
Marshal.StructureToPtr(infos, infoMem, false);
// construct COPYDATASTRUCT to point to DATA block
COPYDATASTRUCT cds = new COPYDATASTRUCT();
cds.dwData = dwData;
cds.lpData = infoMem;
cds.cbData = (uint)Marshal.SizeOf(typeof(DATA));
// get pointer to COPYDATASTRUCT block
IntPtr cdsMem = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(COPYDATASTRUCT)));
Marshal.StructureToPtr(cds, cdsMem, false);
// send message with block pointer to other process
SendMessage(hWnd, WM_COPYDATA, 0, (uint)cdsMem.ToInt32());
// Free allocated memory
Marshal.FreeHGlobal(cdsMem);
Marshal.FreeHGlobal(infoMem);
}
如果目标窗口在另一个进程中,则需要使用HGlobal内存。我不确定UnmanagedType.SafeArray是否适合你。
答案 2 :(得分:0)
PostMessage可能失败,因为窗口句柄无效。调用GetLastError以找出失败的原因。你真的想在这里使用SendMessage - 只保证在调用期间分配缓冲区,PostMessage是异步的 - 它在发布消息后返回,你的cds结构可能在调用目标窗口proc之前被释放。如果需要使用PostMessage,则必须显式分配非托管缓冲区,将数据复制到该缓冲区,并将其用于调用。