[英]Subscribing to windows messages through unmanaged c++ dll from c# net core
I am trying to subscribe to windows message events/messaging system from c# net core through unamanged c++ dll using pinvoke. 我正在尝试使用pinvoke从c#网络核心通过未处理的c ++ dll订阅Windows消息事件/消息系统。
Issues I am having. 我遇到的问题。
Getting the handle for my process or creating an empty window (does .net even support that). 获取我的过程的句柄或创建一个空窗口(.net甚至支持它)。
var hwnd = Process.GetCurrentProcess().Handle;
var hwnd1 = Process.GetCurrentProcess().Handle.ToPointer();
Is either of that is valid to get the handle. 两者中的任何一个是否有效都可以获取该句柄。
How do I marshal that handle to c++ HWND
type. 我如何将其编组为c ++
HWND
类型的HWND
。 IntPtr
seems like obvious choice, but it does not work. IntPtr
似乎是显而易见的选择,但它不起作用。
Here is what I am using to subscribe to events 这是我用来订阅活动的东西
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()
{
}
}
I've tried IntPtr
and int
for HWND
marshalling, neither works. 我已经尝试过将
IntPtr
和int
用于HWND
编组,但都没有用。 Also I am not sure how I am supposed to catch window message based events, there is very little online if anything. 另外,我不确定应该如何捕获基于窗口消息的事件,几乎没有在线资源。
Any help appreciated. 任何帮助表示赞赏。
In general using an IntPtr is corrent. 通常,使用IntPtr是正确的。
Handle()
Returns such a IntPtr. 返回这样的IntPtr。
It looks like that you're trying to use your process HWND to get window messages which will not work because you have to use a window HWND to get the messages associated to that HWND. 似乎您正在尝试使用进程HWND来获取无法使用的窗口消息,因为您必须使用窗口HWND来获取与该HWND关联的消息。
Eventually found a way to make this work, it involves creating a window through c++ pinvoke. 最终找到了一种实现此目的的方法,它涉及通过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);
}
}
}
Run this in your main Method in the main thread and your menu/gui in secondary thread 在主线程的main方法和辅助线程的menu / gui中运行此命令
Task.Run(ShowMenu);
_customWindow.GetMessage();
Importer is custom class containing c++ marshalled functions to create/handle window, look the up by the name as they are the same. Importer是包含c ++编组函数以创建/处理窗口的自定义类,请按名称查找,因为它们相同。 All CAPS class/struct are windows/c++ api structs, those can be found on official msdn.
所有CAPS类/结构都是Windows / C ++ API结构,可以在官方msdn上找到。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.