Подписка на сообщения Windows через неуправляемые c ++ dll из ядра c # net

Я пытаюсь подписаться на сообщения о событиях 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

Решение

В общем, использование IntPtr является правильным.

Handle()

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

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

0

Другие решения

В конце концов нашел способ сделать эту работу, он включает в себя создание окна через 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 ++ API, их можно найти на официальном MSDN.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector