gpt4 book ai didi

c++ - 使用 WM_COPYDATA 将结构从 C++ 发送到 WPF

转载 作者:可可西里 更新时间:2023-11-01 18:27:45 26 4
gpt4 key购买 nike

我有一个 native C++ 应用程序,暂时只需要将其命令行字符串和当前鼠标光标坐标发送到 WPF 应用程序。消息发送和接收都很好,但我无法将 C# 中的 IntPtr 实例转换为结构。

当我尝试这样做时,应用程序要么毫无异常(exception)地崩溃,要么跳过转换它的代码行并接收循环中的下一条消息。这可能意味着发生了 native 异常,但我不知道为什么。

这是 C++ 程序。目前我忽略命令行字符串并使用假光标坐标来确保一切正常。

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

这里是 WPF 应用程序接收消息的部分。 IF 语句中的第二行被跳过,如果整个事情不只是崩溃的话。

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

这里是结构的 C# 定义。我无休止地研究编码属性,但一无所获。

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

有什么想法吗?

最佳答案

如果没有关于您的设置的更多信息,我不确定您一定会出错。我尽可能地复制了代码(在 WPF 应用程序中使用 WndProc,从我自己的 win32 应用程序发送)并且它对我来说工作正常。如果您正在运行 64 位应用程序,肯定会出现一些错误,即 Pack = 1 将导致 COPYDATASTRUCT 变得未对齐并且从指针读取可能会以痛苦告终。

仅传递整数会崩溃吗?查看传递 LPWSTR 或 wstring 的注释代码将导致严重的问题,尽管在您解码发送的数据之前这不会变得明显。

就其值(value)而言,这是我的代码片段,它们似乎对我有用,包括跨过命令行。

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

关于c++ - 使用 WM_COPYDATA 将结构从 C++ 发送到 WPF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1891237/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com