繁体   English   中英

从C ++ DLL向.NET应用程序发送通知

[英]Sending notifications from C++ DLL to .NET application

我正在编写需要通知客户端应用程序的C ++ DLL。 在C ++(MFC)中,我可以在DLL中注册一个客户端窗口句柄,然后在需要通知客户端某些事情时调用PostMessage。 客户端是C#应用程序时该怎么办?

PostMessage只是告诉Windows将消息发布到另一个应用程序的主应用程序循环。 如果客户端是C#应用程序,几乎可以肯定会做同样的事情,因此,更正确的问题是,如何读取在C#中发送到主应用程序循环的消息。

您可以在C#窗口中重写WndProc方法来处理此特定消息

protected override void WndProc(ref Message m)
{
    if (m.Msg = YOUR_MESSAGE)
    {
        // handle the notification
    }
    else
    {
        base.WndProc(ref m);
    }
}

可以通过将消息发布到Windows句柄来完成。 在dotnet类中,创建一个虚拟窗口,该窗口可以拦截消息,然后触发消息。

这是一些代码,您只需要填写我使用WM_MYMESSAGE的位置即可引用正确的Windows消息,现在可以在C ++ dll中向其发布消息。 请注意,我敢肯定有更好/其他的方式来做你想做的事,但这也许也可以。

//Dummy window classes.  Because we don't have access to the wndproc method of a form, we create
//dummy forms and expose the method to the SystemHotKeyHook class as an event.

/// <summary>
/// Inherits from System.Windows.Form.NativeWindow. Provides an Event for Message handling
/// </summary>
private class NativeWindowWithEvent : System.Windows.Forms.NativeWindow
{
    public event MessageEventHandler ProcessMessage;
    protected override void WndProc(ref Message m)
    {
        //Intercept the message you are looking for...
        if (m.Msg == (int)WM_MYMESSAGE)
        {
            //Fire event which is consumed by your class
            if (ProcessMessage != null)
            {
                bool Handled = false;
                ProcessMessage(this, ref m, ref Handled);
                if (!Handled)
                {
                    base.WndProc(ref m);
                }
            }
            else
            {
                base.WndProc(ref m);
            }
        }
        else
        {
            base.WndProc(ref m);
        }
    }
}
/// <summary>
/// Inherits from NativeWindowWithEvent and automatic creates/destroys of a dummy window
/// </summary>
private class DummyWindowWithEvent : NativeWindowWithEvent, IDisposable
{
    public DummyWindowWithEvent()
    {
        CreateParams parms = new CreateParams();
        this.CreateHandle(parms);
    }
    public void Dispose()
    {
        if (this.Handle != (IntPtr)0)
        {
            this.DestroyHandle();
        }
    }
}

拦截消息的类:

// <summary>
/// System hotkey interceptor
/// </summary>
public class MessageIntercept: IDisposable
{
    private delegate void MessageEventHandler(object Sender, ref System.Windows.Forms.Message msg, ref bool Handled);

    //Window for WM_MYMESSAGE Interceptor
    private DummyWindowWithEvent frmDummyReceiver_m;

    /// <summary>
    /// Default constructor
    /// </summary>
    public MessageIntercept()
    {
        this.frmDummyReceiver_m = new DummyWindowWithEvent();
        this.frmDummyReceiver_m.ProcessMessage += new MessageEventHandler(this.InterceptMessage);
    }

    private void InterceptMessage(object Sender, ref System.Windows.Forms.Message msg, ref bool Handled)
    {
        //Do something based on criteria of the message
        if ((msg.Msg == (int)WM_MYMESSAGE) && 
            (msg.WParam == (IntPtr)xyz))
        {
            Handled = true;
            System.Diagnostics.Debug.WriteLine("Message intercepted.");
        }
    }
}

根据两者的紧密程度,我可能会使用回调/事件方法。

对我而言,整个“ PostMessage”方法似乎有点破烂(取决于您要执行的操作,如果这是您要发布的标准消息,那显然很好)

您可以为本机类创建托管C ++包装器,该托管包装器可以处理回调并发出托管(C#兼容)事件,C#类可以侦听该事件。

通常,我非常喜欢通过托管C ++层将本机C ++链接到C#-这样,您的C#应用​​程序就不需要知道本机C ++代码的所有“丑陋”低级细节。

如果要实现穷人的发布-订阅模式,则可以使用回调。 这个线程中有一些不错的信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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