Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Setfocus auf dbgrid (https://www.delphipraxis.net/180794-setfocus-auf-dbgrid.html)

Luckner 18. Jun 2014 10:48

Setfocus auf dbgrid
 
Hallo,
folgendes Problem. Habe ein Dbgrid, eigebettet in einem Frame. Ebenso in diesem Frame ist ein Panel mit einet Schliessen-Button. Würde gerne, wenn auf Button schliessen gedrückt, dann auf Dbgrid springen (1.-ter Datensatz) und anschliessend ohne die Maus in die Hand zu nehmen, weiter mit den Pfeil-Tasten im Grid rauf oder runter mich bewegen. Mit dbgrid.setfocus funktioniert es nicht. Wenn ich mit der Maus auf Dbgrid klicke, dann geht es wieder. Habe schon mit dbgridcellclick(nil) probiert, funktioniert auch nicht.

Danke, Luckner

DeddyH 18. Jun 2014 11:03

AW: Setfocus auf dbgrid
 
Lass doch das DBGrid DBGrid sein und navigiere stattdessen durch die verbundene Datenmenge, oder habe ich das Problem missverstanden?

Perlsau 18. Jun 2014 11:20

AW: Setfocus auf dbgrid
 
Zitat:

Zitat von Luckner (Beitrag 1262733)
Mit dbgrid.setfocus funktioniert es nicht. Wenn ich mit der Maus auf Dbgrid klicke, dann geht es wieder. Habe schon mit dbgridcellclick(nil) probiert, funktioniert auch nicht.

Kann ich nicht nachvollziehen, denn ich gehe häufig ebenso vor: Nachdem der Anwender Werte in DB-Edits bearbeitet und den Post-Button betätigt hat, wird automatisch der Fokus auf das darüberliegende DBGrid gesetzt. Und das funktioniert stets tadellos. Vielleicht würde es dir helfen, wenn du einmal durch die entsprechenden Methoden stepst, vielleicht wird ja noch was aufgerufen nach dem DBGrid.SetFocus, das den Fokus wieder verändert ... ?

Luckner 18. Jun 2014 11:29

AW: Setfocus auf dbgrid
 
Danach wird nichts mehr aufgerunfen. Habe jetzt festgestellt, dass wenn ich mit der Maus auf die Buttons klicke, dan wird setfocus richtig ausgeführt. Mit meinem Hotkey F10, wo ich nur die Procedure Button.Click aufrufe, der Fücus auf dem Frame- oder Form1-Fenster landet. Mit den Pfeil-Tasten geht links, oben das Fenstermenue auf. Fenster minimieren, maximieren Schliessen usw.

Perlsau 18. Jun 2014 11:34

AW: Setfocus auf dbgrid
 
Wo genau setzt du denn deinen Fokus für das DBGrid? Ich würde das in deinem Fall mal in der Button-Ereignisbehandlung versuchen ...

Luckner 18. Jun 2014 11:44

AW: Setfocus auf dbgrid
 
Aus einem Editfeld im Panel wird folgendes aufgerufen:

Delphi-Quellcode:
procedure TFrameAuftrag.JvEditKundennrsuchenKeyDown(Sender: TObject;
  var Key: Word; Shift: TShiftState);
begin
  if Key = VK_F10 then ButtonPanelSchliessen.Click;
end;
Dann im Button:

Delphi-Quellcode:
procedure TFrameAuftrag.ButtonPanelSchliessenClick(Sender: TObject);
begin
 DBGridAuftrag.SetFocus;
 PanelFilter.Visible := False;
 JvHTButtonSuchenFiltern.Visible := True;
end;

Perlsau 18. Jun 2014 11:51

AW: Setfocus auf dbgrid
 
Was passiert, wenn du das Setzen des DBGrid-Fokus ans Ende stellst, d.h. zuletzt ausführst? Welche Delphi-Version verwendest du eigentlich?

stahli 18. Jun 2014 11:58

AW: Setfocus auf dbgrid
 
Wird denn ButtonPanelSchliessenClick auch ausgeführt?

Versuche dann mal folgendes:
Delphi-Quellcode:
procedure TFrameAuftrag.ButtonPanelSchliessenClick(Sender: TObject);
 begin
  DBGridAuftrag.SetFocus;
  // PanelFilter.Visible := False;
  // JvHTButtonSuchenFiltern.Visible := True;
 end;
Es ist denkbar, dass Dir hier ein Zeitverhalten der VCL in die Quere kommt. Es KÖNNTE SEIN, dass der Focus noch nicht wirklich umgesetzt wurde und Dein Edit durch Ausschalten des Panels "verschwindet". Dann würde der Parent den Focus erhalten.

Wenn das das Problem wäre, dann vielleicht einfach den Focus zuletzt zuweisen:

Delphi-Quellcode:
procedure TFrameAuftrag.ButtonPanelSchliessenClick(Sender: TObject);
 begin
  PanelFilter.Visible := False;
  JvHTButtonSuchenFiltern.Visible := True;
  DBGridAuftrag.SetFocus;
 end;
Da die VCL solche Anweisungen verzögert durch Nachrichtenverarbeitungen abarbeitet muss man mit solchen Effekten rechnen.


EDIT: Oups, kein roter Kasten, aber Perlsau ist wohl auf der gleichen Spur...

himitsu 18. Jun 2014 12:03

AW: Setfocus auf dbgrid
 
JvEditKundennrsuchenKeyDown:
Wenn du Eingaben selber verarbeitest, dann solltest du besser auch die weitere Verarbeitung abschalten. (hier einfach
Delphi-Quellcode:
Key:=0;
und in ganz besonderen Extremfällen ein Delphi-Referenz durchsuchenAbort)

Und was passiert, wenn den Fokus als Letztes setzt?

Luckner 18. Jun 2014 12:27

AW: Setfocus auf dbgrid
 
Die Lösung ist: Key:=0; Jetzt funktioniert es.

Danke himitsu und allen Anderen.

Perlsau 18. Jun 2014 12:31

AW: Setfocus auf dbgrid
 
Zitat:

Zitat von stahli (Beitrag 1262753)
Da die VCL solche Anweisungen verzögert durch Nachrichtenverarbeitungen abarbeitet muss man mit solchen Effekten rechnen.

Eigentlich kann ich mir nicht vorstellen, daß die Codezeilen nicht der Reihe nach ausgeführt werden. Ich glaube vielmehr, daß durch das Unsichtbarmachen des einen und das Sichtbarmachen des anderen der Fokus gesetzt wird, was auch immer das für visuelle Komponenten sind:

Delphi-Quellcode:
 PanelFilter.Visible := False;
 JvHTButtonSuchenFiltern.Visible := True;
Zitat:

Zitat von stahli (Beitrag 1262753)
EDIT: Oups, kein roter Kasten, aber Perlsau ist wohl auf der gleichen Spur...

Genau deshalb bin ich mir ziemlich sicher, daß das Setzen des Fokus ans Ende der Befehlsliste gehört. Das war schon mein Gedanke, als ich den TE oben fragte:

Zitat:

vielleicht wird ja noch was aufgerufen nach dem DBGrid.SetFocus, das den Fokus wieder verändert ... ?
.

Zitat:

Zitat von Luckner (Beitrag 1262760)
Die Lösung ist: Key:=0; Jetzt funktioniert es.

Echt? Kann ich mir kaum vorstellen ... wie sieht dein Code denn jetzt aus?

Ach ja, bevor ich's wieder vergesse: Welche Delphi-Version setzt du ein?

stahli 18. Jun 2014 12:47

AW: Setfocus auf dbgrid
 
Ok, Problem ist ja gelöst, dennoch ein Satz zu Perlsaus Frage:

Wenn DBGrid konkret den Fokus hat, dürfte es ja egal sein, ob ein anderes Panel ausgeblendet wird. In meinem Framework bin ich mit ähnlichen Abläufen aber einige Male auf die Nase gefallen - und bei verschiedenen Delphi- bzw- Windows-Versionen auch unterschiedlich.
Man kann auf jeden Fall nicht davon ausgegen, dass alle VCL-Ereignisse immer und überall 1:1 chronologisch nacheinander abgearbeitet werden.

Die Codezeilen werden natürlich nacheinander abgearbeitet, aber wenn nur Nachrichten verschickt werden kann man nie sicher sein, wann diese "beim Empfänger" verarbeitet werden. Bei schnellen Abläufen kann dann mal eine erwartete Reihenfolge durcheinander kommen.

Ein konkretes (ähnlich gelagertes) Problem hatte ich, wenn ich ein focusiertes Control gelöscht habe und zuvor ein anderes focusiert habe. Windows wollte dann unbedingt das gelöschte nochmal neu zeichnen, aber das existierte dann ja nicht mehr. Gelöst habe ich das indem ich das zu löschende Control erst mal unsichtbar gemacht und erst später gelöscht habe.

Dass die Lösung hier in der Key-Behandlung lag ist beruhigend. Aber Zusammenhänge wie von mir angesprochen sollte man mit als mögliche Problemursache beachten.

Perlsau 18. Jun 2014 13:28

AW: Setfocus auf dbgrid
 
Okay, das mit den verzögerten Messages kann ich zwar theoretisch nachvollziehen, hab's aber noch nicht erlebt bzw. hab keinen Schimmer, wie man das reproduzieren könnte. Dagegen erlebe ich des Öfteren, daß ein Umstellen der Befehlsreihenfolge ein Fehlverhalten beseitigen kann. Z.B. hatte ich kürzlich ein ähnliches Problem: Wenn ich ein DB-Edit, das den Fokus hatte und das auf eine Tabelle zeigte, die sich im Edit- oder Insert-Modus befand, auf ReadOnly := True setzte, wurde der geänderte Wert beim Tabelle.Post nicht übernommen. Bemerkt hatte ich das dadurch, daß ein Auslösen von Tabelle.Post via Buttonklick dazu führte, den Wert zu übernehmen, via Menüklick dagegen nicht. Beide Klicks führten zur selben Ereignisbehandlung einer TActionList. Der Unterschied bestand lediglich darin, daß beim Klick auf den Button der Fokus vom DBEdit weg war, bevor ich dieses Edit auf ReadOnly setzte, beim Klick via Menü jedoch weiterhin den Fokus behielt. Die Lösung bestand darin, den Fokus in der Ereignisbehandlung auf den Button zu setzen und gut war. Natürlich hätte ich auch die Reihenfolge in der Post-Methode ändern können: Erst posten und dann DBEdit.ReadOnly := True. Doch das hätte mein Programmkonzept völlig über den Haufen geworfen, was jetzt aber zu weit führen würde.

Zitat:

Zitat von stahli (Beitrag 1262769)
Wenn DBGrid konkret den Fokus hat, dürfte es ja egal sein, ob ein anderes Panel ausgeblendet wird.

Ich dachte mal, wenn der TE in seiner DBEdit-Ereignisbehandlung (KeyDown) die ButtonPanelSchliessen-Ereignisbehandlung aufruft (ist eigentlich schlechter Stil, das sollte eine private Methode sein, die von Key- und Button-Ereignisbehandlung gleichermaßen aufgerufen wird), könnte da nicht der Fokus auf dem DBEdit verbleiben? Denn schließlich folgt nach dem KeyDown noch das KeyUp, das ja ebenfalls vom Benutzer ausgelöst wird und den Fokus womöglich wieder an das DBEdit zurückgibt. Oder gehört das KeyUp dann dem DBGrid, wenn das den Fokus hat? Mir ist auf jeden Fall nicht so recht klar, wieso ein leeren des Tastaturpuffers im KeyDown des DBEdit (Key = #0) das Problem löst ...

stahli 18. Jun 2014 13:40

AW: Setfocus auf dbgrid
 
Wir schweifen etwas ab, aber noch kurz:

Die VCL hat gewissermaßen ein Eigenleben, das sich auch mal ändern kann. Eigene Logiken davon abhängig zu machen, kann unerwartete Schwierigkeiten bereiten.
Hinzu kommt, dass die Controls in sich öfters nicht so arbeiten, wie man es erwarten sollte (http://www.delphipraxis.net/85385-tr...kt-falsch.html).
Das sollte man nur im Auge behalten.

Das vorliegende Key-Problem ist wohl, dass F10 eine Menüfunktion aufruft. Wenn Key nicht "neutralisiert" wird, macht Windows das noch, nachdem die Anwendung schon mit der Bearbeitung fertig ist.

Perlsau 18. Jun 2014 13:48

AW: Setfocus auf dbgrid
 
Zitat:

Zitat von stahli (Beitrag 1262779)
Das vorliegende Key-Problem ist wohl, dass F10 eine Menüfunktion aufruft. Wenn Key nicht "neutralisiert" wird, macht Windows das noch, nachdem die Anwendung schon mit der Bearbeitung fertig ist.

Ach ja, ich vergaß: F10 ist ja die universelle Windows-Taste für den Aufruf des jeweiligen Hauptmenüs: Schlechte Wahl für eine Anwendung ...

Für dein DBRadioGroup hätte ich einfach TJvDBRadioPanel aus den Jedis genommen ...

himitsu 18. Jun 2014 14:04

AW: Setfocus auf dbgrid
 
Zitat:

Zitat von Perlsau (Beitrag 1262761)
Zitat:

Zitat von Luckner (Beitrag 1262760)
Die Lösung ist: Key:=0; Jetzt funktioniert es.

Echt? Kann ich mir kaum vorstellen ... wie sieht dein Code denn jetzt aus?

Auf F10 reagiert z.B. das Hauptmenü, womit dann nach dem Verlassen der Eventmethode noch anderer Code auf das VK_F10 ragiert und irgendwas macht.


PS: Den schönsten Spaß hat man, wenn einige Ereignisse im OnKeyDown verarbeitet werden und Andere im OnKeyUp.

Ein gutes Beispiel hatte ich da auch mal, so wurde im OnKeyDown per F2 das aktuelle ShowModal-Fenster geschlossen,
während das übergeordnete Fenster im OnKeyUp per F2 eine neue Instanz des Fenster öffnete.
- F2 rein und alles ist OK
- per F2 wieder raus ging nicht, da es gleich wieder rein ging, weil das eine Fenster sich im Down ausblendete und das Up dann im anderen Fenster landete.
> beides gleichermaßen im Up ODER im Down ausgeführt, hätte keine Probleme bereitet :stupid:

Oder wie hier:
Mehrere Stellen verarbeiten das selbe Tastenereignis und man wundert sich dann, wenn Mehreres passiert oder Einiges nicht richtig.

Perlsau 18. Jun 2014 14:07

AW: Setfocus auf dbgrid
 
Genau dafür gibt's den Spruch: Verarschen kann ich mich alleine :-D
Daß das wunderbar klappt, hat wohl schon jeder einmal erleben dürfen :lol:

Luckner 18. Jun 2014 14:37

AW: Setfocus auf dbgrid
 
Hallo Perlsau, himitsu,

Meine Delphi-Version ist 7 Pro. Folgendes Problem noch, auf das, so glaube ich, gerade himitsu darauf hingewiesen hat. Habe versucht einige Funktionen ebenfalls in einem anderem Frame mit den F-Tasten zu steuern. Es funktioniert nicht, weil im Tastaturpuffer jetzt die Funktionen der F-Tasten aus dem vorherigen Frame noch hinterlegt sind und in einem weiterem Frame nicht funktionieren bzw. Mist machen. Kann ich, wenn ich ein Frame verlasse, den gesamten Tastaturpuffer zurücksetzen? Mit dem key := 0 funktioniert auch das Bewegen mit den Pfeiltasten im DB-Grid nicht mehr. Aber das werde ich noch gesondert überprüfen.

himitsu 18. Jun 2014 14:50

AW: Setfocus auf dbgrid
 
Ich hoffe du setzt das nur dann auf 0, wenn du darin etwas gemacht hast (z.B. nur bei deinem VK_F10) und nicht immer auch für alle anderen Ereignisse.

PS: Man sollte am Besten auch unbedingt immer die kompletten ShiftStates prüfen.
Also nicht mit
Delphi-Quellcode:
... IN Shift
, sondern mit
Delphi-Quellcode:
Shift = [...]
, auch und vorallem wenn man keine dieser Tasten verwendet.
F10 ist nunmal kein Strg+F10 usw.

Delphi-Quellcode:
if (Key = VK_F10) and (Shift = []) then begin
  ...
  Key := 0;
end;

Luckner 18. Jun 2014 15:38

AW: Setfocus auf dbgrid
 
Danke himitsu,
der Tipp mit key:=0 war richtig. Hatte Das an der falsche Stelle gesetzt. Jetzt habe ich das Problem, das z.B. die F2-Taste in einem weiterem Frame eine andere Funktion haben sollte. Leider wird die Funktion aus dem vorherigem Frame aufgerufen. Da holft das Setzen key := 0 nicht. Irgendwie müsste man den speicher löschen. Aber wie?

stahli 18. Jun 2014 15:46

AW: Setfocus auf dbgrid
 
Verstehe ich das so richtig?

Du hast in einem Formular mehrere Frames mit diversen Controls. Wenn Du F10 oder F2 drückst, soll etwas gemacht werden, egal, welches Control gerade den Focus hat?

Ansonsten mach doch mal einen Screenshot oder so, dass das etwas nachvollziehbarer wird...

Perlsau 18. Jun 2014 15:52

AW: Setfocus auf dbgrid
 
Zitat:

Zitat von Luckner (Beitrag 1262798)
Danke himitsu,
der Tipp mit key:=0 war richtig. Hatte Das an der falsche Stelle gesetzt. Jetzt habe ich das Problem, das z.B. die F2-Taste in einem weiterem Frame eine andere Funktion haben sollte. Leider wird die Funktion aus dem vorherigem Frame aufgerufen. Da holft das Setzen key := 0 nicht. Irgendwie müsste man den speicher löschen. Aber wie?

Kann es sein, daß du da was verwechselst? Das eine ist der Tastaturpuffer: dieser enthält Zeichen, die du mit deiner Tastatur eingegeben hast. Das andere sind Hotkeys, die u.U. für's gesamte Programm gelten: Bestimmte Ereignisse werden beim Drücken vorher festgelegter Tasten ausgelöst. Mit Key := 0 bzw. Key := #0 (bei KeyPress) löschst du lediglich den Tastaturpuffer, der danach keine zuvor eingegebene Zeichen mehr enthält.

Luckner 18. Jun 2014 16:02

AW: Setfocus auf dbgrid
 
Habe in einer Form 2 Frames. In der Form, wie auch in den einzelnen Frames gibt es z.B. Schliessen-Button. Schliessen-Button in Frame1 schliesst das Frame1, schliessen-Button in Frame2 schliesst Frame2. Schliessen-Button in Form1 schliesst die Form. Beide Frames sind allClient. Aus der Form kann man nur ein Frame aufrufen. So, wenn man in Frame1 ist, würde ich gerne mit der F10-Taste Frame1 schliessen, in Frame2 dann Frame2 schliesse und am Ende dann die Form. Die Buttons in den jeweiligen Frames machen das schon. Wenn ich jetzt in Frame1, oder 2 bin und F10 drücke wird sofort die ganze Form geschlossen. Das hin und her Springen von Frame zu Frame mache ich über die Eigenschaft "Visible". Möglicherweise müsste ich ein nichtsichtbares Frame auch deaktivieren?

Luckner 18. Jun 2014 16:20

AW: Setfocus auf dbgrid
 
Hallo Perlsau,

ja, dann sind es Hotkeys. kann man die irgendwie zurücksetzen oder Überschreiben?

Perlsau 18. Jun 2014 16:20

AW: Setfocus auf dbgrid
 
Die Ereignisbehandlungen für Keys im Hauptformular gelten auch für zusätzliche Fenster sowie Frames. Einzig beim Aufruf eines modalen Fensters gelten sie dort nicht. Im Übrigen ist die Wahl der F10-Taste eine schlechte, denn damit werden normalerweise Menüs aktiviert.

himitsu 18. Jun 2014 16:23

AW: Setfocus auf dbgrid
 
Jupp, viele Programme nehmen daher Strg+F4 für Frames/Tabs, da Alt+F4 ja auch schon als Fenster-Schließen bekannt ist.


Hier wird übrigens nirgendwo der Tastaturpuffer gelöscht.

Das Tastenereignis wird von der VCL-Messageloop aus dem MessageQueue geholt und dann verarbeitet.
Dabei wird das Key-Event durch mehrere Komponenten geschleift. Sobald nun Eine das Key auf 0 setzt, bekommen die Danach dann nur noch diese 0 oder deren Event wird ganricht erst aufgerufen.



Du hast nicht zufällig KeyPreview der Form aktiviert?
Wenn ja, dann bekommt sie zuerst das Event, ansonsten bekommt die Form das als Letztes und zuerst die Komponenten/Frames.

Also entweder kein KeyPreview,
oder du muß in der Form selber schauen ob es einen Frame gibt, dann schleißt du den Frame und wenn nicht, dann die Form.

Luckner 20. Jun 2014 09:53

AW: Setfocus auf dbgrid
 
Hallo,
war gestern ganzen Tag unterwegs, deshalb erst heute weiter zu diesem Zhema. Himitsu danke für den Tipp mit "keypreview". Klar, die Taste F10 ist nicht glücklich gewählt, aber Chef möchte ganz einfach mit möglich nur einem Tansten-klick irgendwelche Funktionen in verschiedenen Masken aufrufen. Nach möglichkeit nur die F-Tasten. Also schalte ich, wenn ich in der Form ein Frame aufrufe "keypreview" aus, dann funktionieren die F-Tasten im Frame und wenn ich auf die Hauptform zurückspringe, wird "keypreview" auf True gesetzt, damit die F-Tasten da auch reagieren. Hatte gerade einige Tests gemacht und es scheint zu funktionieren.


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:59 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