Autor Beitrag
UweK
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 52
Erhaltene Danke: 1

Win 7
Delphi Enterprise XE6
BeitragVerfasst: Mi 12.04.23 15:06 
Hallo,

Wenn ich auf eine Zelle des TStringGrid klicke, wird das Ereignis TStringGrid.OnSelectCell ausgelöst. Gibt es eine Möglichkeit, in dieser Ereignisbehandlung festzustellen, ob das ein einfacher Klick oder ein Doppelklick war?

Zweck der Übung: Bei einem einfachen Klick möchte ich standardmäßig den Text in der Zelle bearbeiten. Beim Doppelklick soll auf bequeme Weise sofort der in der Zelle stehende Text gelöscht und durch einen in einer Variablen schon bereitstehenden neuen Text ersetzt werden. Ohne den alten erst per Tastatur löschen, und dann per Tastenkombination oder rechter Maustaste den neuen Text einfügen zu müssen.

Vielen Dank für Tipps. Gruß Uwe
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4791
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 15.04.23 08:07 
Hallo,

da bisher noch niemand geantwortet hat, versuche ich es mal mit einer Antwort.
Jeder Doppelklick führt automatisch vorher auch ein normales Klick-Ereignis aus (d.h. also bei einem TStringGrid auch zusätzlich OnSelectCell). Um explizit einen Doppelklick abzufragen, müßtest du schon das OnDblClick-Ereignis verwenden (die TStringGrid-Eigenschaften Col und Row geben dann die aktuell selektierte Zelle an).

Persönlich finde ich aber (wenn es sich nicht nur um ein persönliches Projekt bei dir handelt) es ungewöhnlich, daß ein Doppelklick (evtl. unabsichtlich) den Text löscht. Oder gibt es eine Undo-Funktion?
Eine andere Alternative wäre die zusätzliche Verwendung einer Kontrolltaste (wie Ctrl, Shift oder Alt).
UweK Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 52
Erhaltene Danke: 1

Win 7
Delphi Enterprise XE6
BeitragVerfasst: Mo 17.04.23 08:20 
Hallo,

OnDblClick ist leider wie OnClick nur ein allgemeines Ereignis des TStringGrid vom Typ TNotifyEvent. Als einzigen Parameter liefert es mir "ASender: TObject". Nur OnSelectCell liefert auch die Zeile und Spalte der angeklickten Zelle. Aber ein vergleichbares "DblOnSelectCell" oder so gibt es laut Delphi-Hilfe nicht. Zweck meiner Frage war, ob es vielleicht einen Dreh gibt, bei einem Doppelklick auf TStringGrid im Ereignis OnDblClick irgendwo in den internen Variablen von TStringGrid die Zeile und Spalte zu finden.

Falls das nicht möglich ist, muss ich mir halt eine andere Benutzungsart ausdenken, vielleicht mit Drag & Drop versuchen. Lediglich aus Bequemlichkeit sollte alles nur mit der Maus gehen, ohne Zusatztasten drücken zu müssen. Mit Zusatztasten wäre dann der letzte Plan B, wenn es nicht anders geht. Aber da könnte man auch mal vergessen, die richtige Zusatztaste mitzudrücken, und verliert dadurch eine Information.

Inhaltlich habe ich eine Bildschirmtabelle mit vielen Probendaten. In einer Spalte "Probenname" möchte ich endlose chemische Bezeichnungen, die man nicht ständig aufs neue tippen kann, aus einer Vorlagenliste daneben auswählen. Meine Idee für den Ablauf war: Einen Namen in der Vorlagenliste (TListBox) markieren => Doppelklick auf eine (im Normalfall noch leere) Zelle, um ihn dort direkt einzutragen. Wenn doch schon was altes in der Zelle steht, geht es eben verloren. Ein einfacher Klick auf eine Zelle soll dagegen nur den normalen Editiermodus für diese Zelle starten, unter Beibehaltung des schon vorhandenen Textes.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4791
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mo 17.04.23 11:26 
Ich habe doch geschrieben:
Th69 hat folgendes geschrieben:
(die TStringGrid-Eigenschaften Col und Row geben dann die aktuell selektierte Zelle an)

Diese Eigenschaften werden ja automatisch nach dem Aufruf von OnSelectCell gesetzt, stehen also dann im OnDblClick-Ereignis zur Verfügung.

Für diesen Beitrag haben gedankt: UweK
UweK Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 52
Erhaltene Danke: 1

Win 7
Delphi Enterprise XE6
BeitragVerfasst: Mo 17.04.23 13:42 
Hallo,

Ja natürlich, da habe ich beim Lesen gepennt und das mit ACol und ARow verwechselt, die bei OnSelectCell direkt übergeben werden.

So geht es. Vielen Dank.
Gruß Uwe
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19288
Erhaltene Danke: 1743

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 17.04.23 21:54 
Ich persönlich fände hier wahlweise einen Rechts- oder Mittelklick schöner. Und man wüsste dann auch sofort, was gemeint ist, ohne ggf. auf einen zweiten Klick zu achten. Der Rechtsklick ist mit dieser Funktion ja nicht umsonst auch in der Kommandozeile von Windows als einfügen implementiert.

Davon abgesehen gäbe es ja auch die Möglichkeit z.B. mit den VirtualTrees auch eine DropDown Auswahl usw. direkt in der Zelle zu implementieren.

Für diesen Beitrag haben gedankt: UweK
UweK Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 52
Erhaltene Danke: 1

Win 7
Delphi Enterprise XE6
BeitragVerfasst: Do 20.04.23 11:29 
Hallo jaenicke,

Danke für den zusätzlichen Tipp. Ich mache es zwar nun anders, aber VirtualTrees kannte ich bisher nicht, und habe mit das für eventuelle spätere Anwendungen gemerkt.

Nur der Vollständigkeit halber: Ich habe die Reihenfolge jetzt einfach umgekehrt. Also nicht mehr erst auf den Textvorschlag und dann auf die Tabellenzelle klicken, sondern umgekehrt der normale Mausklick erst auf die Zelle und dann auf den Vorschlag, was Fehlbedienungen gut vermeidet.

Gruß Uwe
UweK Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 52
Erhaltene Danke: 1

Win 7
Delphi Enterprise XE6
BeitragVerfasst: Do 20.04.23 14:16 
Hallo,

Doch noch einmal. TListBox zeichnet sich manchmal nicht neu, obwohl es intern den ItemIndex geändert hat. Das finde ich merkwürdig, weil das eigentlich ein ganz elementarer interner Ablauf in der Komponente TListBox sein sollte, den ich von außen gar nicht beeinflussen kann.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
MyForm.NamesListBoxOnClick(ASender);
begin
// NamesListBox.Repaint;
  SchreibeDiesenEintragAusTListBoxInDieZelle(Spalte, Zeile, NamesListBox.Items[ItemIndex]);
end;


Nach dem Klick auf einen Eintrag in der ListBox passiert meist das Erwartete: Der angelickte Eintrag wird farbig markiert da er jetzt der ausgewählte ist, ItemIndex wird entsprechend intern neu gesetzt, und in der obigen Prozedur wird der richtige String übertragen, nämlich der angeklickte und farbig markierte.

Ein Problem gibt es aber, wenn die Listbox weniger Einträge enthält, als sie bei ihrer aktuellen Höhe eigentlich anzeigen könnte. Dann bleibt ja unter den Einträgen noch ein leerer Raum übrig.

Beispiel: 8 angezeige Einträge "Zeile 0" bis "Zeile 7". Ich klicke zunächst auf "Zeile 3". Das markiert ganz normal "Zeile 3" farbig, setzt intern automatisch "ItemIdex:= 3", und meine obige Prozedur überträgt den String "Zeile 3". Wenn ich jetzt in den leeren Raum unten in der Listbox klicke, setzt das "ItemIndex:= 7", und meine Prozedur überträgt "Zeile 7". Dieses Setzen von ItemIndex macht inhaltlich auch Sinn, weil ein Klick ganz unten nur den letzten Eintrag meinen kann. Aber: farbig markiert bleibt weiterhin "Zeile 3", die Markierung springt nicht auf "Zeile 7". Nun drücke ich einmal die "Pfeiltaste hoch". Das verringert korrekt "IdemIndex:= ItemIndex - 1", also in diesem Fall "7 => 6". Erst jetzt ändert sich auch wieder die farbige Markierung, indem sie vom falschen alten "Zele 3" auf "Zeile 6" springt.

Ich habe schon mal ein bisschen herumprobiert, ob vielleicht ein zusätzliches TListBox.Repaint (oben in der Prozedur auskommentiert dargestellt) die korrekte Dartellung des letzten Eintrags wiederherstellen kann, aber das brachhte sichts.

Hat jemand einen Tipp?

Vielen dank, Gruß Uwe
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19288
Erhaltene Danke: 1743

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 20.04.23 15:09 
Geht es wirklich wie in deinem Profil angegeben um Delphi XE6? Das kann ich leider aktuell nicht testen. In der aktuellen Gratisversion funktioniert es wie erwartet.
UweK Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 52
Erhaltene Danke: 1

Win 7
Delphi Enterprise XE6
BeitragVerfasst: Mi 26.04.23 11:19 
Ja, das ist immer noch Delphi XE6.

Weitere Experimente haben jetzt mein Problem gelöst, aber ohne dass ich so recht verstehe warum.

Mir ist aufgefallen, dass im Objektinspektor TListBox.ExtendedSelect = true und TListBox.MultiSelect = true eingeschaltet waren. Das ist wohl der Standard, wenn man ein TListBox aus der Komponentenpalette einfügt. Das brauche ich natürlich nicht, und habe beide auf false gesetzt.

Jetzt geht es, und zwar deshalb, weil nun ein Klick auf den leeren Raum unter dem letzten Listeneintrag keine Wirkung mehr hat. Der vorherige Listeneintrag bleibt zwar farbig markiert wie vorher, aber auch ItemIndex ändert sich nicht mehr, so dass beides weiter zusammen passt.

TListBox.ItemIndex ändert sich jetzt nur noch durch einen gezielten Klick auf einen der Einträge.

Moderiert von user profile iconTh69: Delphi-Tags hinzugefügt