简体   繁体   English

通过C#Net Core的非托管C ++ DLL订阅Windows消息

[英]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. 我已经尝试过将IntPtrint用于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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM