J'ai une application C++ native qui, pour le moment, doit simplement envoyer sa chaîne de ligne de commande et les coordonnées du curseur de la souris en cours à une application WPF. Le message est envoyé et reçu très bien, mais je ne peux pas convertir l'instance IntPtr
en C# en une structure.Envoyer une structure de C++ à WPF en utilisant WM_COPYDATA
Lorsque j'essaie de le faire, l'application se bloque sans exception ou la ligne de code qui la convertit est ignorée et le message suivant dans la boucle est reçu. Cela signifie probablement qu'il y a une exception native, mais je ne sais pas pourquoi.
Voici le programme C++. Pour le moment j'ignore la chaîne de la ligne de commande et j'utilise de fausses coordonnées du curseur juste pour m'assurer que les choses fonctionnent.
#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;
}
Et voici la partie de l'application WPF qui reçoit le message. La deuxième ligne à l'intérieur de l'instruction IF est ignorée si tout ne se bloque pas.
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;
}
Et voici les définitions C# pour les structures. J'ai joué sans fin avec des attributs de marshalling et je n'ai obtenu nulle part.
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;
}
}
Des idées?
J'ai aussi essayé WndProc primordial dans une fenêtre Winforms, le comportement est le même. –