Post by Michael Landenbergereine von TListView abgeleitete Komponente im vsReport-Stil reagiert nur sehr
unzuverlässig auf MouseUp-Ereignisse.
Das Problem nervt :-( Ich habe eben ein simples Testprojekt mit einem Formular
angelegt, auf das ich ein TListView mit ViewStyle = vsReport gesetzt habe.
Unter Windows 10 (1709) lässt sich das Problem reproduzieren: wenn die
Eigenschaft MultiSelect des Listviews auf TRUE gesetzt wird, wird ca. die
Hälfte aller MouseDown- und MouseUp-Events einfach ignoriert. Bei Multiselect
= FALSE verhält sich das Listview dagegen ganz normal, alle Mausaktionen
werden ordnungsgemäß ausgewertet.
Um der Sache auf den Grund zu gehen, habe ich in meiner Komponente den Handler
für WM_LBUTTONDOWN-Botschaften überschrieben. Testweise habe ich in den
überschriebenen Handler vor dem Aufruf des vererbten Handlers einen Befehl zum
Simulieren des Loslassens der linken Maustaste (mittels SendInput ())
eingebaut. Dabei stellte sich heraus, dass bei diesem simulierten Loslassen
*keine* WM_LBUTTONUP-Botschaft an die TListView-Komponente geschickt wird. Das
ist unnormal (normalerweise generieren auch simulierte Benutzeraktionen die
entsprechenden Botschaften). Auf das anschließende, tatsächliche Loslassen der
linken Maustaste hat das Programm dann aber ganz normal reagiert.
Jetzt habe ich folgenden Workaround programmiert, der zwar funktioniert, bei
dem mir aber nicht sonderlich wohl ist:
1. Zunächst habe ich meiner Komponente zwei private-Eigenschaften verpasst:
eine Boolean-Eigenschaft "FButtonDown" und eine Integer-Eigenschaft
"FApplyMouseFix". Letztere wird beim Erstellen der Komponente auf 0
initialisiert.
2. Ich habe die Botschafts-Handler WMLButtonDown und WMLButtonUp in meiner
Komponente überschrieben. In WMLButtonDown wird FButtonDown auf TRUE gesetzt,
in WMLButtonUp wieder auf FALSE. Danach wird der geerbte Handler aufgerufen,
um das normale Verhalten der Komponente sicherzustellen.
3. In WMLButtonDown wird zusätzlich FApplyMouseFix abgefragt. Die Eigenschaft
kann 3 gültige Werte annehmen: 0 bedeutet, dass das Vorhandensein des Fehlers
geprüft werden soll. Tritt er *nicht* auf, wird FApplyMouseFix auf 1 gesetzt.
Dieser Wert bedeutet, dass keine erneute Prüfung stattfinden und der
Workaround nicht angewendet werden soll. Ist der Fehler jedoch vorhanden, wird
FApplyMouseFix auf 2 gesetzt. Bei diesem Wert erfolgt ebenfalls keine erneute
Prüfung, allerdings wird dann aber bei jedem Drücken der linken Maustaste der
Workaround angewandt.
4. Die Prüfung auf Vorhandensein des Fehlers habe ich so realisiert:
Beim Drücken der linken Maustaste wird innerhalb des Botschafts-Handlers
WMLButtonDown mittels SendInput () ein Loslassen der linken Maustaste
simuliert. Normalerweise generiert das eine WM_LBUTTONUP-Botschaft, welche in
WMLButtonUp ausgewertet wird. Dort wird, wie geschrieben, die Eigenschaft
FButtonDown auf FALSE gesetzt. Ist die Eigenschaft nach dem simulierten
Loslassen aber immer noch TRUE, dann weiß meine Komponente, dass
Mausbotschaften nicht korrekt verarbeitet werden, d. h. dass der Fehler
vorhanden ist. In diesem Fall wird FApplyMouseFix auf 2 gesetzt, mit den unter
3. beschriebenen Konsequenzen. Ist FButtonDown dagegen FALSE, nachdem das
Loslassen simuliert wurde, ist alles ok. In diesem Fall setzt das Programm
FApplyMouseFix auf 1. Zusätzlich wird einmalig ein weiterer Druck auf die
linke Maustaste simuliert, denn ursprünglich wurde diese ja vom Benutzer
gedrückt und die zum Testen erfolgte Simulation des Loslassens soll das nicht
unterlaufen.
5. Bei jedem weiteren Drücken der linken Maustaste wird dann in Abhängigkeit
des Wertes in FApplyMouseFix entweder ein Loslassen der Taste simuliert (als
Workaround) oder nicht.
Entsprechendes habe ich auch für die mittlere und rechte Maustaste
programmiert, denn auch die sind von dem Problem betroffen.
Lange Rede, kurzer Sinn: jetzt macht die Komponente, was sie soll. Allerdings
kann ich nicht glauben, dass man dazu auf einen solchen Hack angewiesen ist.
Es muss noch eine andere Lösung des Problems geben. Was mich auch erstaunt:
man liest im Netz nichts über dieses Problem. Ich kann mir aber nicht
vorstellen, dass es nur auf meinem Rechner und in meiner Konstellation
(Windows 10 1709 mit Delphi 10.1/10.2) auftritt.
Gruß
Michael