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

问题描述:

我在写一个需要通知客户端应用程序的C++ DLL。在C++(MFC)中,我可以在DLL中注册一个客户端窗口句柄,然后在需要通知客户端某事时调用PostMessage。当客户端是C#应用程序时,我能做些什么?将通知从C++ DLL发送到.NET应用程序

您可以覆盖在C#窗口WndProc方法来处理这个特定的消息

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

PostMessage只是告诉Windows向另一个应用程序的主应用程序循环发出消息。如果客户端是C#应用程序,几乎肯定会做同样的事情,所以更合适的问题是,如何读取发送到C#中主应用程序循环的消息。

+0

对。答案是......? – Curtis 2009-06-04 22:36:25

如果你想实现一个穷人版的发布 - 订阅模式,回调是要走的路。在this thread有一些很好的信息。

通过发送消息到窗口句柄可以做到这一点。在你的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++代码的所有“丑陋”低级细节。