Question: Question:
How can I drag and drop data from a C ++ / MFC program to a C # / WPF program? Currently, with the following code, I was able to confirm that the data was stored in DragEventArgs
on the C # side, but I can not retrieve it well. Since the C ++ side is existing code, I would like to support it on the C # side. Should I use C ++ / CLI to create a DLL just for converting values?
C ++ code
typedef struct {
bool isBar;
int val;
WCHAR name[100];
} Bar;
typedef struct {
int val;
TCHAR name[100];
Bar bar[1];
} Foo;
void StartDrag(Foo foo) {
STGMEDIUM data;
data.tymed = TYMED_HGLOBAL;
data.hGlobal = (HGLOBAL)foo;
data.pUnkForRelease = NULL;
CLIPFORMAT f;
f = RegisterClipboardFormat(TEXT("FOO"));
COleDataSource *DataSource = new COleDataSource();
DataSource->CacheData(f, &data);
DataSource->DoDragDrop(DROPEFFECT_COPY|DROPEFFECT_MOVE);
}
C # code
[StructLayout(LayoutKind.Sequential)]
public struct Bar
{
[MarshalAs(UnmanagedType.Bool)]
public bool IsText;
public int value;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public string name;
}
[StructLayout(LayoutKind.Sequential)]
public struct Foo
{
public int value;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public string name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public Bar[] bar;
}
void OnDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent("FOO"))
{
var fooStream = e.Data.GetData("FOO");
// fooStreamはMemoryStream、BinaryReaderで見ると
// C++側で設定した値が入っているのが見える
var foo = e.Data.GetData(typeof(Foo)); // fooはnull
}
}
Answer: Answer:
I think that System.Runtime.InteropServices.Marshal can be realized only with C #.
(Unconfirmed until operation)
MemoryStream ms = //...
Foo obj;
byte[] data = ms.ToArray();
if (data.Length != Marshal.SizeOf(Foo)) {
// 受信サイズがFoo型サイズと一致しないためマーシャリング不可
// 適切なエラー処理...
}
IntPtr rawmem = Marshall.AllocCoTaskMem(data.Length);
try {
Marshal.Copy(data, 0, rawmem, data.Length)
obj = (Foo)Marshal.PtrToStructure(rawmem, typeof(Foo));
} finally {
Marshal.FreeCoTaskMem(rawmem);
}
Since the C ++ side struct Bar
and Foo
contain string type WCHAR
and TCHAR
members, respectively, it is better to specify the appropriate CharSet
value in the StructLayout
attribute of the C # side struct.