Event "Active Window Changed" abfangen

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von jvbsl.

    Event "Active Window Changed" abfangen

    Hi,

    Ich habe eine Anwendung A geschrieben, die den Titel des aktiven Windows anzeigen kann.

    Die Anwendung A soll im Hintergrund laufen und immer dann, wenn bestimmte Fenster aktiviert werden, wenn ich also etwa das Fenster der Anwendung B auswähle, dann sollen Informationen dazu am Bildschirm zusätzlich angezeigt werden.

    Natürlich kann ich innerhalb der Anwendung A einen Timer starten und z.B. jede Sekunde nachgucken, ob sich die aktuelle Anwendung geändert hat. Besser gefallen würde es mir aber, wenn die Anwendung A auf das Ereignis "Active Window Changed" wartet, also erst dann aufwacht, wenn es auch etwas zu tun gibt.

    Wie fange ich denn in VB Ereignisse ab, die außerhalb meiner Anwendung A liegen? Geht das überhaupt mit "Bordmitteln"? Irgendwie habe ich dazu im Netz nichts gefunden.

    LG
    Peter

    Peter329 schrieb:

    Wie fange ich denn in VB Ereignisse ab, die außerhalb meiner Anwendung A liegen?
    Möglicherweise reicht es, die WndProc zu überschreiben und die Parameter richtig auszuwerten.


    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    Möglicherweise reicht es, die WndProc zu überschreiben und die Parameter richtig auszuwerten.


    Und wie überschreibe ich die WndProc? Welche Parameter hat die? Und wie werte ich die aus?

    Fragen über Fragen!

    LG
    Peter
    irgendwann muss glaub jeder mal doch seine Nase in ein gutes Buch stecken Entwickler-Ressourcen und Tools, Bücher und WebCasts
    Überschreiben ist ein OOP-Feature, und empfehle ich dir, dich fundiert sachkundig zu machen.

    Aber natürlich geht auch quick & dirty Info:
    tipp einfach innerhalb des Forms overrides WndProc und Enter drücken, dann generiert dir der Editor eine richtige und sicher angelegte Überschreibung.
    Zu den Argumenten dann im ObjectBrowser nachgucken, und auf MSDN.

    Edit: ups - jetzt erst deine ursprüngliche Frage gelesen.
    Nein, eine WndProc - Überschreibung hilft dir überhaupt nicht, um zu ermitteln welches Fenster einer anneren Anwendung grad aktiv ist.
    WndProc verarbeitet nur Messages der eigenen Anwendung.
    Allenfalls, wenn dein Fenster in den Vorder- oder Hinter-grund geht kan WndProc vermelden.

    Und sorry, ich weiß auch nicht, wie's denn dann geht.
    Auch gefällt mir das Thema nicht wirklich geht mir schon bisserl in Richtung Fremdanwendungen überwachen und auszuspionieren.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    okie ... das mit der WndProc have ich jetzt in Ansätzen verstanden:

    VB.NET-Quellcode

    1. Protected Overrides Sub WndProc(ByRef msg As System.Windows.Forms.Message)
    2. Debug.Print(msg.Tostring) 'perform WndProc evaluation
    3. MyBase.WndProc(msg) 'invoke original function
    4. End Sub


    Aber wie schon vermerkt, hilft das nicht weiter, weil das Event "Active Window Changed" die WndProc NICHT auslöst.

    Schade! Trotzdem vielen Dank für die Ratschläge!

    LG
    Peter

    Gonger96 schrieb:

    Gibt da glaube ich keine Message für, braucht ja auch keine Anwendung. Du müsstest nen Hook setzen.

    Mhh ... und wie macht man das jetzt ... ?

    [edit] ... hab deinen Update erst jetzt mitbekommen. Also, nach SetWinEventHook werde ich mal schauen ... Danke für den Rat ...

    LG
    Peter
    So, da bin ich wieder ... :)

    Unter "SetWinEventHook" kriegt man in Google einen MSDN Link serviert, in dem exemplarisch dargestellt wird, wie man einen "Mouse-Hook" implementiert. Die aktuellen Mouse Koordinaten werden in der Titel Zeile eingeblendet.

    Das Coding verwendet leider eine "deprecated function" und daran scheitere ich, wenn ich die Sache nachvollziehen will:

    VB.NET-Quellcode

    1. hookproc = AddressOf MouseHookProc
    2. hHook = SetWindowsHookEx(WH_MOUSE, _
    3. hookproc, _
    4. IntPtr.Zero, _
    5. AppDomain.CurrentDomain.GetCurrentThreadId())


    Warnung 1 "Public Shared Function GetCurrentThreadId() As Integer" ist veraltet: "AppDomain.GetCurrentThreadId has been deprecated because it does not provide a stable Id when managed threads are running on fibers (aka lightweight threads). To get a stable identifier for a managed thread, use the ManagedThreadId property on Thread. go.microsoft.com/fwlink/?linkid=14202".

    Der Link hilft leider nicht viel weiter. Da wird nur gesagt, dass man sich angucken soll, wie die neue Funktionalität aussieht. Da wäre ich dann von alleine nicht drauf gekommen! :)

    Also, soweit ich das verstehe, ist die Anweisung

    AppDomain.CurrentDomain.GetCurrentThreadId()

    veraltet und man soll das durch irgendwas anderes ersetzen. Aber das überfordert mich jetzt leider ... kann mir jemand weiter helfen?

    LG
    Peter

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Peter329“ ()

    Ohne alles gelesen zu haben soll die Meldung einfach aussagen, dass du eine nicht veralterte Property verwenden solltest.
    Nämlich "Thread.ManagedThreadId" -> msdn.microsoft.com/en-us/libra…edthreadid(v=vs.110).aspx

    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten

    VB.NET-Quellcode

    1. hHook = SetWindowsHookEx(WH_MOUSE, _
    2. hookproc, _
    3. IntPtr.Zero, _
    4. System.Thread.ManagedThreadId())


    Fehler 1 "Thread" ist kein Member von "System".

    Irgendwie klappt das nicht .... :(

    LG
    Peter
    Wow, das war aber jetzt super nett von dir!

    Die Syntax stimmt jetzt! Herzlichen Dank also für deinen Rat und deine Geduld!

    Nun mache ich mich dran, die Sache auszutesten ... mal gucken was das wird! :D

    LG
    Peter
    So ... jetzt hab ich die Sache ausprobiert. Ich hab mal den Code mit meinen Korrekturen und Kommentaren eingestellt ...

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices 'Required for mouse hook
    2. 'Call original code upon exit from hook
    3. Public Delegate Function CallBack( _
    4. ByVal nCode As Integer, _
    5. ByVal wParam As IntPtr, _
    6. ByVal lParam As IntPtr) As Integer
    7. Public Class Form1
    8. '----------------------------------------------------------------------------------------------
    9. 'Implement mouse hook routines
    10. '----------------------------------------------------------------------------------------------
    11. 'Declare the mouse hook constant.
    12. 'For other hook types, obtain these values from Winuser.h in Microsoft SDK.
    13. Dim WH_MOUSE As Integer = 7
    14. Shared hHook As Integer = 0
    15. 'Keep the reference so that the delegate is not garbage collected.
    16. Private hookproc As CallBack
    17. 'Import for the SetWindowsHookEx function.
    18. <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
    19. Public Overloads Shared Function SetWindowsHookEx _
    20. (ByVal idHook As Integer, ByVal HookProc As CallBack, _
    21. ByVal hInstance As IntPtr, ByVal wParam As Integer) As Integer
    22. End Function
    23. 'Import for the CallNextHookEx function.
    24. <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
    25. Public Overloads Shared Function CallNextHookEx _
    26. (ByVal idHook As Integer, ByVal nCode As Integer, _
    27. ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
    28. End Function
    29. 'Import for the UnhookWindowsHookEx function.
    30. <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
    31. Public Overloads Shared Function UnhookWindowsHookEx _
    32. (ByVal idHook As Integer) As Boolean
    33. End Function
    34. 'Point structure declaration.
    35. <StructLayout(LayoutKind.Sequential)> Public Structure Point
    36. Public x As Integer
    37. Public y As Integer
    38. End Structure
    39. 'MouseHookStruct structure declaration.
    40. <StructLayout(LayoutKind.Sequential)> Public Structure MouseHookStruct
    41. Public pt As Point
    42. Public hwnd As Integer
    43. Public wHitTestCode As Integer
    44. Public dwExtraInfo As Integer
    45. End Structure
    46. '----------------------------------------------------------------------------------------------
    47. 'Process hook routine
    48. '----------------------------------------------------------------------------------------------
    49. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    50. If hHook.Equals(0) Then
    51. hookproc = AddressOf MouseHookProc
    52. hHook = SetWindowsHookEx(WH_MOUSE, _
    53. hookproc, _
    54. IntPtr.Zero, _
    55. Threading.Thread.CurrentThread.ManagedThreadId())
    56. 'AppDomain.CurrentDomain.GetCurrentThreadId())
    57. If hHook.Equals(0) Then
    58. MsgBox("SetWindowsHookEx Failed")
    59. Return
    60. Else
    61. Button2.Text = "UnHook Windows Hook"
    62. End If
    63. Else
    64. Dim ret As Boolean = UnhookWindowsHookEx(hHook)
    65. If ret.Equals(False) Then
    66. MsgBox("UnhookWindowsHookEx Failed")
    67. Return
    68. Else
    69. hHook = 0
    70. Button2.Text = "Set Windows Hook"
    71. Me.Text = "Mouse Hook"
    72. End If
    73. End If
    74. End Sub
    75. Public Shared Function MouseHookProc( _
    76. ByVal nCode As Integer, _
    77. ByVal wParam As IntPtr, _
    78. ByVal lParam As IntPtr) As Integer
    79. Dim MyMouseHookStruct As New MouseHookStruct()
    80. 'Dim ret As Integer
    81. If (nCode < 0) Then
    82. Return CallNextHookEx(hHook, nCode, wParam, lParam)
    83. End If
    84. MyMouseHookStruct = CType(Marshal.PtrToStructure(lParam, MyMouseHookStruct.GetType()), MouseHookStruct)
    85. Dim tempForm As Form
    86. tempForm = Form.ActiveForm()
    87. Dim strCaption As String
    88. strCaption = "x = " & MyMouseHookStruct.pt.x & " y = " & MyMouseHookStruct.pt.y
    89. tempForm.Text = strCaption
    90. Return CallNextHookEx(hHook, nCode, wParam, lParam)
    91. End Function


    Es geht um den Aufruf
    hHook = SetWindowsHookEx(WH_MOUSE, _
    hookproc, _
    IntPtr.Zero, _
    Threading.Thread.CurrentThread.ManagedThreadId())

    Der liefert hHook = 0 .... und damit die Meldung "SetWindowsHookEx Failed" ...

    Die übergebenen Parameter, z.b. WH_Mouse = 7, sehen ordentlich aus. Nur es passiert halt nix! Wie kann ich das denn jetzt debuggen? Oder weiß jemand sagar, was ich falsch mache?

    LG
    Peter
    Du willst keinen Mouse-Hook, du willst einen WndProc Hook
    pinvoke.net/default.aspx/user32.setwindowlong
    pinvoke.net/default.aspx/user32.getwindowlong
    pinvoke.net/default.aspx/user32.callwindowproc
    Erst liest du den aktuellen WndProc-Funktionspointer aus. Dann erstellst du einen Delegaten(WndProc-Signatur) auf deine Methode, die ausgeführt werden soll und setzt mit SetWindowLong den neuen WndProc.
    Innerhalb deiner Methode musst du dann nur noch mit CallWindowProc die Alte WndProc am Ende aufrufen...

    Innerhalb deiner Methode willst du außerdem auf bestimmte Dinge reagieren:
    Z.B. das hier könnte das sein, was du suchst: msdn.microsoft.com/de-de/libra…op/ms646274(v=vs.85).aspx
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---