Invio di una struttura da C++ a WPF utilizzando WM_COPYDATA

 C Programming >> Programmazione C >  >> Tags >> WPF
Invio di una struttura da C++ a WPF utilizzando WM_COPYDATA


Ho un'applicazione nativa C++ che, per il momento, deve semplicemente inviare la stringa della riga di comando e le coordinate correnti del cursore del mouse a un'applicazione WPF. Il messaggio viene inviato e ricevuto correttamente, ma non riesco a convertire il IntPtr istanza in C# in una struttura.


Quando provo a farlo, l'applicazione si arresta in modo anomalo senza eccezioni o la riga di codice che la converte viene saltata e viene ricevuto il messaggio successivo nel ciclo. Questo probabilmente significa che si è verificata un'eccezione nativa, ma non so perché.


Ecco il programma C++. Per il momento sto ignorando la stringa della riga di comando e sto usando coordinate del cursore false 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 saltata, se il tutto non si arresta in modo anomalo.


    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;
}

Ed ecco le definizioni C# per gli struct. Ho giocato all'infinito con gli attributi di smistamento e non sono arrivato 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?


Alcune risposte al codice


#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;
}
    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;
}
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;
} }
/* 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);
}
} }

No