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/)
-   -   Delphi Modale Form -> SetFocus auf TLabeledEdit geht nicht (https://www.delphipraxis.net/199763-modale-form-setfocus-auf-tlabelededit-geht-nicht.html)

Hobbycoder 18. Feb 2019 13:08

Modale Form -> SetFocus auf TLabeledEdit geht nicht
 
Hi,

ich bastel jetzt schon ne ganze Weile an einem Problem rum. Ich habe eine Login-Form, aber es will mir nicht gelingen, dem ersten LabeledEdit den Focus zu geben. Mit der Maus oder der Tab-Taste geht's schon, wenn die Form erst mal angezeigt wird, aber ich hätte es gern ohne Useraktion.

Bei all den ganzen Versuchen bin ich dann auf
Delphi-Quellcode:
PostMessage(lbledtUsername.Handle, WM_SETFOCUS, 0, 0);
in FormShow hängengeblieben, was zwar den Cursor auf mein LabeledEdit setzt, aber ich dann dort nichts eingeben kann, außer mit Tab zum nächsten Control zu wechseln, was dann zur Folge hat, dass ich das nicht mehr zurück ins vorherige Control komme (weder per Tab noch per Maus).

Ich bin ein bischen ratlos, weil ich mir das Verhalten so gar nicht erklären kann. Weder die Tatsache, dass LabeledEdit.SetFocus oder LMCLogin.ActiveControl:=LMCLogin.lbledtUsername wirkungslos bleiben, noch das sehr merkwürdige Verhalten nach dem PostMessage im FormShow.

Zur Verdeutlichung hier mal der Source (die auskommentierten Zeilen spiegeln meine Versuche von Workaround dar):
Delphi-Quellcode:
unit fLMCLogin;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, BadgeBtn, Vcl.StdCtrls, Vcl.ExtCtrls;

type
  TLMCLogin = class(TForm)
    lbledtUsername: TLabeledEdit;
    lbledtPassword: TLabeledEdit;
    bdgbtnLogin: TBadgeBtn;
    bdgbtnAbort: TBadgeBtn;
    tmr1: TTimer;
    procedure FormPaint(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure lbledtPasswordChange(Sender: TObject);
    procedure tmr1Timer(Sender: TObject);
  private
    FirstPaint: Boolean;
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  LMCLogin: TLMCLogin;

implementation

{$R *.dfm}

procedure TLMCLogin.FormPaint(Sender: TObject);
begin
//  if FirstPaint then
//  begin
//    FirstPaint:=False;
//    lbledtUsername.SetFocus;
//  end;
end;

procedure TLMCLogin.FormShow(Sender: TObject);
begin
//  FirstPaint:=True;
//  lbledtPassword.Text:='';
//  bdgbtnLogin.Enabled:=False;
//  lbledtUsername.SelectAll;
//  lbledtUsername.SetFocus;
//  self.ActiveControl:=lbledtUsername;
//  tmr1.Enabled:=True;
//  Perform(WM_NEXTDLGCTL, 0, 0);
  PostMessage(lbledtUsername.Handle, WM_SETFOCUS, 0, 0);
end;

procedure TLMCLogin.lbledtPasswordChange(Sender: TObject);
begin
  bdgbtnLogin.Enabled:=True;
  bdgbtnLogin.Default:=True;
end;

procedure TLMCLogin.tmr1Timer(Sender: TObject);
begin
//  tmr1.Enabled:=False;
//  lbledtUsername.SetFocus;
end;

end.
Aufruf dann so:
Delphi-Quellcode:
    LMCLogin.ActiveControl:=LMCLogin.lbledtUsername;
    LMCLogin.lbledtPassword.Text:='';
    LMCLogin.bdgbtnLogin.Enabled:=False;
    if LMCLogin.ShowModal=mrOK then
    ...
PS: Die Unit BadgeButton ist eine selbstgeschriebe, aber auch mit Standard-TButton erreiche ich gleiches Verhalten.

hoika 18. Feb 2019 14:38

AW: Modale Form -> SetFocus auf TLabeledEdit geht nicht
 
Hallo,
hast du FormActivate schon probiert?

Zu Deinem FormShow und PostMessage.
Du bist innerhalb der Nachrichtenbearbeitung des ON_SHOW und sendest eine weitere Nachricht,
hier hätte wieder besseren Wissens sogar SendMessage benutzt, wenn halt überhaupt.

hoika 18. Feb 2019 14:45

AW: Modale Form -> SetFocus auf TLabeledEdit geht nicht
 
Hallo,

ich habe mal ein Minimal-Beispiel erzeugt.
Sowohl FormShow als auch FormActivate funktionieren.

Delphi-Quellcode:
procedure TForm133.FormShow(Sender: TObject);
begin
  LabeledEdit2.SetFocus;
end;
Allerdings ohne das LMCLogin.ActiveControl:=LMCLogin.lbledtUsername;


Ist das wirklich dein ganzer Code?

Mache mal ein neues leeres Projekt und probier das aus.

dummzeuch 18. Feb 2019 15:03

AW: Modale Form -> SetFocus auf TLabeledEdit geht nicht
 
Mir würde als erstes einfallen, statt eines LabeledEdit ein Label und ein Edit getrennt zu verwenden. Hast Du das mal probiert?

Hobbycoder 19. Feb 2019 07:30

AW: Modale Form -> SetFocus auf TLabeledEdit geht nicht
 
Zitat:

Zitat von hoika (Beitrag 1425884)
Hallo,
hast du FormActivate schon probiert?

Gleicher Effekt

Zitat:

Zitat von hoika (Beitrag 1425884)
Zu Deinem FormShow und PostMessage.
Du bist innerhalb der Nachrichtenbearbeitung des ON_SHOW und sendest eine weitere Nachricht,
hier hätte wieder besseren Wissens sogar SendMessage benutzt, wenn halt überhaupt.

War ja auch mehr ein Test.

Zitat:

Zitat von hoika (Beitrag 1425886)
Hallo,

ich habe mal ein Minimal-Beispiel erzeugt.
Sowohl FormShow als auch FormActivate funktionieren.

Delphi-Quellcode:
procedure TForm133.FormShow(Sender: TObject);
begin
  LabeledEdit2.SetFocus;
end;
Ich habe auch ein Minimalbeispiel erzeugt. Da funktioniert es auch bestens.

Zitat:

Zitat von hoika (Beitrag 1425886)

Allerdings ohne das LMCLogin.ActiveControl:=LMCLogin.lbledtUsername;


Ist das wirklich dein ganzer Code?

Mache mal ein neues leeres Projekt und probier das aus.

Jepp. Ist der ganze Code. Die Unit LMCLogin.pas habe ich komplett gepostet. Der Aufruf ist natürlich nach hinten raus abgeschnitten. Aber vorweg kommt nichts.

Aber ich habe meinen Fehler mittlerweile gefunden.
Zur Erklärung: Wenn eine Anwendung eine Anmeldung benötigt, und man die Loginform im OnShow der Mainform modal aufruft, erscheint die MainForm erst, wenn der modale Dialog beendet ist. Ausdiesem Grund packe ich das gern in die OnPaint der Mainform (mit einer Firstpaint-Variable). So auch dieses mal. Allerdings bleibt dann wohl der Fokus noch auf der Mainform.
Jetzt habe ich im OnPaint noch ein
Delphi-Quellcode:
Inherited; Application.ProcessMessages;
vor dem modalen Aufruf der Loginform eingesetzt, damit alle Zeichenvorgänge und Nachrichten abgearbeitet sind. Und dann klappt auch ein SetFocus im FormShow der LoginForm.

Danke euch trotzdem, denn ihr habt mich dazu angehalten, das, was vor dem modalen Aufruf kommt, noch mal genauestens anzuschauen.

Uwe Raabe 19. Feb 2019 07:47

AW: Modale Form -> SetFocus auf TLabeledEdit geht nicht
 
Zitat:

Zitat von Hobbycoder (Beitrag 1425922)
Ausdiesem Grund packe ich das gern in die OnPaint der Mainform (mit einer Firstpaint-Variable). So auch dieses mal. Allerdings bleibt dann wohl der Fokus noch auf der Mainform.
Jetzt habe ich im OnPaint noch ein
Delphi-Quellcode:
Inherited; Application.ProcessMessages;
vor dem modalen Aufruf der Loginform eingesetzt, damit alle Zeichenvorgänge und Nachrichten abgearbeitet sind.

Entschuldige bitte diese drastischen Worte, aber falscher kann man es wirklich kaum machen. Im OnPaint einen modalen Dialog aufrufen ist schon ein konzeptioneller Fehler und dann noch die auftretenden Probleme mit einem Application.ProcessMessages kitten ist wie den Teufel mit dem Beelzebub austreiben.

Es gibt genügend Möglichkeiten, den Login-Dialog sauber aufzurufen. Welche davon geeignet sind, hängt von deiner Delphi-Version und einigen anderen Umständen und Vorgaben ab.

hoika 19. Feb 2019 09:40

AW: Modale Form -> SetFocus auf TLabeledEdit geht nicht
 
Hallo,
so drastisch würde ich das nicht ausdrucken,
aber ja, es ist grundsätzlich falsch ;)

Richtig wäre entweder in der DPR oder im FormActivate des Hauptfensters.

Delphi-Quellcode:
procedure TForm1.FormActivate();
begin
  OnActivate:= nil; // Mehrfachaufruf von FormActivate verhindern

  if not Login then
  begin
    PostMessage(Handle, WM_CLOSE, 0, 0);
    Exit;
  end;
end;

Uwe Raabe 19. Feb 2019 10:09

AW: Modale Form -> SetFocus auf TLabeledEdit geht nicht
 
Zitat:

Zitat von hoika (Beitrag 1425933)
so drastisch würde ich das nicht ausdrucken,

Ich weiß, war nicht so gemeint...

peterbelow 19. Feb 2019 10:32

AW: Modale Form -> SetFocus auf TLabeledEdit geht nicht
 
Zitat:

Zitat von Hobbycoder (Beitrag 1425873)
Hi,

ich bastel jetzt schon ne ganze Weile an einem Problem rum. Ich habe eine Login-Form, aber es will mir nicht gelingen, dem ersten LabeledEdit den Focus zu geben. Mit der Maus oder der Tab-Taste geht's schon, wenn die Form erst mal angezeigt wird, aber ich hätte es gern ohne Useraktion.

Äh, normalerweise setzt man einfach im Designer für das Form die Eigenschaft ActiveControl auf das Control, das beim ersten Anzeigen des Forms den Focus habe soll...


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