Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Решаем проблему приема структуры из C# в Delphi через `WM_COPYDATA`

Delphi , ОС и Железо , Справочник по сообщениям

В данной статье мы рассмотрим проблему передачи структуры из C# в Delphi через WM_COPYDATA и предложим решение для ее решения.

Описание проблемы

Разработчик столкнулся с проблемой передачи структуры из C# в Delphi через WM_COPYDATA. Несмотря на то, что он следовал формату из https://www.pinvoke.net/default.aspx/Structures.COPYDATASTRUCT для копирования данных структуры, на стороне Delphi не получалось принять сообщение. Разработчик подозревает, что проблема может быть связана с неправильным кодированием структуры.

Решение проблемы

Для решения проблемы мы предлагаем следующим образом изменить код в C#:

  1. Убедитесь, что в структуре COPYDATASTRUCT присутствует атрибут [StructLayout(LayoutKind.Sequential)].
  2. Измените определение функции SendMessage на SendMessageCopyData, как показано ниже:
[DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage", SetLastError = false)]
public static extern int SendMessageCopyData(IntPtr hWnd, int uMsg, UIntPtr wParam, ref COPYDATASTRUCT lParam);
  1. Добавьте метод IntPtrAlloc<T>, который выделяет память под структуру и копирует ее в выделенный участок памяти:
public static IntPtr IntPtrAlloc<T>(T param)
{
    IntPtr retval = Marshal.AllocHGlobal(Marshal.SizeOf(param));
    Marshal.StructureToPtr(param, retval, false);
    return retval;
}
  1. Добавьте метод IntPtrFree, который освобождает выделенную память:
public static void IntPtrFree(ref IntPtr preAllocated)
{
    Marshal.FreeHGlobal(preAllocated);
    preAllocated = IntPtr.Zero;
}
  1. Измените метод SendFingerPrintResult следующим образом:
public void SendFingerPrintResult(string msg)
{
    // Получаем окно для отправки структуры
    IntPtr receiverHandle = GetWindow();
    if (receiverHandle == IntPtr.Zero) return;

    // Получаем структуру
    ReturnStruct ret = GetReturnStruct();
    IntPtr ptr = IntPtrAlloc(ret);
    try
    {
        var cds = new COPYDATASTRUCT
        {
            dwData = IntPtr.Zero,
            cbData = Marshal.SizeOf(ret),
            lpData = ptr
        };

        IntPtr iPtr = IntPtrAlloc(cds);
        try
        {
            SendMessageCopyData(receiverHandle, WM_COPYDATA, senderID, iPtr);
        }
        finally
        {
            IntPtrFree(ref iPtr);
        }
    }
    finally
    {
        IntPtrFree(ref ptr);
    }
}
  1. Измените структуру ReturnStruct следующим образом:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct ReturnStruct
{
    public int i;

    public byte card_len;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
    public string card;

    public byte name_len;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
    public string name;

    public byte responsecode_len;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)]
    public string responsecode;

    public byte responsetext_len;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
    public string responsetext;

    public byte approval_len;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 15)]
    public string approval;

    public byte tranid_len;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
    public string tranid;

    public byte reference_len;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
    public string reference;

    public double d;

    public byte transactionType_len;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
    public string transactionType;

    public byte creditCardType_len;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
    public string creditCardType;

    public int EMVContact;

    public byte applicationName_len;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
    public string applicationName;

    public byte applicationIdentifier_len;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 15)]
    public string applicationIdentifier;

    public byte reserved_len;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
    public string reserved;
}
  1. Добавьте метод GetReturnStruct, который заполняет структуру ReturnStruct данными:
public ReturnStruct GetReturnStruct()
{
    var ret = new ReturnStruct();

    ret.i = ...;

    ret.card = ...;
    ret.card_len = (byte)Math.Min(System.Text.Encoding.Default.GetByteCount(ret.card), 50);

    ret.name = ...;
    ret.name_len = (byte)Math.Min(System.Text.Encoding.Default.GetByteCount(ret.name), 100);

    // Заполните остальные поля структуры аналогичным образом

    return ret;
}

После внесения этих изменений, сообщение с структурой должно быть принято на стороне Delphi без проблем.

Создано по материалам из источника по ссылке.

В данной статье рассматривается проблема передачи структуры из C# в Delphi через `WM_COPYDATA` и предлагается решение для ее решения.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Справочник по сообщениям ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-05-01 11:27:24/0.0035190582275391/0