使用 SendMessage WM_COPYDATA 发送双精度数组

Posted

技术标签:

【中文标题】使用 SendMessage WM_COPYDATA 发送双精度数组【英文标题】:Send double array with SendMessage WM_COPYDATA 【发布时间】:2013-12-13 17:56:13 【问题描述】:

我在将双精度数组从一个应用程序发送到另一个应用程序时遇到问题(均为 c#)。

我尝试像这样格式化CopyData Struct

    [StructLayout(LayoutKind.Sequential)]
    public struct CopyDataStruct
    
        public IntPtr dwData;
        public int cbData;
        [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.R8)]
        public double[] lpData;
    

Sender Application 我这样填充结构:

            double[] a = new double[2]  1.0, 2.0 ;
            int size = Marshal.SizeOf(typeof(double)) * a.Count();

            CopyDataStruct copyDataStruct;
            copyDataStruct.dwData = IntPtr.Zero;
            copyDataStruct.lpData = a;
            copyDataStruct.cbData = size;

            int result = SendMessage(hWnd, WM_COPYDATA, 0, ref copyDataStruct);

Receiver Application,我试试这个:

    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    
        switch (msg)
        
            case (int)WINMESSAGES.WM_COPYDATA:
                CopyDataStruct cp = (CopyDataStruct)Marshal.PtrToStructure(lParam, typeof(CopyDataStruct));

                break;
        

        return IntPtr.Zero;
    

但在cp.lpDat中,值来自null。不知道是发错了还是收错了。请帮忙,谢谢。

【问题讨论】:

获取 null 很难解释,但它不能像声明的那样工作。 PtrToStructure() 无法计算出数组有多大。将SizeConst = 2 添加到 [MarshalAs] 属性并重试。 谢谢汉斯。我试过这个,在接收器中我得到一个双数组,索引 0 中的数字非常低(cp.lpData[0] = 2.0760134663004284E-305),索引 1 中的数字非常高(cp.lpData[1] = 6.6028210135419114E +260)。 您对 SendMessage() 的声明是错误的,第三个参数是 IntPtr,而不是 int。 [DllImport("User32.dll", EntryPoint = "SendMessage")] public static extern int SendMessage(int hWnd, int Msg, int wParam, ref CopyDataStruct lParam);这适用于单个值(字符串、双精度)。我不能让它只适用于数组。再次感谢汉斯。 【参考方案1】:

您需要使用本机内存。像这样通过 C# double[] 是行不通的。它将被垃圾收集(哎呀,它甚至没有在 C# 中分配 - 它只是在堆栈中)。您可以使用不安全/固定关键字固定对象或使用AllocHGlobal

这是我从互联网上窃取的一些代码。演示发送部分:

    // Marshal the managed struct to a native block of memory.
    var myStruct = new double[2]  1.0, 2.0 ;
    int myStructSize = Marshal.SizeOf(myStruct); 
    IntPtr pMyStruct = Marshal.AllocHGlobal(myStructSize);
    try
    
        Marshal.StructureToPtr(myStruct, pMyStruct, true);

        COPYDATASTRUCT cds = new COPYDATASTRUCT();
        cds.cbData = myStructSize;
        cds.lpData = pMyStruct;

        // Send the COPYDATASTRUCT struct through the WM_COPYDATA message to 
        // the receiving window. (The application must use SendMessage, 
        // instead of PostMessage to send WM_COPYDATA because the receiving 
        // application must accept while it is guaranteed to be valid.)
        NativeMethod.SendMessage(hTargetWnd, WM_COPYDATA, this.Handle, ref cds);

        int result = Marshal.GetLastWin32Error();
        if (result != 0)
        
            MessageBox.Show(String.Format(
                "SendMessage(WM_COPYDATA) failed w/err 0x0:X", result));
        
    
    finally
    
        Marshal.FreeHGlobal(pMyStruct);
    

拍摄:http://code.msdn.microsoft.com/windowsdesktop/CSReceiveWMCOPYDATA-dbbc7ed7

【讨论】:

感谢您的回答。在“Marshal.StructureToPtr(myStruct, pMyStruct, true);”中我有错误“指定的结构必须是 blittable 或具有布局信息。”有什么想法吗?

以上是关于使用 SendMessage WM_COPYDATA 发送双精度数组的主要内容,如果未能解决你的问题,请参考以下文章

使用 SendMessage 从闪烁控件中检索文本

进程通信-SendMessage使用方法

使用 SendMessage 模拟用户鼠标点击

Discord bot 使用 javascript .sendMessage 不是函数

将 CString::GetString() 与 CWnd::SendMessage() 一起使用是不是安全?

delphi中有模拟发送鼠标按键sendmessage的疑问