Подписка на сообщения Windows через неуправляемые c ++ dll из ядра c # net - PullRequest
0 голосов
/ 27 апреля 2018

Я пытаюсь подписаться на сообщения о событиях Windows / систему обмена сообщениями из ядра c # net через c ++ dll без изменений, используя pinvoke.

У меня проблемы.

Получение дескриптора для моего процесса или создание пустого окна (поддерживает ли .net это).

  var hwnd = Process.GetCurrentProcess().Handle;
  var hwnd1 = Process.GetCurrentProcess().Handle.ToPointer();

Является ли что-либо из этого действительным, чтобы получить ручку.

Как мне маршалировать этот дескриптор типа c ++ HWND. IntPtr кажется очевидным выбором, но он не работает.

Вот что я использую для подписки на события

public class MsgSubscribe : IDisposable
{
    private readonly Importer _importer;

    [UnmanagedFunctionPointer(CallingConvention.Winapi)]
    private delegate Status DMsgSubscribe(uint msgType, uint msgQ,  int hwnd, uint msgId);
    private static DMsgSubscribe _dMsgSubscribe;
    private IntPtr PMsgSubscribe { get; set; }

    public bool Available { get; set; }

    public MsgSubscribe(Importer importer)
    {
        _importer = importer;

        if (_importer.hCurModule != IntPtr.Zero)
        {
            PMsgSubscribe = Importer.GetProcAddress(_importer.hCurModule, "MsgSubscribe");
            Available = PUlyMsgSubscribe != IntPtr.Zero;
        }
    }

    public Status MsgSubscribe(uint msgType, uint msgQ, int hwnd, uint msgId)
    {
        Status result = Status.FunctionNotAvailable;


        if (Available)
        {
            _dMsgSubscribe = (DMsgSubscribe)Marshal.GetDelegateForFunctionPointer(PMsgSubscribe, typeof(DMsgSubscribe));
            result = _dMsgSubscribe(msgType, msgQ, hwnd, msgId);
        }

        return result;
    }



    public void Dispose()
    {
    }
}

Я пробовал IntPtr и int для HWND сортировки, ни один не работает. Кроме того, я не уверен, как я должен отлавливать события, основанные на сообщениях окна, в Интернете очень мало всего, если что-либо.

Любая помощь приветствуется.

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

В конце концов нашел способ сделать эту работу, он включает в себя создание окна через C ++ Pinvoke.

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Constants.Constants;
using Constants.Enums;
using Models.WindowsApiModels;

namespace Dependencies.MessagingHandling
{
    public class CustomWindow : IDisposable
    {
        delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);


        private const int ErrorClassAlreadyExists = 1410;
        public IntPtr Handle { get; private set; }
        public List<YourType> Messages { get; set; }

        public void Dispose()
        {
            if (Handle != IntPtr.Zero)
            {
                Importer.DestroyWindow(Handle);
                Handle = IntPtr.Zero;
            }
        }

        public CustomWindow()
        {
            Messages = new List<YourType>();
            var className = "Prototype Messaging Class";

            WndProc mWndProcDelegate = CustomWndProc;

            // Create WNDCLASS
            WNDCLASS windClass = new WNDCLASS
            {
                lpszClassName = className,
                lpfnWndProc = Marshal.GetFunctionPointerForDelegate(mWndProcDelegate)
            };

            UInt16 classAtom = Importer.RegisterClassW(ref windClass);

            int lastError = Marshal.GetLastWin32Error();

            if (classAtom == 0 && lastError != ErrorClassAlreadyExists)
            {
                throw new Exception("Could not register window class");
            }

            // Create window
            Handle = Importer.CreateWindowExW(
                0,
                className,
                "Prototype Messaging Window",
                0, 0, 0, 0, 0,
                IntPtr.Zero,
                IntPtr.Zero,
                IntPtr.Zero,
                IntPtr.Zero
            );
        }

        private IntPtr  CustomWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
        {
            //handle your message here

            return Importer.DefWindowProc(hWnd, msg, wParam, lParam);
        }



        public Task GetMessage()
        {
            IntPtr handle = Handle;
            int bRet;
            while ((bRet = Importer.GetMessage(out var msg, Handle, 0, 0)) != 0)
            {
                switch (bRet)
                {
                    case -1:
                        Console.WriteLine("Error");
                        CancellationToken token = new CancellationToken(true);
                        return Task.FromCanceled(token);
                    default:
                        Importer.TranslateMessage(ref msg);
                        Importer.DispatchMessage(ref msg);
                        break;
                }
            }
            return Task.FromResult(true);
        }
    }
}

Запустите это в вашем основном методе в главном потоке, а ваше меню / графический интерфейс во вторичном потоке

 Task.Run(ShowMenu);

 _customWindow.GetMessage();

Importer - это пользовательский класс, содержащий маршалированные функции c ++ для создания / обработки окна, ищите по имени, поскольку они одинаковые. Все классы / структуры CAPS являются структурами Windows / C ++, их можно найти на официальном MSDN.

0 голосов
/ 27 апреля 2018

Обычно использование IntPtr является корректным.

Handle()

Возвращает такой IntPtr.

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

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