从C+发送结构+;使用WM_COPYDATA创建WPF 我有一个本地C++应用程序,暂时只需要将它的命令行字符串和当前鼠标指针坐标发送到WPF应用程序。消息的发送和接收都很好,但我无法将C#中的IntPtr实例转换为结构
当我尝试这样做时,应用程序将毫无例外地崩溃,或者跳过转换它的代码行并接收循环中的下一条消息。这可能意味着发生了本机异常,但我不知道为什么 这是C++程序。目前,我忽略命令行字符串,并使用假光标坐标来确保工作正常从C+发送结构+;使用WM_COPYDATA创建WPF 我有一个本地C++应用程序,暂时只需要将它的命令行字符串和当前鼠标指针坐标发送到WPF应用程序。消息的发送和接收都很好,但我无法将C#中的IntPtr实例转换为结构,c++,wpf,interop,marshalling,wm-copydata,C++,Wpf,Interop,Marshalling,Wm Copydata,当我尝试这样做时,应用程序将毫无例外地崩溃,或者跳过转换它的代码行并接收循环中的下一条消息。这可能意味着发生了本机异常,但我不知道为什么 这是C++程序。目前,我忽略命令行字符串,并使用假光标坐标来确保工作正常 #include "stdafx.h" #include "StackProxy.h" #include "string" typedef std::basic_string<WCHAR, std::char_traits<WCHAR>> wstring; s
#include "stdafx.h"
#include "StackProxy.h"
#include "string"
typedef std::basic_string<WCHAR, std::char_traits<WCHAR>> wstring;
struct StackRecord
{
//wchar_t CommandLine[128];
//LPTSTR CommandLine;
//wstring CommandLine;
__int32 CursorX;
__int32 CursorY;
};
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
COPYDATASTRUCT data;
ZeroMemory(&data, sizeof(COPYDATASTRUCT));
StackRecord* record = new StackRecord();
wstring cmdLine(lpCmdLine);
//record.CommandLine = cmdLine;
record->CursorX = 5;
record->CursorY = 16;
data.dwData = 12;
data.cbData = sizeof(StackRecord);
data.lpData = record;
HWND target = FindWindow(NULL, _T("Window1"));
if(target != NULL)
{
SendMessage(target, WM_COPYDATA, (WPARAM)(HWND) target, (LPARAM)(LPVOID) &data);
}
return 0;
}
下面是结构的C#定义。我没完没了地玩弄编组属性,结果一无所获
internal static class Interop
{
public static readonly int WM_COPYDATA = 0x4A;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct CopyDataStruct
{
public IntPtr dwData;
public int cbData;
public IntPtr lpData;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)]
public struct StackRecord
{
//[MarshalAs(UnmanagedType.ByValTStr)]
//public String CommandLine;
public Int32 CursorX;
public Int32 CursorY;
}
}
有什么想法吗?如果没有关于您的设置的更多信息,我不确定您的错误是什么。我尽我所能复制了代码(在WPF应用程序中使用WndProc,从我自己的win32应用程序发送),它对我来说运行良好。如果您正在运行64位应用程序,则肯定会出现一些错误,即Pack=1将导致COPYDATASTRUCT未对齐,从指针读取可能会导致痛苦 它只是在通过ints吗?查看通过LPWSTR或wstring的注释代码将导致严重的问题,尽管在您解组发送的数据之前,这不会变得明显 值得一提的是,这是我的代码片段,它似乎对我有用,包括让命令行通过
/* C++ code */
struct StackRecord
{
wchar_t cmdline[128];
int CursorX;
int CursorY;
};
void SendCopyData(HWND hFind)
{
COPYDATASTRUCT cp;
StackRecord record;
record.CursorX = 1;
record.CursorY = -1;
_tcscpy(record.cmdline, L"Hello World!");
cp.cbData = sizeof(record);
cp.lpData = &record;
cp.dwData = 12;
SendMessage(hFind, WM_COPYDATA, NULL, (LPARAM)&cp);
}
/* C# code */
public static readonly int WM_COPYDATA = 0x4A;
[StructLayout(LayoutKind.Sequential)]
public struct CopyDataStruct
{
public IntPtr dwData;
public int cbData;
public IntPtr lpData;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct StackRecord
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
public string CommandLine;
public Int32 CursorX;
public Int32 CursorY;
}
protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_COPYDATA)
{
StackRecord record = new StackRecord();
try
{
CopyDataStruct cp = (CopyDataStruct)Marshal.PtrToStructure(lParam, typeof(CopyDataStruct));
if (cp.cbData == Marshal.SizeOf(record))
{
record = (StackRecord)Marshal.PtrToStructure(cp.lpData, typeof(StackRecord));
}
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine(e.ToString());
}
handled = true;
}
else
{
handled = false;
}
return IntPtr.Zero;
}
我已经构建了两个应用程序(分别使用VC++和VC#),解决了问题的“简化”变体(即无法获得该结构),它们似乎工作得完美无缺,因此可能确实与您的设置有关,如前所述 无论如何,下面是代码(只需将其粘贴到新创建的WIN32应用程序(适用于VC++)和WINDOWS窗体应用程序(适用于C#)中即可运行和测试): StackProxy.cpp 希望这有帮助 我对C语言和(尤其是)互操作(对C++编程感兴趣)没有太多的了解,但在几小时前没有人回答过,只是觉得尝试这个问题是个很好的挑战。更不用说赏金了:)
*amn it,我迟到了:)我还尝试在Winforms窗口中重写WndProc,行为是一样的。“即Pack=1将导致COPYDATASTRUCT未对齐,从指针读取可能会以痛苦告终。”啊,现在很明显。我习惯于从Pack=1有意义的文件中读取结构。C++应用程序是32位的,但是我有一个64位的系统,.NET代码被压缩到64位代码。卸下包装=1将其固定。谢谢“查看通过LPWSTR或wstring的注释代码将导致严重问题”,我认为可能是这样。我还尝试像您一样传递固定的wchar\t字符串,但没有成功,但这是由于上述问题。
/* C++ code */
struct StackRecord
{
wchar_t cmdline[128];
int CursorX;
int CursorY;
};
void SendCopyData(HWND hFind)
{
COPYDATASTRUCT cp;
StackRecord record;
record.CursorX = 1;
record.CursorY = -1;
_tcscpy(record.cmdline, L"Hello World!");
cp.cbData = sizeof(record);
cp.lpData = &record;
cp.dwData = 12;
SendMessage(hFind, WM_COPYDATA, NULL, (LPARAM)&cp);
}
/* C# code */
public static readonly int WM_COPYDATA = 0x4A;
[StructLayout(LayoutKind.Sequential)]
public struct CopyDataStruct
{
public IntPtr dwData;
public int cbData;
public IntPtr lpData;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct StackRecord
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
public string CommandLine;
public Int32 CursorX;
public Int32 CursorY;
}
protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_COPYDATA)
{
StackRecord record = new StackRecord();
try
{
CopyDataStruct cp = (CopyDataStruct)Marshal.PtrToStructure(lParam, typeof(CopyDataStruct));
if (cp.cbData == Marshal.SizeOf(record))
{
record = (StackRecord)Marshal.PtrToStructure(cp.lpData, typeof(StackRecord));
}
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine(e.ToString());
}
handled = true;
}
else
{
handled = false;
}
return IntPtr.Zero;
}
#include "stdafx.h"
#include "StackProxy.h"
#include <string>
struct StackRecord {
__int32 CursorX;
__int32 CursorY;
};
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {
StackRecord record;
record.CursorX = 5;
record.CursorY = 16;
COPYDATASTRUCT data;
data.dwData = 12;
data.cbData = sizeof(StackRecord);
data.lpData = &record;
HWND target = FindWindow(NULL, _T("Window1"));
if(target != NULL)
SendMessage(target, WM_COPYDATA, (WPARAM)(HWND) target, (LPARAM)(LPVOID) &data);
return 0;
}
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public struct COPYDATASTRUCT
{
public System.Int32 dwData;
public System.Int32 cbData;
public System.IntPtr lpData;
}
int WM_COPYDATA = 0x4A;
[StructLayout(LayoutKind.Sequential)]
public struct StackRecord
{
public Int32 CursorX;
public Int32 CursorY;
}
public Form1()
{
InitializeComponent();
Text = "Window1";
}
protected override void WndProc(ref Message msg)
{
if (msg.Msg == WM_COPYDATA) {
COPYDATASTRUCT cp = (COPYDATASTRUCT)Marshal.PtrToStructure(msg.LParam, typeof(COPYDATASTRUCT));
StackRecord record = (StackRecord)Marshal.PtrToStructure(cp.lpData, typeof(StackRecord));
MessageBox.Show(String.Format("X: {0}, Y: {1}, Data: {2}", record.CursorX, record.CursorY, cp.dwData));
}
base.WndProc(ref msg);
}
}
}