2010-07-20 7 views
7

Ich schreibe eine C# -Anwendung, die Window Messages abfangen muss, die eine andere Anwendungen sendet. Die Firma, die die Anwendung geschrieben hat, die ich überwache, hat mir einen Beispielcode geschickt, allerdings in C++, den ich nicht wirklich kenne.C# - Erfassen von Windows-Meldungen aus einer bestimmten Anwendung

In der C++ Beispielcode ich sie den folgenden Code verwenden haben:

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

Wie ich es dieses ruft eine Id von Windows für die spezifische Botschaft verstehen wir hören möchten. Dann bitten wir C++, OnShockStatusMessage immer dann aufzurufen, wenn eine Nachricht mit der ID abgefangen wird.

Nach ein wenig Forschung habe ich zusammen die folgenden in setzen 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!"); 
    } 

} 

Wie ich verstehe dies die gleiche grundlegende Sache tun sollten, ist, daß es:

  1. Findet die Anwendung I möchte überwachen
  2. Registriert die Window Messages, die ich abfangen möchte
  3. Uhren für alle Window Messages - dann löscht diejenigen, die ich brauche

jedoch in meiner Überschreibung der WndProc() Methode weder meine Kontrollen Intercept eine der spezifischen Nachrichten oder jede Nachricht aus der Anwendung Ich bin Überwachung.

Wenn ich Debug.WriteLine für alle Nachrichten, die durch sie kommen, kann ich sehen, dass es sie überwacht. Es filtert jedoch niemals die Nachrichten heraus, die ich möchte.

Durch Ausführen der Beispiel-Monitoring-Anwendung in C++ geschrieben, kann ich sehen, dass Window Messages gesendet und abgeholt werden - es ist nur meine C# -Implementierung tut nicht das Gleiche.

Antwort

1

Es stellte sich heraus, dass ich auch die andere Anwendung eine PostMessage senden musste und sie bat, meine Anwendung die Window Messages zu senden.

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); 

Nicht schön Code, aber gut genug, um zu beweisen, dass es funktioniert, das alles was ich brauche jetzt ist :)

0

Ich denke, das Problem ist mit Ihrer P/Invoke-Definition für RegisterWindowMessage(). pinvoke.net schlägt folgende Verwendung:

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

Mit uint als Rückgabewert statt IntPtr soll den Unterschied machen. Normalerweise möchten Sie IntPtr verwenden, wenn der Rückgabewert ein Handle ist (z. B. HWND oder HANDLE), aber wenn der Rückgabewert direkt in einen C# -Typ konvertiert werden kann, ist es besser, diesen Typ zu verwenden.

+0

Der Beispielcode Sie hier gegeben habe, ist eigentlich das, was ich im Moment bin mit :) –

+0

@Peter Ah, verpasste das. Warum hast du die Liste eine Liste von IntPtr gemacht? Warum nicht einfach Liste machen? ? – Andy

+0

Ich erwarte, dass es nur die [DllImport] -Anweisungen von verschiedenen Webseiten kopieren würde, um zu sehen, ob es einen Unterschied machte, aber jeder hatte leichte Unterschiede. –

Verwandte Themen