c# - 通过来自 c# net core 的非托管 c++ dll 订阅 Windows 消息

标签 c# c++ .net-core managed windows-messages

我正在尝试使用 pinvoke 通过 unamanged c++ dll 从 c# net core 订阅 Windows 消息事件/消息系统。

我遇到的问题。

获取我的进程的句柄或创建一个空窗口(.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()
    {
    }
}

我已尝试使用 IntPtrint 进行 HWND 编码,但均无效。 此外,我不确定我应该如何捕获基于窗口消息的事件,如果有的话,在线的很少。

感谢任何帮助。

最佳答案

最终找到了一种方法来完成这项工作,它涉及通过 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);
        }
    }
}

在主线程中的 main 方法中运行它,在辅助线程中的菜单/GUI 中运行它

 Task.Run(ShowMenu);

 _customWindow.GetMessage();

Importer 是自定义类,包含用于创建/处理窗口的 C++ 编码函数,请按名称查找,因为它们是相同的。所有 CAPS 类/结构都是 windows/c++ api 结构,可以在官方 msdn 上找到。

关于c# - 通过来自 c# net core 的非托管 c++ dll 订阅 Windows 消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50062231/

相关文章:

C# 在继承类中为父属性添加自定义属性

c# - 如何以编程方式确定 Jet 数据库引擎类型

c# - 需要从 XML 中获取值

c++ - C++动态库中的导出函数

nuget - dotnet core 是否有命令行包安装程序

c# - 我应该选择哪个版本的 EntityFramework for MySQL?

c++ - 重新编译未修改的文件

c++ - std::map 中值的内存分配

c# - 在 .NET Core 上创建 HttpMessageHandler,可以向我自己发出请求

c# - 让 dotnet core 2.0.0 Socket.Listen() 支持 UNIX Domain Socket?