ListView - MouseClick ohne Elemente

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 2 Antworten in diesem Thema. Der letzte Beitrag () ist von Facebamm.

    ListView - MouseClick ohne Elemente

    Hallo :D

    ich hab eine ListView ohne elemente und mochte ein MouseClick performen.
    Problem ist nur, das eine ListView ohne elemente kein MouseClick performt.

    hat jemand eine bessere Lösung als meine?

    C#-Quellcode

    1. private int _rightMouseTriggerCount; // wie oft geklick wurde in der messung
    2. private Task<int> _rightMouseClickTask;
    3. private async void listView1_MouseDownAsync(object sender, MouseEventArgs e)
    4. {
    5. if (e.Button == MouseButtons.Right)
    6. {
    7. if (_rightMouseClickTask == null) // läuft erkennung?
    8. {
    9. _rightMouseTriggerCount = 1; // einzel "klick"
    10. _rightMouseClickTask = _rightMouseClickTaskAsync();
    11. int result = await _rightMouseClickTask;
    12. if(result == 2)
    13. {
    14. } else
    15. {
    16. listView1_MouseClick(sender, e);
    17. }
    18. _rightMouseClickTask = null;
    19. Console.WriteLine(result);
    20. } else // erkennung läuft
    21. {
    22. _rightMouseTriggerCount += 1; // erkannter neuer "klick"
    23. }
    24. }
    25. }
    26. private async Task<int> _rightMouseClickTaskAsync()
    27. {
    28. await Task.Delay(330); // die messung
    29. return _rightMouseTriggerCount > 1
    30. ? 2
    31. : 1;
    32. }
    Einmal Holzhammer in VB.NET:

    VB.NET-Quellcode

    1. Private MouseIsInListView As Boolean = False
    2. Protected Overrides Sub WndProc(ByRef m As Message)
    3. If MouseIsInListView AndAlso m.WParam = New IntPtr(513) Then MessageBox.Show("Linker Mausknopf wurde über dem ListView geklickt.")
    4. MyBase.WndProc(m)
    5. End Sub
    6. Private Sub ListView1_MouseEnter(sender As Object, e As EventArgs) Handles ListView1.MouseEnter
    7. MouseIsInListView = True
    8. End Sub
    9. Private Sub ListView1_MouseLeave(sender As Object, e As EventArgs) Handles ListView1.MouseLeave
    10. MouseIsInListView = False
    11. End Sub

    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.
    Die idee ist ganz cool, aber ich würde noch ein schritt weiter gehen :D

    also im Source habe ich folgendes gefunden:

    Spoiler anzeigen

    C#-Quellcode

    1. // System.Windows.Forms.ListView
    2. // Token: 0x06002A7E RID: 10878 RVA: 0x000C7930 File Offset: 0x000C5B30
    3. private unsafe void WmReflectNotify(ref Message m){
    4. ...
    5. //Zeile 182
    6. int indexOfClickedItem = this.GetIndexOfClickedItem(lvhi);
    7. ...
    8. //Zeile 186
    9. if (!base.ValidationCancelled && indexOfClickedItem != -1)
    10. {
    11. this.OnClick(EventArgs.Empty);
    12. this.OnMouseClick(new MouseEventArgs(button, 1, p.X, p.Y, 0));
    13. }
    14. ...
    15. }


    Was man machen müsste ich die Abfrage for indexOfClickedItem != -1 entfernen...
    Das hab ich gemacht

    Spoiler anzeigen

    C#-Quellcode

    1. class ListViewEx : ListView
    2. {
    3. public unsafe ListViewEx()
    4. {
    5. Type t = typeof(ListViewEx).BaseType;
    6. MethodInfo m = t.GetMethod("WmReflectNotify", BindingFlags.Instance | BindingFlags.NonPublic);
    7. MethodBody body = m.GetMethodBody();
    8. byte[] il = body.GetILAsByteArray();
    9. int size = il.Length;
    10. /* IL-Code
    11. * 365 0431 ldarg.0
    12. * 366 0432 call instance bool System.Windows.Forms.Control::get_ValidationCancelled()
    13. * 367 0437 brtrue.s 381 (0461) ldarg.0
    14. * ** Remove content
    15. * 395 04C3 ldloc.3 (wird zu nop)
    16. * 396 04C4 ldc.i4.m1 (wird zu nop)
    17. * 397 04C5 beq.s 411 (04EF) ldarg.0 (wird zu nop)
    18. * ** End Remove content
    19. */
    20. fixed (byte* ilPtr = il)
    21. {
    22. for (int i = 0; i < size; i++)
    23. {
    24. byte* basePtr = ilPtr + i;
    25. if (*(basePtr) == OpCodes.Ldarg_0.Value
    26. && *(basePtr + 1) == OpCodes.Call.Value
    27. && *(basePtr + 6) == OpCodes.Brtrue_S.Value
    28. && *(basePtr + 8) == OpCodes.Ldloc_3.Value
    29. && *(basePtr + 9) == OpCodes.Ldc_I4_M1.Value
    30. && *(basePtr + 10) == OpCodes.Beq_S.Value
    31. )
    32. {
    33. *(basePtr + 8) = (byte)OpCodes.Nop.Value;
    34. *(basePtr + 9) = (byte)OpCodes.Nop.Value;
    35. *(basePtr + 10) = (byte)OpCodes.Nop.Value;
    36. break;
    37. }
    38. }
    39. }
    40. }
    41. }


    So und jetzt muss ich das ganze nur noch zurück schreiben und da hänge ich.
    Im internet wird immer ein MethodeBuilder o.ä genutzt, aber das verwende ich doch nur dann, wenn ich was neues erzeugen möchte.
    In meinem Fall ist es schon da.

    Was ich weiterhin gefunden habe ich der m.MethodHandle.Value.ToPointer() aber wie komme ich davon aus zum Speicher der Methode so das ich einfach beine Bytes setze oder anders gesagt:
    Wie schreibe ich mein ByteArray zurück in die Methode?