2015-10-20 15 views
5

Bevor ich beginne ich muss bestätigen, dass kein anderer Stapelüberlauf Beitrag zu diesem Thema michOnClick-Ereignis für dynamische Schaltfläche?

noch geholfen hatte

Ich habe eine dynamische Schaltfläche namens von btnApply

Es erstellt wird dynamisch auf einer dynamischen Form frmSort durch ein auf Klick Ereignis statischer Taste btnSort auf statische Form frmTable

Unter dem globalen Bereich var von frmTable wird

erklärt
btnApply: TButton; 
Procedure btnApplyClick(Sender:TObject); 
//other vars 

Unter dem btnSort auf Klick

//other code 
btnApply:= TButton.create(frmSort); 
//all its properties 
BtnApply.onclick:= btnApplyClick; 
//other code 

Dann später

Procedure btnApplyClick(Sender:TObject); 
Begin 
    //it's code it has to execute 
End; 

Ich erhalte eine Fehlermeldung beim "BtnApply.onclick: = btnApplyClick;" Zeile der inkompatiblen Typen zwischen Methodenzeiger und regulärer Prozedur

Wie kann ich das machen?

Vielen Dank im Voraus

Antwort

13

Ihre btnApplyClick Bedürfnisse ein Verfahren zur Herstellung eines Objektes sein. Da die Schaltfläche in einem Formular sein muss trotzdem nützlich sein, machen sie ein Verfahren zur Herstellung der Form selbst:

type 
    TfrmSort = class(TForm) 
    // UI controls listed here 
    public 
    procedure btnApplyClick(Sender: TObject); 
    end; 

implementation 

procedure TfrmSort.btnApplyClick(Sender: TObject); 
begin 
    (Sender as TButton).Caption := 'You clicked me'; 
end; 

procedure TfrmSort.FormCreate(Sender: TObject); 
var 
    Btn: TButton; 
begin 
    Btn := TButton.Create(Self); 
    Btn.Parent := Self; 
    Btn.Top := 100; 
    Btn.Left := 100; 
    Btn.OnClick := btnApplyClick; 
end; 

Wenn aus irgendeinem Grund können Sie es nicht ein Formular Methode machen (obwohl ich nicht sehen kann wie dies der Fall für eine visuelle Kontrolle wäre), können Sie es sich um ein Verfahren nach einem Objekt machen, wie folgt aus:

implementation 

// You must use StdCtrls in order to have the types available if 
// it's not already in your uses clause 
type 
    TDummyButtonClickObj = class 
    class procedure ButtonClickHandler(Sender: TObject); 
    end; 

{ TDummyButtonClickObj } 

class procedure TDummyButtonClickObj.ButtonClickHandler(Sender: TObject); 
begin 
    (Sender as TButton).Caption := 'You clicked me.'; 
end; 

procedure TForm2.FormCreate(Sender: TObject); 
begin 
    with TButton.Create(Self) do 
    begin 
    Parent := Self; 
    Top := 100; 
    Left := 100; 
    Caption := 'Click here'; 
    OnClick := TDummyButtonClickObj.ButtonClickHandler; 
    end; 
end; 
+0

Ich sehe:

procedure btnApplyClick(Self: Pointer; Sender: TObject); 
  • Verwenden Sie die TMethod Aufzeichnung das Verfahren die Taste zuweisen dein erster punkt aber leider ist mein frmSort nicht als typ wie die frmTable deklariert, sondern eher als frmSort : TForm zusammen mit dem btnApply: TButton im var. Und ich bin ein unerfahrener Programmierer, also kenne ich auch keine Klassen. Kann ich den Typ frmSort = class (TForm) umgehen oder ist es der einzige Weg – RaymondSWalters

  • +0

    Ihr zweiter hat funktioniert. Vielen Dank man – RaymondSWalters

    +1

    Es ist auch möglich, eine ** Nicht-Mitglied ** Prozedur als Event-Handler zu verwenden. Es dauert nur ein paar zusätzliche Schritte, um einzurichten. Fügen Sie einen zusätzlichen expliziten Parameter hinzu, um den 'Self'-Zeiger zu berücksichtigen:' procedure btnApplyClick (Self: Pointer; Sender: TObject); 'und verwenden Sie dann den' TMethod'-Record, um die Prozedur der Schaltfläche zuzuweisen: 'var M: TMethod; M.Code: = @btnApplyClick; M.Data: = Null; BtnApply.onclick: = TNotifyEvent (M); ' –

    8

    wie andere gesagt haben, sollte die Ereignisbehandlungsroutine ein Mitglied einer Klasse sein. Das erwartet die Veranstaltung. Es ist jedoch auch möglich, eine Nichtmitglieds--Prozedur als Ereignisbehandler zu verwenden. Es dauert nur ein paar zusätzliche Schritte, um einzurichten.

    1. einen zusätzlichen expliziten Parameter hinzufügen für die Self Zeiger zu berücksichtigen:

      var 
          btnApply: TButton; 
          M: TMethod; 
          //other vars 
      
      Procedure btnApplyClick(Self: Pointer; Sender: TObject); 
      
      ... 
      
      btnApply := TButton.create(frmSort); 
      //all its properties 
      M.Code := @btnApplyClick; 
      M.Data := nil; // can be anything you want passed to the Self parameter 
      BtnApply.onclick := TNotifyEvent(M); 
      //other code 
      
      ... 
      
      procedure btnApplyClick(Self: Pointer; Sender: TObject); 
      Begin 
          // code to execute 
      End; 
      
    +0

    Kens Antwort funktionierte, aber ich werde das auch versuchen.Danke – RaymondSWalters

    +1

    Ich würde das überhaupt nicht empfehlen. Weitaus besser ist es, eine Klassenmethode zu verwenden, um solche Tricks zu vermeiden, wenn Sie dies tun müssen, ohne eine Instanz zu haben. –

    +3

    Das ist deine Meinung. Es gibt nützliche Fälle, in denen dies nützlich ist, z. B. das Übergeben benutzerdefinierter Kontextinformationen direkt an den Event-Handler, ohne sie anderswo speichern zu müssen, wie in der Eigenschaft "Tag" des Steuerelements. Benutze es oder nicht, es ist deine Wahl. Ich verwende diesen Ansatz die ganze Zeit, wenn ich Konsolen-Apps verwende, um ereignisgesteuerten Code zu testen, ohne dafür UIs zu erstellen. –

    Verwandte Themen