Отправить байт [] из c # через Win32 SendMessage - PullRequest
1 голос
/ 26 мая 2011

Я работаю над переносом некоторого кода с c ++ на c #, и у меня возникли некоторые проблемы с получением PostMessage для работы в приложении c #.Я не очень хорош (пока) в MFC и думаю, что делаю несколько основных ошибок.Что происходит в коде c ++, так это то, что байтовый массив публикуется в окне:

unsigned long result[5] = {0};
//Put some data in the array
unsigned int res = result[0];
Text winName = "window name";
HWND hWnd = FindWindow(winName.getConstPtr(), NULL);
BOOL result = PostMessage(hWnd, WM_COMMAND, 10, res);

Я использую следующий код c # (на основе кода здесь ) в попыткесделать то же самое:

[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern Int32 FindWindow(String lpClassName, String lpWindowName);

[DllImport("User32.dll", EntryPoint = "PostMessage")]
public static extern int PostMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);

[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT
{
    public IntPtr dwData;
    public int cbData;
    [MarshalAs(UnmanagedType.SafeArray)]
    public byte[] lpData;
}

public static int sendWindowsByteMessage(int hWnd, int wParam, byte[] data)
{
    int result = 0;

    if (hWnd > 0)
    {
         int len = data.Length;
         COPYDATASTRUCT cds;
         cds.dwData = (IntPtr)100;
         cds.lpData = data;
         cds.cbData = len + 1;
         result = PostMessage(hWnd, WM_COPYDATA, wParam, ref cds);
    }

    return result;
}

byte[] result = getResults();
int hWnd = MessageHelper.FindWindow(null, "window name");
int status = MessageHelper.sendWindowsByteMessage(hWnd, 10, result);

Значение status всегда равно 0, что в соответствии с документами PostMessage означает сбой.Какие-нибудь указатели на (возможно простые) ошибки, которые я делаю?

Ответы [ 3 ]

1 голос
/ 26 мая 2011

WM_ COPYDATA должно быть отправлено, а не отправлено.

Я не уверен, что ваш байт [] маршалинг тоже подходит.

1 голос
/ 26 мая 2011

Вот версия той же логики, которую я успешно использовал:

    [StructLayout(LayoutKind.Sequential)]
    internal class COPYDATASTRUCT
    {
        internal uint dwData;
        internal uint cbData;
        internal IntPtr lpData;
    }

    // send DATA packet
    internal static void SendData(IntPtr hWnd, uint dwData, DATA infos)
    {
        // get pointer to DATA block
        IntPtr infoMem = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(DATA)));
        Marshal.StructureToPtr(infos, infoMem, false);

        // construct COPYDATASTRUCT to point to DATA block
        COPYDATASTRUCT cds = new COPYDATASTRUCT();
        cds.dwData = dwData;
        cds.lpData = infoMem;
        cds.cbData = (uint)Marshal.SizeOf(typeof(DATA));

        // get pointer to COPYDATASTRUCT block
        IntPtr cdsMem = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(COPYDATASTRUCT)));
        Marshal.StructureToPtr(cds, cdsMem, false);

        // send message with block pointer to other process
        SendMessage(hWnd, WM_COPYDATA, 0, (uint)cdsMem.ToInt32());

        // Free allocated memory
        Marshal.FreeHGlobal(cdsMem);
        Marshal.FreeHGlobal(infoMem);
    }

Если целевое окно находится в другом процессе, вам нужно использовать память HGlobal. Я не уверен, что UnmanagedType.SafeArray сделает это за вас.

0 голосов
/ 26 мая 2011

PostMessage, вероятно, завершается ошибкой, потому что дескриптор окна недействителен.Вызовите GetLastError, чтобы выяснить причину сбоя.Вы на самом деле захотите использовать SendMessage здесь - буфер гарантированно будет выделен только на время вызова, а PostMessage асинхронный - он возвращается после отправки сообщения, и ваша структура cds может быть освобождена до вызова целевого окна proc,Если вам нужно использовать PostMessage, вам придется явно выделить неуправляемый буфер, скопировать в него свои данные и использовать его для вызова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...