5146


C++/MFCのプログラムからC#/WPFのプログラムにドラッグアンドドロップでデータを渡すにはどうするのがよいでしょうか。現在以下のようなコードで、C#側で`DragEventArgs`にデータが入っているのまで確認できたのですがうまく取り出せません。C++側は既存コードなのでC#側で対応したいです。値を変換するためだけのDLLをC++/CLIで作るとよいのでしょうか？

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);
    }
    
[/code]

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
        }
    }
    
[/code]


CC BY-SA 3.0
2015-01-23T07:03:18.627
5139
2015-01-23T08:18:25.167
7722
question
c# c++ .net
C++/MFCからC#/WPFへドラッグアンドドロップするには


[System.Runtime.InteropServices.Marshal](https://msdn.microsoft.com/ja-
jp/library/system.runtime.interopservices.marshal.aspx) ならC#のみで実現可能かと思います。  
（動作までは未確認）

[code]

    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);
    }
    
[/code]

C++側struct `Bar`, `Foo`はそれぞれ文字列型`WCHAR`,
`TCHAR`メンバを含むため、C#側structの[`StructLayout`](https://msdn.microsoft.com/ja-
jp/library/system.runtime.interopservices.structlayoutattribute.aspx)属性に適切な`CharSet`値を明示した方が良いです。


CC BY-SA 3.0
2015-01-23T08:10:52.683
5146
2015-01-23T08:18:25.167
2015-01-23T08:18:25.167
49
49
5139
answer