Wie findet man heraus, in welcher Reihenfolge welches Event für ein Control gefeuert wird?
Nachdem das Thema im Thread DataGridView / ColumnHeaderMouseClick / Welches Event folgt danach? war und eine Lösung vielleicht etwas untergegangen ist, hier die bisher genannten Möglichkeiten:
EventHandler-Codeerstellung
Man kopiert sich den folgenden Code ins Projekt und führt ihn aus. Nach dem Ausführen des Codes kann man ihn aus dem Projekt löschen.
Spoiler anzeigen
Man erhält eine Datei auf dem Desktop, die alle EventHandler des übergebenden Controls enthält. Den Dateiinhalt kopiert man sich ins Projekt und macht die gewünschten Aktionen mit dem Ziel-Control. Will man wissen, was nach dem
Wie @RodFromGermany im o.g. Thread erwähnte, haben die EventHandler-Prozedurnamen einen kleinen Zusatz, um nicht in Konflikt mit bestehenden zu geraten.
dynamische EventHandler-Erstellung
Ein bisschen anspruchsvoller (v.a. vom Verständnis) ist die dynamische EventHandler-Erstellung. Leider muss man wohl kompliziert einen passenden Delegaten erstellen, der zum jeweiligen Event passt (Ursprungsquellcode). An der Verwendung von Generika bin ich gescheitert, s. o. erwähnter Thread.
Man führt einmalig die Methode
Spoiler anzeigen
Wie @ErfinderDesRades im o.g. Thread erwähnte, könnte man zu Beginn der For-Schleife auch die Events rausfiltern, die nicht relevant sein dürften, indem man den Event-Namen auswertet.
Man könnte sicherlich auch was über das Erfassen der WndProc-Parameter rausbekommen. Da dort allerdings extrem viele Nachrichten hin- und herwandern, wird das Rausfiltern der relevanten Daten schwierig - falls überhaupt dort alles erfasst wird.
Nachdem das Thema im Thread DataGridView / ColumnHeaderMouseClick / Welches Event folgt danach? war und eine Lösung vielleicht etwas untergegangen ist, hier die bisher genannten Möglichkeiten:
- EventHandler-Codeerstellung
- dynamische EventHandler-Erstellung
EventHandler-Codeerstellung
Man kopiert sich den folgenden Code ins Projekt und führt ihn aus. Nach dem Ausführen des Codes kann man ihn aus dem Projekt löschen.
VB.NET-Quellcode
- Private Sub WriteCodeFor(Control As Control)
- Dim Code As New Text.StringBuilder
- Code.AppendLine("Private Property EventHistory As New List(Of String)")
- Code.AppendLine("Private IgnoreEvents As Boolean = True")
- Code.AppendLine()
- For Each ControlEvent In Control.GetType.GetEvents.OrderBy(Function(x) x.Name)
- Code.AppendLine($"Private Sub {Control.Name}_{ControlEvent.Name}_LoggingCode(sender As Object, e As {ControlEvent.EventHandlerType.GetMethod("Invoke").GetParameters(1).ParameterType.Name}) Handles {Control.Name}.{ControlEvent.Name}")
- Code.AppendLine(" If IgnoreEvents Then Return")
- Code.AppendLine($" EventHistory.Add(""{Control.Name}.{ControlEvent.Name}"")")
- Code.AppendLine("End Sub")
- Code.AppendLine()
- Next
- IO.File.WriteAllText($"{Environment.GetFolderPath(Environment.SpecialFolder.Desktop)}\EventHandlerCode for {Control.Name}.txt", Code.ToString)
- End Sub
Man erhält eine Datei auf dem Desktop, die alle EventHandler des übergebenden Controls enthält. Den Dateiinhalt kopiert man sich ins Projekt und macht die gewünschten Aktionen mit dem Ziel-Control. Will man wissen, was nach dem
MouseClick
auf einen Button passiert, schaltet man im dortigen EventHandler IgnoreEvents
auf False
und erhält alle Folgeevents in der Liste EventHistory
., die man sich zu einem späteren Zeitpunkt ansehen kann.Wie @RodFromGermany im o.g. Thread erwähnte, haben die EventHandler-Prozedurnamen einen kleinen Zusatz, um nicht in Konflikt mit bestehenden zu geraten.
dynamische EventHandler-Erstellung
Ein bisschen anspruchsvoller (v.a. vom Verständnis) ist die dynamische EventHandler-Erstellung. Leider muss man wohl kompliziert einen passenden Delegaten erstellen, der zum jeweiligen Event passt (Ursprungsquellcode). An der Verwendung von Generika bin ich gescheitert, s. o. erwähnter Thread.
Man führt einmalig die Methode
Log
für das gewünschte Zielcontrol aus und das Ergebnis zeigt sich dann in der Konsole/im Ausgabe-Fenster, in der dann die EventHandler Rückmeldung geben.VB.NET-Quellcode
- Imports System.Reflection
- Imports System.Reflection.Emit
- '[…]
- Private Sub Log(Control As Control)
- For Each ControlEvent In Control.GetType().GetEvents
- Dim HandlerType = ControlEvent.EventHandlerType
- Dim InvokeMethod = HandlerType.GetMethod("Invoke")
- Dim Parameters = InvokeMethod.GetParameters()
- Dim ParameterTypes = Parameters.Select(Function(x) x.ParameterType).ToArray
- Dim aName As New AssemblyName() With {.Name = "DynamicTypes"}
- Dim AssemblyBuilder = Emit.AssemblyBuilder.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Run)
- Dim ModuleBuilder = AssemblyBuilder.DefineDynamicModule(aName.Name)
- Dim TypeBuilder = ModuleBuilder.DefineType("Handler", TypeAttributes.Class Or TypeAttributes.Public)
- Dim MethodBuilder = TypeBuilder.DefineMethod("DynamicHandler", MethodAttributes.Public Or MethodAttributes.Static, InvokeMethod.ReturnType, ParameterTypes)
- Dim ILGenerator = MethodBuilder.GetILGenerator()
- ILGenerator.EmitWriteLine($"{Control.Name} löste das Event »{ControlEvent.Name}« aus.")
- ILGenerator.Emit(OpCodes.Ret)
- Dim FinalType = TypeBuilder.CreateType()
- Dim EventHandler = FinalType.GetMethod("DynamicHandler")
- Dim FinalDelegate = [Delegate].CreateDelegate(HandlerType, EventHandler)
- ControlEvent.AddEventHandler(Control, FinalDelegate)
- Next
- End Sub
Wie @ErfinderDesRades im o.g. Thread erwähnte, könnte man zu Beginn der For-Schleife auch die Events rausfiltern, die nicht relevant sein dürften, indem man den Event-Namen auswertet.
Man könnte sicherlich auch was über das Erfassen der WndProc-Parameter rausbekommen. Da dort allerdings extrem viele Nachrichten hin- und herwandern, wird das Rausfiltern der relevanten Daten schwierig - falls überhaupt dort alles erfasst wird.
Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.
Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()