Ho un'applicazione C++ nativa che, per il momento, deve semplicemente inviare la sua stringa di riga di comando e le coordinate del cursore del mouse corrente a un'applicazione WPF. Il messaggio viene inviato e ricevuto correttamente, ma non riesco a convertire l'istanza IntPtr
in C# in una struttura.Invio di una struct da C++ a WPF utilizzando WM_COPYDATA
Quando provo a farlo, l'applicazione si arresta in modo anomalo senza eccezioni oppure la riga di codice che la converte viene saltata e viene ricevuto il messaggio successivo nel ciclo. Questo probabilmente significa che si sta verificando un'eccezione nativa, ma non so perché.
Ecco il programma C++. Per il momento sto ignorando la stringa della riga di comando e uso false coordinate del cursore solo per assicurarmi che le cose funzionino.
#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;
}
Ed ecco la parte dell'applicazione WPF che riceve il messaggio. La seconda riga all'interno dell'istruzione IF viene ignorata, se il tutto non si arresta.
public IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == Interop.WM_COPYDATA)
{
var data = (Interop.CopyDataStruct)Marshal.PtrToStructure(lParam, typeof(Interop.CopyDataStruct));
var record = (Interop.StackRecord)Marshal.PtrToStructure(data.lpData, typeof(Interop.StackRecord));
MessageBox.Show(String.Format("X: {0}, Y: {1}", record.CursorX, record.CursorY));
}
return IntPtr.Zero;
}
E qui ci sono le definizioni C# per le strutture. Ho giocato all'infinito con attributi di marshalling e ottenuto da nessuna parte.
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;
}
}
Qualche idea?
Ho anche provato l'override WndProc in una finestra WinForms, il comportamento è lo stesso. –