Hi,
eines der Grundprinzipien von schönem Programmieren ist, Code-Wiederholungen zu vermeiden, auch wenn es um mehrere Projekte geht.
Ich habe öfters den Fall, dass ich auch Doppelklicks auf ListViews auswerten muss. Und jedes mal musste ich den selben Code per GUIRegisterMsg (WM_NOTIFY) nehmen. Unschön.
Das Problem, wieso sich sowas schlecht in allgemeine Funktionen auslagern lässt, ist, dass AutoIt nur einen Message-Handler pro Message zulässt. Wenn ich also bei einer UDF auf Basis von GUIRegisterMsg WM_NOTIFY noch für etwas anderes brauche, ist die UDF hinfällig. Ich habe jetzt eine allgemeine Funktion auf Basis der Windows-Internen Funktion SetWindowLong bzw. SetWindowLongPtr geschrieben.
Dabei wird die WndProc (die Funktion, welche das Message-Handling übernimmt (geschieht in AutoIt intern)) des Parent-Fensters durch eine andere, selbstgeschriebene Funktion ausgetauscht, welche dann die Überwachung von WM_NOTIFY vornimmt. Gegebenenfalls wird dann eine festgelegte Callback-Funktion zur Verarbeitung aufgerufen. Danach wird dann die originale WndProc ausgeführt.
WICHTIG: Um die Message-Verwaltung nicht unnötig schlecht zu beeinflussen, sollte in der Callback-Funktion von verzögernden Aktionen (Sleeps, User-Interaktionen...) abgesehen werden!!!
Am besten erkennt man das an dem schönen Beispiel. Auch sieht man dort ein kleines Gimmik:
Die Parameter der Callback-Funktion können je nach Bedarf variiert werden - ganz, wie der Programmierer es braucht. Das Prinzip sollte ja z.B. von mehreren Konstruktoren einer Klasse bekannt sein.
Dabei ist die Anzahl der Parameter entscheidend:
Bei x Parametern wird die Funktion mit diesen Werten in dieser Reihenfolge aufgerufen
2 Parameter -> Func(Item-Nummer, Klick-Art)
3 Parameter -> Func(Item-Nummer, SubItem-Nummer, Klick-Art)
4 Parameter -> Func(Item-Nummer, SubItem-Nummer, Klick-Art, ListView-Handle)
Die Klick-Art sagt einfach aus, was für ein Klick erfolgt ist: Linksklick, Rechtsklick, Doppellinksklick, Doppelrechtsklick.
Zur Überprüfung stehen 4 Konstanten zur Verfügung:
$LVIC_CLICK
$LVIC_RCLICK
$LVIC_DOUBLE
$LVIC_RDOUBLE
Alles, was jetzt noch unverständlich klingt, erklärt das Beispiel, hoffe ich:
Spoiler anzeigen
#include "ListViewItemClick.au3"
#include <GuiListView.au3>
$sDisplayClicked_Format = "Item mit der Nummer %i wurde geklickt: %s"
[/autoit] [autoit][/autoit] [autoit];init
$hWnd = GUICreate("ListViewItemClick Beispiel", 600, 400)
$hListView = _GUICtrlListView_Create($hWnd, "", 0, 0, 400, 400)
_GUICtrlListView_SetExtendedListViewStyle($hListView, $LVS_EX_FULLROWSELECT)
$cDisplayClicked = GUICtrlCreateLabel("", 410, 10, 180, 40)
[/autoit] [autoit][/autoit] [autoit];data
_GUICtrlListView_AddColumn($hListView, "My Random Number", 383)
For $i = 1 To 25
_GUICtrlListView_AddItem($hListView, Random(0, 100, True))
Next
GUISetState()
[/autoit] [autoit][/autoit] [autoit];Funktion registrieren
_LVIC_RegisterClickFunc($hListView, ClickFunc)
While True
Switch GUIGetMsg()
Case -3
Exit
EndSwitch
WEnd
;Beliebigen Funktionsheader verwenden!
[/autoit] [autoit][/autoit] [autoit];~ Func ClickFunc($iItem, $iAction) ; <-- Wäre hier ausreichend
;~ Func ClickFunc($iItem, $iSub, $iAction)
Func ClickFunc($iItem, $iSub, $iAction, $hListView)
Local $sAction
Switch $iAction
Case $LVIC_CLICK
$sAction = "Linksklick"
Case $LVIC_RCLICK
$sAction = "Rechtsklick"
Case $LVIC_DOUBLE
$sAction = "Doppelklick"
Case $LVIC_RDOUBLE
$sAction = "Doppelrechtsklick (Wer tut sowas?)"
EndSwitch
GUICtrlSetData($cDisplayClicked, StringFormat($sDisplayClicked_Format, $iItem, $sAction))
EndFunc
Die UDF selber besteht im wesentlichen nur aus einer Funktion: _LVIC_RegisterClickFunc
Diese Funktion benötigt zwei Parameter... Das ListView-Handle und die Callback-Funktion. Ganz einfach.
Wenn zum Erstellen der interne Befehl (GUICtrlCreateListView) genutzt wird, dann muss vorher das Handle per GUICtrlGetHandle ermittelt werden.
So, die UDF selber ist im Anhang.
Lob, Kritik und Wünsche sind natürlich erwünscht.
Gruß