Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   TActionList - gleicher ShortCut für zwei Actions (https://www.delphipraxis.net/214893-tactionlist-gleicher-shortcut-fuer-zwei-actions.html)

ThomasWB 30. Mär 2024 18:58

TActionList - gleicher ShortCut für zwei Actions
 
Hallo zusammen,
Ich habe eine Applikation mit zwei TreeView-Komponenten.
  • Dazu habe ich in der ActionList zwei Aktionen (Shortcut: F2) definiert zum Ändern des Items im jeweiligen Treeview.
  • Diese Aktionen haben unterschiedliche Beschriftungen und Hilfetexte und sind entsprechenden Buttons und MenüItems zugeordnet.
Ich dachte nun, dass je nachdem welche TreeView-Komponente den Focus hat, der Shortcut entsprechend die für diese Komponente "zuständigen" Action auslöst. Die andere Action ist dabei durch den "Verlust" des Focus disabled. Leider funktioniert der Shortcut jedoch nur bei einer Action. Die zweite Action wird durch den Shortcut nie ausgelöst.

Mach ich hier etwas falsch oder gibt es diese Möglichkeit (Shortcut "mehrfach" vergeben) nicht?

himitsu 30. Mär 2024 20:10

AW: TActionList - gleicher ShortCut für zwei Actions
 
Shortcuts sind global, egal was aktiv ist.

Drum macht man es ja als Shortcut, damit es immer und überall aufrufen kann.
Wäre doch bissl nutzlos, wenn ein ShortCut an einem Button nur funktioniert, wenn er den Fokus hat ... da könnte ich stattdessen auch einfach universell Leertaste oder Enter drücken.

Entweder du regelst, beim Fokuswechsel, welche Action davon aktivi ist,
oder du fängst im Form.OnKeyXxx mit KeyPreview dieses ab und steuerst dann manuell an, was jetzt gemacht werden soll.

peterbelow 31. Mär 2024 12:30

AW: TActionList - gleicher ShortCut für zwei Actions
 
Zitat:

Zitat von ThomasWB (Beitrag 1535132)
Hallo zusammen,
Ich habe eine Applikation mit zwei TreeView-Komponenten.
  • Dazu habe ich in der ActionList zwei Aktionen (Shortcut: F2) definiert zum Ändern des Items im jeweiligen Treeview.
  • Diese Aktionen haben unterschiedliche Beschriftungen und Hilfetexte und sind entsprechenden Buttons und MenüItems zugeordnet.
Ich dachte nun, dass je nachdem welche TreeView-Komponente den Focus hat, der Shortcut entsprechend die für diese Komponente "zuständigen" Action auslöst. Die andere Action ist dabei durch den "Verlust" des Focus disabled. Leider funktioniert der Shortcut jedoch nur bei einer Action. Die zweite Action wird durch den Shortcut nie ausgelöst.

Mach ich hier etwas falsch oder gibt es diese Möglichkeit (Shortcut "mehrfach" vergeben) nicht?

Nur mal am Rande: F2 ist der Key, der in einem Windows-Treeview den fokusierten Eintrag in den Editmodus schaltet, dafür braucht man keine extra Action...

Delphi.Narium 31. Mär 2024 17:20

AW: TActionList - gleicher ShortCut für zwei Actions
 
Sind die beiden TreeViews auf dem gleichen Formular? Wenn nein, helfen zewi TActionList, eine je Formular. Die können dann beide den gleichen ShortCut haben.

Was eventuell funktionieren könnte wäre, die TreeViews auf zwei Frames zu legen und je Frame auch eine TActionList. Könnte funktionieren, hab' ich aber noch nicht probiert.

Oder im Ereignis OnEnter bzw. OnExit die dann jeweils "erforderliche" Action auf Enabled setzen, so dass immer nur eine TAction aktiv ist. Damit könntest Du dann sogar verhindern, dass F2 'ne Wirkung zeigt, wenn kein TreeView den Focus hat.

Wenn aber sowieso per TAction auf F2 das gemacht wird, was bei F2 in 'nem TreeView ohne TAction gemacht wird, wäre das Standardverhalten durchaus die einfachere und sinnvollere Alternative. Per TAction und ShortCut auf F2 bitte nur dann, wenn zwingend eine weitere Logik im Programmablauf erforderlich ist, z. B. dann, wenn nicht nur der Treeevieweintrag selbst bearbeitet werden soll, sondern auch in einem Dialog am Eintrag hängende Objekte.

ThomasWB 1. Apr 2024 11:52

AW: TActionList - gleicher ShortCut für zwei Actions
 
Zitat:

Nur mal am Rande: F2 ist der Key, der in einem Windows-Treeview den fokusierten Eintrag in den Editmodus schaltet, dafür braucht man keine extra Action...
Das würde ausreichen, wenn es ein einfaches Ändern des Eintrages ist. Es wird hierbei aber je nach Treeview ein Formular aufgerufen, dass den endgültigen Inhalt des Knoten steuert.

Zitat:

"erforderliche" Action auf Enabled
Das habe ich schon gemacht - durch das OnUpdate-Event des jeweiligen TAction-Items. Damit verhindere ich perfekt den Aufruf der Änderung des Knotens bei TAction = disbaled, wenn das entsprechende Treeview keinen Fokus hat. Leider funktioniert F2 am anderen Treeview trotzdem nicht.

Zitat:

oder du fängst im Form.OnKeyXxx mit KeyPreview dieses ab und steuerst dann manuell an, was jetzt gemacht werden soll.
Ich hatte schon befürchtet, dass dies die einzigen Lösung ist. Da ich aber mit TActionList erst ganz neu zu arbeiten begonnen habe (es bietet einige Vorteile), dachte ich, ich frage mal nach, bevor ich den "Umweg" über Form.OnKey nehme.

Delphi.Narium 1. Apr 2024 13:50

AW: TActionList - gleicher ShortCut für zwei Actions
 
Bevor Du Form.OnKeyXxx nutzt, probiere bitte, ob OnEnter bzw. OnExit nicht ausreichend sind, um dort Enabled auf True bzw. False zu setzen.

Das Ereignis OnUpdate der ActionList dürfte hier kaum die "richtige" Stelle sein. Die zu einem Treeview gehörende TAction muss halt enabled werden, wenn der Focus zum Treeview wechselt. Die andere Action muss in dem Moment auf Enabled := false gesetzt werden.

Wüsste gerade nicht, wie Du im OnUpdate-Ereignis der TActionList feststellen kannst, welcher Treeview gerade den Focus hat, um dann die entsprechende TAction auf Enabled := true zu setzen.

Frei nach dem Motto:
Delphi-Quellcode:
procedure TForm1.aclUpdate(Action: TBasicAction; var Handled: Boolean);
begin
  Action1.Enabled := TreeView1.HasFocus;
  Action2.Enabled := TreeView2.HasFocus;
  Handled := true;
end;
Beim Nachfolgenden könnte ich mir aber schon vorstellen, dass es funktioniert:
Delphi-Quellcode:
procedure TForm1.TreeView1Enter(Sender: TObject);
begin
  Action1.Enabled := True;
  Action2.Enabled := False;
end;

procedure TForm1.TreeView2Enter(Sender: TObject);
begin
  Action2.Enabled := True;
  Action1.Enabled := False;
end;

procedure TForm1.TreeView1Exit(Sender: TObject);
begin
  Action1.Enabled := False;
  Action2.Enabled := False;
end;

procedure TForm1.TreeView2Exit(Sender: TObject);
begin
  Action1.Enabled := False;
  Action2.Enabled := False;
end;
Prinzipiell kannst Du jederzeit im Programmablauf bei 'ner Action Enabled auf true bzw. false setzen. Das muss nicht im OnUpdate der Actionlist passieren. Im OnUpdate wird aber ggfls. (abhängig davon bei welcher Action gerade Enabled = true ist) entschieden, welche Action zum Zuge kommt.
Zumindest schalte ich in meinen Programmen im Ablauf bestimmte Actions ein oder aus, so dass immer die "passende" aufgerufen wird, auch wenn mehrere über den gleichen ShortCut verfügen. Da ich aber nur Delphi 7 habe, kann ich nicht sagen, ob das Verhalten bei neueren Delphis noch genauso geblieben ist.

Das Ereignis OnUpdate der ActionList habe ich noch nie benötigt. Und ich nutze grundsätzlich 'ne Actionlist und mehr oder weniger viele Actions für die Programmsteuerung.

Was auch noch gehen könnte: Die Logik, die Du momentan in den beiden Actions hast, verlagerst Du in zwei Prozeduren.

Dann machst Du die eine Action, die auf F2 reagiert, dort fragst Du dann sinngemäss sowas ab:
Delphi-Quellcode:
procedure TForm1.ActionFuerF2Execute(Sender: TObject);
begin
  if ActiveControl = TreeView1 then ProcedurFuerTreeView1;
  if ActiveControl = TreeView2 then ProcedurFuerTreeView2;
end;

msohn 1. Apr 2024 14:03

AW: TActionList - gleicher ShortCut für zwei Actions
 
Zitat:

Leider funktioniert F2 am anderen Treeview trotzdem nicht.
Das Problem ist, dass TCustomActionList.IsShortCut aufgibt, nach weiteren Actions zu suchen, sobald der Shortcut einer Action übereinstimmt - vollkommen unabhängig davon ob die Action enabled ist etc. also auch wenn Action.HandleShortcut False liefert.

Die einfachste Lösung dafür wären jetzt 2 getrennte ActionLists. Dann funktioniert der Ansatz mit dem disablen.

Leider ist TCustomActionList.IsShortCut nach all den Jahren immer noch nicht virtuell, so dass es keine wirklich elegante Lösung gibt.

peterbelow 1. Apr 2024 14:36

AW: TActionList - gleicher ShortCut für zwei Actions
 
Zitat:

Zitat von msohn (Beitrag 1535173)
Zitat:

Leider funktioniert F2 am anderen Treeview trotzdem nicht.
Das Problem ist, dass TCustomActionList.IsShortCut aufgibt, nach weiteren Actions zu suchen, sobald der Shortcut einer Action übereinstimmt - vollkommen unabhängig davon ob die Action enabled ist etc. also auch wenn Action.HandleShortcut False liefert.

Die einfachste Lösung dafür wären jetzt 2 getrennte ActionLists. Dann funktioniert der Ansatz mit dem disablen.

Leider ist TCustomActionList.IsShortCut nach all den Jahren immer noch nicht virtuell, so dass es keine wirklich elegante Lösung gibt.

TForm hat auch eine IsShortcut-Methode, und die ist virtual. Für eine Übersicht des Keyhandlings in der VCL sieh hier. Bitte Geduld, braucht sehr lange zum laden. Alternativ auch in Github.

ThomasWB 1. Apr 2024 16:56

AW: TActionList - gleicher ShortCut für zwei Actions
 
Zitat:

Die einfachste Lösung dafür wären jetzt 2 getrennte ActionLists. Dann funktioniert der Ansatz mit dem disablen.
Ich habe jetzt alle Aktionen für den Treeview, für den die Shortcuts nicht funktioniert haben, in eine eigene TActionList gesteckt - und es funktioniert perfekt. Vielen Dank.

Zitat:

Wüsste gerade nicht, wie Du im OnUpdate-Ereignis der TActionList feststellen kannst, welcher Treeview gerade den Focus hat, um dann die entsprechende TAction auf Enabled := true zu setzen.
Ich habe hier mal ein Besipiel für OnUpdate - nicht nur mit Fokus auf Treeview sondern noch ein paar Optionen mehr:
Code:
     actAufgabeDown.Enabled := (ActiveControl = listAufgaben) and
                               (listAufgaben.Selected<>nil) and
                               (listAufgaben.Selected.AbsoluteIndex<>listAufgaben.Items.Count-1);
Da ich nur ganz wenige doppelte oder mehrfache Benutzungen (Buttons, Menüs etc.) meiner Funktionen habe, wäre TActionList nicht so extrem wichtig/sinnvoll. Aber mit der OnUpdate-Methode kann ich direkt bei der Funktion ein enable/disable hinterlegen und muss dies nicht irgendwo in einer eigenen Funktion etc. programmieren. Somit habe ich alles an einer Stelle.


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:38 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz