C# - 捕获来自特定应用程序的Windows消息

时间:2010-07-20 11:12:49

标签: c# .net c++ mfc windows-messages

我正在编写一个C#应用程序,需要拦截另一个应用程序发出的窗口消息。编写我正在监控的应用程序的公司给我发了一些示例代码,但它是用C ++编写的,我真的不知道。

在C ++示例代码中,我使用了以下代码:

 UINT uMsg = RegisterWindowMessage(SHOCK_MESSAGE_BROADCAST);
 ON_REGISTERED_MESSAGE(WM_SHOCK_BROADCAST_MESSAGE, OnShockStatusMessage)
 LRESULT OnShockStatusMessage(WPARAM wParam, LPARAM lParam);

据我了解,这会从Windows中检索我们想要侦听的特定消息的Id。然后我们要求C ++在拦截与Id匹配的消息时调用 OnShockStatusMessage

经过一番研究后,我将以下内容放在C#中

[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);

private IntPtr _hWnd; // APS-50 class reference
private List<IntPtr> _windowsMessages = new List<IntPtr>(); // APS-50 messages

private const string _className = "www.AuPix.com/SHOCK/MessageWindowClass";

// Windows Messages events
private const string _messageBroadcast = "www.AuPix.com/SHOCK/BROADCAST";
private const string _messageCallEvents = "www.AuPix.com/SHOCK/CallEvents";
private const string _messageRegistrationEvents = "www.AuPix.com/SHOCK/RegistrationEvents";
private const string _messageActions = "www.AuPix.com/SHOCK/Actions";

private void DemoProblem()
{
    // Find hidden window handle
    _hWnd = FindWindow(_className, null);

    // Register for events
    _windowsMessages.Add( new IntPtr( RegisterWindowMessage( _messageActions ) ) );
    _windowsMessages.Add( new IntPtr( RegisterWindowMessage( _messageBroadcast ) ) );
    _windowsMessages.Add( new IntPtr( RegisterWindowMessage( _messageCallEvents ) ) );
    _windowsMessages.Add( new IntPtr( RegisterWindowMessage( _messageRegistrationEvents ) ) );
}

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);

    // Are they registered Windows Messages for the APS-50 application?
    foreach (IntPtr message in _windowsMessages)
    {
        if ((IntPtr)m.Msg == message)
        {
            Debug.WriteLine("Message from specified application found!");
        }
    }

    // Are they coming from the APS-50 application?
    if ( m.HWnd == shock.WindowsHandle)
    {
        Debug.WriteLine("Message from specified application found!");
    }

}

据我所知,这应该做同样的基本事情,因为它:

  1. 查找我想要监控的应用程序
  2. 注册我想拦截的窗口消息
  3. 观看所有窗口消息 - 然后删除我需要的窗口消息
  4. 然而,在我覆盖 WndProc()方法时,我的检查都没有拦截任何特定消息或来自我正在监控的应用程序的任何消息。

    如果我 Debug.WriteLine 所有通过它的消息,我可以看到它正在监视它们。但是它永远不会过滤掉我想要的消息。

    通过运行用C ++编写的示例监视应用程序,我可以看到正在发送和拾取窗口消息 - 这只是我的C#实现不会这样做。

2 个答案:

答案 0 :(得分:1)

原来我还需要向其他应用程序发送一个 PostMessage ,要求它向我的应用程序发送Window Messages。

PostMessage((int)_hWnd, _windowsMessages[0], SHOCK_REQUEST_ACTIVE_CALLINFO, (int)_thisHandle);
PostMessage((int)_hWnd, _windowsMessages[0], SHOCK_REQUEST_ALL_REGISTRATIONINFO, (int)_thisHandle);
PostMessage((int)_hWnd, _windowsMessages[0], SHOCK_REQUEST_CALL_EVENTS, (int)_thisHandle);
PostMessage((int)_hWnd, _windowsMessages[0], SHOCK_REQUEST_REGISTRATION_EVENTS, (int)_thisHandle);

不是漂亮的代码,但足以证明它的工作原理我现在需要的只是:)

答案 1 :(得分:0)

我认为问题在于RegisterWindowMessage()的P / Invoke定义。 pinvoke.net建议使用以下内容:

[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);

使用uint作为返回值而不是IntPtr应该会有所不同。通常,当返回值是句柄(例如IntPtrHWND)时,您希望使用HANDLE,但是当返回值可以直接转换为C#类型时,它会更好使用那种类型。