Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Delphi 5 Button-Events abfragen


LokutusvB - Di 09.10.07 11:01
Titel: Delphi 5 Button-Events abfragen
Hallo Leute,

ich arbeite zur Zeit an einem Programm, welches über verschiedene Buttons (Button1 bis Button 10) verschiedene andere Ereignisse auslöst und Eigenschaften anderer Komponenten (1 bis 10) verändert.

Zur Zeit ist es noch so, dass ich für jeden Button eine separate Click-Procedure (TForm_Main.Button1Click(Sender: TObject) bis Button10) erstellt habe.

Nun soll das Programm aber erweitert werden, die Erweiterungen an sich sind nicht das Problem, nur werden es irgendwann 50 und mehr Buttons sein. Auch alles kein Problem. Nur wird mir irgendwann der Quelltext zu lang und unübersichtlich. Für jeden der Buttons wird beim Click Ereignisse mit anderen Objekten ausgelöst, dieses Vorgehen kann ich wunderbar durch Schleifen und FindComponent-Aufrufe abhandeln. Leider weiss ich momentan noch keine Möglichkeit, wie ich das in einer oder 2 Prozeduren für alle Buttons abhandeln kann, sondern müßte trotzdem für jeden Button eine ButtonXClick-Procedure nutzen, in der ich dann die Abhandlungsprocedure mit Übergabe aufrufe.

Nun zu meiner Frage:
Gibt es eine Möglichkeit, in einer Procedure alle Buttons abzuhandeln?
Also so in etwa

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
TForm_Main.ButtonCLick(Sender: TObject):
begin

 // for ii := 1 to MAX_BTN do 
   // if TButton(Form_main.FindComponent(Button + IntToStr(ii))). ->ClickEvent = True) then Cklickereignis(ButtonX);

end;


Ich hoffe, ihr versteht, wie ich das meine und könnt mir bei dem Problem weiterhelfen.

MFG
LokutusvB

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


jasocul - Di 09.10.07 11:04

FindComponent sollte Dir auf den richtigen Weg helfen.


LokutusvB - Di 09.10.07 11:11

user profile iconjasocul hat folgendes geschrieben:
FindComponent sollte Dir auf den richtigen Weg helfen.


Ja, soweit gehe ich mit. Nur habe ich noch nichts finden können, mit dem ich abfragen kann, ob ein Button ein Click-Event ausgelöst hat oder nicht, Click oder OnClick hilft mir der der If-Abfrage leider nicht weiter. Das ist hier mein Problem, was ich momentan habe.

MFG
LokutusvB

Zusatz: Lösung gefunden :)


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure TForm_Main.ButtonClick(Sender: TObject);
var
  ii: Integer;

begin
  for ii := 1 to 10 do
    if (Sender = TButton(Form_Main.FindComponent('Button' + IntToStr(ii))))
      then ShowMessage('Button' + IntToStr(ii));
end;


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


Narses - Di 09.10.07 11:32

Moin und :welcome: im Forum!

Du hast da irgendwo einen Denkfehler. :? Das Ereignis ist die Information, dass ein Button angeklickt wurde. Welcher steht ja im Parameter Sender. Wenn du einen Index brauchst, kannst du dafür die .Tag-Eigenschaft verwenden. :idea:

cu
Narses


Andreas Schilling - Di 09.10.07 11:37

Wenn der erste Button ein OnClick - Ereignis hat, das im OI bei OnClick allen anderen Button zuweisen. Dann wird beim Klick auf einen Button immer diese eine Procedure verwendet.
Im onClick-Procedure des Button1 kannst du dann auf den "Sender" des Ereignis reagieren

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
if [sender as TButton].name = 'Button1'
then begin
....
end;
if [sender as TButton].name = 'Button2'
then begin
....
end;
......


LokutusvB - Di 09.10.07 11:40

user profile iconAndreas Schilling hat folgendes geschrieben:
Wenn der erste Button ein OnClick - Ereignis hat, das im OI bei OnClick allen anderen Button zuweisen. Dann wird beim Klick auf einen Button immer diese eine Procedure verwendet.
Im onClick-Procedure des Button1 kannst du dann auf den "Sender" des Ereignis reagieren

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
if [sender as TButton].name = 'Button1'
then begin
....
end;
if [sender as TButton].name = 'Button2'
then begin
....
end;
......


Hallo an euch :) !
Das schaut doch sehr gut aus, das jetzt noch in eine Schleife, und mir bleib ein haufen Tipperrei erspart :)
Also so in etwa:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
for ii := 1 to MAX_BTN do 
if [sender as TButton].name = 'Button' + IntToStr(ii)
then begin
....
....
end;
......


ist das soweit richtig?

Zusatz:
Bei meiner gefundenen ersten Lösung meckert Delphi 5 aber auch nicht rumm und gibt mir jeweils das richtige Ergebnis für den Button aus, müßte dann also auch gehen.

MFG
LokutusvB


Narses - Di 09.10.07 12:23

Moin!

Also IMHO hast du immernoch einen Denkfehler in deinem Anwendungskonzept (heißt: du verwendest die VCL nicht designgerecht)... :nixweiss:

Trotzdem nochmal einen Ansatz als Denkzettel: ;)

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure TForm_Main.ButtonClick(Sender: TObject);  

begin  
  case (Sender as TButton).Tag of
    0// Dinge für Button.Tag=0 tun
    1// Dinge für Button.Tag=1 tun
    2// Dinge für Button.Tag=2 tun
    //...
  end;
end;

Setzt voraus, dass du die .Tag-Eigenschaft der Buttons passend im OI einstellst.

cu
Narses


LokutusvB - Di 09.10.07 12:49

Hm, Ok, danke für den Hinweis. Habe jetzt im OI den Buttons jeweils die Tag-Egenschaft vergeben (1 bis 10).

Ist mein folgender Ausschnitt nun desinggrecht, wenn nicht, warum? Verstehe das ganze leider noch immer nicht, warum meine beiden vorherigen Möglihckeiten nicht designgerecht sind.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm_Main.ButtonClick(Sender: TObject);
var
  ii: Integer;

begin
 {for ii := 1 to 10 do
  if (Sender = TButton(Form_Main.FindComponent('Button' + IntToStr(ii))))
   then ShowMessage('Button' + IntToStr(ii));   }

 for ii := 1 to 10 do
  if (Sender as TButton).Tag = ii then ShowMessage('Test: Button' + IntToStr(ii));
end;


MFG
LokutusvB


Miri - Di 09.10.07 13:32

Dein Denkfehler ist glaube ich einfach, dass du überhaupt keine Schleife brauchst!
Wenn du im OI jedem Button diese Prozedur im OnClick zuweist, dann wird - egal welcher Button geklickt wird - diese Prozedur aufgerufen.
Dank des Parameters "Sender" und die Nummerierung in den Tags weiß die Prozedur schon, welcher Button gerade gedrückt wurde. Du brauchst also nur noch sagen, was bei welchem Button passieren soll:

user profile iconNarses hat folgendes geschrieben:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure TForm_Main.ButtonClick(Sender: TObject);  
begin  
  case (Sender as TButton).Tag of
    0// Dinge für Button.Tag=0 tun
    1// Dinge für Button.Tag=1 tun
    2// Dinge für Button.Tag=2 tun
    //...
  end;
end;



Sprich: hinter "0:" kommt, was spezielles bei dem Button mit dem Tag 0 passieren soll. Hinter "1:" das, was bei Button mit Tag 1 passieren soll, und so weiter.
Wenn alle Buttons dasselbe tun sollen (z.B. ihre Tag-Nr. ausgeben), brauchst du nicht einaml das case, sondern einfach nur

Delphi-Quelltext
1:
2:
3:
4:
procedure TForm_Main.ButtonClick(Sender: TObject);  
begin  
  ShowMessage('Test: Button ' + inttostr((Sender as TButton).Tag);
end;


Narses - Di 09.10.07 13:33

Moin!

user profile iconLokutusvB hat folgendes geschrieben:
Ist mein folgender Ausschnitt nun desinggrecht,
Das bezog sich auf diese Aussage:
user profile iconLokutusvB hat folgendes geschrieben:
Nur habe ich noch nichts finden können, mit dem ich abfragen kann, ob ein Button ein Click-Event ausgelöst hat oder nicht, Click oder OnClick hilft mir der der If-Abfrage leider nicht weiter.


user profile iconLokutusvB hat folgendes geschrieben:
Verstehe das ganze leider noch immer nicht, warum meine beiden vorherigen Möglihckeiten nicht designgerecht sind.
Konkret: Es gibt keine Möglichkeit, "mit einer if-Abfrage einen Buttonklick zu behandeln", da eine VCL-Anwendung ereignisorientiert abläuft. Das Ereignis ist die Information, dass ein Button angeklickt wurde. Es ist demzufolge "nicht designgerecht", den Buttonzustand pollen zu wollen. :nixweiss:

Ich würde das so machen: ;)

Delphi-Quelltext
1:
2:
3:
4:
procedure TForm_Main.ButtonClick(Sender: TObject);
begin
  ShowMessage('Test: Button' + IntToStr((Sender as TButton).Tag));
end;

cu
Narses


LokutusvB - Di 09.10.07 13:38

Danke euch beiden, jetzt hab ich's gerafft ;)

Super, wie schön einfach das geht, wenn man nicht ganz so kompliziert denkt :)

Nochmals Danke und MFG
LokutusvB