Zeiger auf Ereignisfunktion übergeben



  • Moin!

    Ich habe eine Klasse, in der ich dynamisch, je nach Anforderung, Images anlege.
    Jetzt möchte ich denen aber eine Ereignisfunktion zuweisen.
    Innerhalb meiner Formulars würde ich das ja so machen:

    newImg->OnClick = ImgsClick;
    

    Das funktioniert (für mich überraschenderweise) mal richtig gut.

    Allerdings komm ich innerhalb meiner Klasse nicht an den Funktionzeiger. Ich übergebe zwar schon den Zeiger auf das Formular, aber

    Dest_Form->ImgsClick;
    

    klappt so gar nicht (ist ja auch __published)!

    Wenn ich also meinem Konstruktor gleich mitteilen will, wie die Ereignisfunktion heisst (bzw. der Zeiger darauf), von welchem Dateityp müsste das sein?

    [cpp]
    MyClass::MyClass(TForm* Dest_Form, TPanel* Dest_Panel, ???)
    [/cpp]

    Bin für jeden hilfreichen Hinweis dankbar!



  • MyClass::MyClass(... , TNotifyEvent NameDerLustigenKlickProzedur)
    


  • test = new MyClass(this, Panel1, ImgMouseDown);
    

    oder

    test = new MyClass(this, Panel1, *ImgMouseDown);
    

    bringt

    [C++ Fehler] Form_Tastatur.cpp(18): E2285 Keine Übereinstimmung für 'Tasten::Tasten(TFormTastatur * const,TPanel *,void (_fastcall * (_closure )(TObject *,TMouseButton,TShiftState,int,int))(TObject *,TMouseButton,TShiftState,int,int))' gefunden
    

    oder

    [C++ Fehler] Form_Tastatur.cpp(18): E2285 Keine Übereinstimmung für 'Tasten::Tasten(TFormTastatur * const,TPanel *,void)' gefunden
    

    Sorry, bin zu blöd (Hab irgendwie grad nen Blackout)! Brauch da mehr Hilfe! 😞



  • Hallo el Clio,
    ich bin nicht sicher ob ich dich verstanden habe. Du hast eine Form und in der Form deine Klasse MyClass. In MyClass erzeugst du dynamisch ein Image, dem du dann die Ereignisfunktion aus deiner Form für ein OnClick zuweisen möchtest. Die Funktion ist als __pubished deklariert.

    Mein Vorschlag:

    // In deiner Form (MyForm)
    MyTest = new MyClass(this, Panel1, MyForm);
    
    // Die Ereignisfunktion
    TMyForm::ImgClick(TObject *Sender)
    {
    }
    
    // In deiner Klasse
    TForm* DestForm;
    
    // z.B. im Konstructor
    DestForm = MyForm;
    
    // nach erzeugen eines neuen Image
    newImg->OnClick = DestForm->ImgClick;
    

    Ich habe das jetzt nicht getestet und erhebe keinen Anspruch auf Funktionsfähigkeit. Ob die Lösung nun elegan ist will ich auch nicht behaupten.

    Viele Erfolg
    Evi48



  • Hab ich genauso versucht, aber da die OnClick- (in meinem Fall OnMouseDown-) Funktion als __published deklariert ist habe ich über den Zeiger des TMyForm keinen Zugriff auf die Ereignisfunktion. (Ich nehme an, dass es daran liegt, auf jeden Fall hab ich keinen Zugriff von aussen.)



  • Na dann deklarir sie doch einfach als public. Du gehst in das h-File kopierst die Ereignisfunktion und fügst sie als public wieder ein unter __publishrd löscht oder remst die Funktion.

    Evi48



  • Auch das hatte ich schon gemacht, komischerweise "kommt" die dann ständig!
    Also direkt nach dem start des Progs hält es zig mal am Breakpoint in der Funktion - ohne dass das Formular einmal sichtbar gewesen wäre gescheige denn dass ich irgendwohin geklickt hätte.



  • Hallo el Clio,
    das kann ich mir nur so vorstellen, dass in einem Konstruktor die Funktion bereits aufgerufen wird. Hast du in deiner Form bereits ein Image welches die Funktion aufruft? So kann ich nur schlecht etwas dazu sagen warum schon beim Start des Programms die Funktion aufgerufen wird.

    Evi48



  • ???

    wieso wird die funktion direkt aufgerufen? ich geb dem Konstruktor ja nur den Zeiger auf die Funktion, das heisst ich würde gerne, und den dann zwischenspeichern.
    da wird doch nix aufgerufen... (oder?)

    mal anders gefragt:

    von was für einem Typ ist denn die OnMouseDown-Funktion eines TImage?



  • Das ist so per Ferndiagnose schlecht zu sagen. Etwas Code könnte jetzt hilfreich sein (new aus der Form und ein Teil deiner Klasse).

    Evi48



  • ok... Code kommt:

    // in meiner Klassen-Header
    class Tasten
    {
       private:
            ...
            void ImgsCreate(char from, char to, int *index_start, bool is_Shift, bool is_Space);
            ...
    
       public:
            Tasten(TForm* Dest_Form, TPanel* Dest_Panel);
            void ImgsMouseDown(TObject *Sender,
              TMouseButton Button, TShiftState Shift, int X, int Y);
            void ImgsMouseUp(TObject *Sender,
              TMouseButton Button, TShiftState Shift, int X, int Y);
            void ImgsClick(TObject *Sender);
    };
    
    // in meiner Klasen-cpp
    Tasten::Tasten(TForm* Dest_Form, TPanel* Dest_Panel)
    {
       ...
       ImgsCreate('1','9',&i,false,false);
       ...
    }
    
    void Tasten::ImgsCreate(char from, char to, int *index_start, bool is_Shift, bool is_Space)
    {
       ...
       // Ereignisfunktonen zuweisen
       // [HIER WERDEN JA NUR DIE KLASSENEIGENEN FUNKTIONEN ZUGEWIESEN - Ich möchte aber die des Formulars haben (Dest_Form->ImgsMouseDown wird verweigert!)]
       newImg->OnMouseDown = ImgsMouseDown; // Tastendruck
       newImg->OnMouseUp   = ImgsMouseUp;   // Taste loslassen
       newImg->OnClick     = ImgsClick;     // Klick
       ...
    }
    
    // in meiner Formular-cpp
    Tasten *tasten;
    //---------------------------------------------------------------------------
    __fastcall TFormTastatur::TFormTastatur(TComponent* Owner)
            : TForm(Owner)
    {
       tasten = new Tasten(this, Panel1);
       ...
    }
    

    So geht das zwar, es werden ja aber eben nur die Klasseneigenen Ereignisfunktionen zugewiesen. Ich möchte aber die des Formulars haben und möchte die mit übergeben, also etwa so:

    tasten = new Tasten(this, Panel1,ImgsMouseDown,ImgsMouseUp,ImgsOnClick);
    

    Wie muss dann die Deklaration aussehen?

    ...
    public:
            Tasten(TForm* Dest_Form, TPanel* Dest_Panel, ???, ???, ???);
    ...
    


  • du kannst nicht auf published-Funktionen zugreifen, sonst könnte ja jeder kommen und überall drin rum pfuschen.

    warum schreibst du nicht einfach neue als public deklarierte ereignis-funktionen, auf die kannst du dann per Form1->MyOnClick zugreifen.

    // header
    public:
      void __fastcall MyOnImageClick(TObject *Sender);
    
    // cpp
    void __fastcall TForm1::MyOnImageClick(TObject *Sender)
    {
      // blah
    }
    
    // dann etwa so beim erzeugen des bildes
    TMyImage *Image = new TMyImage();
    Image->OnClick  = Form1->MyOnImageClick;
    

    wenn du schon ne klasse hast, die ein bild dynamisch erzeugt, so sollte diese auch die nötigen ereignis-funktionen bereitstellen und diese nicht von irgendwo anders her klauben.

    was willst du denn überhaupt erreichen?
    welche funktionalität soll denn deine klasse bieten?



  • Sunday schrieb:

    wenn du schon ne klasse hast, die ein bild dynamisch erzeugt, so sollte diese auch die nötigen ereignis-funktionen bereitstellen und diese nicht von irgendwo anders her klauben.

    hab ich ja, wollte nur die Ereignisfunktionen des Formulars aufrufen, damit man auch sieht, wo das dazu gehört. Von da aus wollte ich eh meine Funktionen aufrufen.
    War eigentlich mehr sone "optik" Sache.

    Sunday schrieb:

    was willst du denn überhaupt erreichen?
    welche funktionalität soll denn deine klasse bieten?

    Das wird ne "dynamisch erzeugte" Bildschirmtastatur, bei der ich mir die Arbeit gespart hab, jedes "Tasten"-Bild einzeln einzubinden und einzurichten.
    Ich bau ne Auto- bzw. Wohnmobil-"Alarmanlage", die unter anderem auch DVD, Navi, Radio, Rückfahrkamera, Einparkhilfe, etc. steuert. Im Alarmmodus wird das Auto mit zig Gassensoren (von Campinggas bis K.O.-Gas), 3 Kameras, usw. überwacht und ist (fast) beliebig erweiterbar.
    Alles auf Xp-Basis, nur halt dass der Benutzer von XP nich viel zu sehen bekommt. Steuerung läuft mit 7"-Touchscreen. Damit der Benutzer auch schön sein Ziel ins Navi eingeben kann brauch ich halt die Bildschirmtastatur, und damits schöner aussieht mach ichs mit Bilder als Buttons. 😉



  • el Clio,

    el Clio schrieb:

    Wie muss dann die Deklaration aussehen?

    ...
    public:
            Tasten(TForm* Dest_Form, TPanel* Dest_Panel, ???, ???, ???);
    ...
    

    ein Beispiel:

    //Klassen-Deklation/Definition
    class MyClass
    {
        TImage* Image1;
    public:
        MyClass(TNotifyEvent clickEvent)
        {
            //...
            Image1->OnClick = clickEvent;
        }
    };
    
    //Instanz anlegen
    void __fastcall TForm1::Button7Click(TObject *Sender)
    {
        MyClass x(&Button7Click);
    }
    


  • Wenn dann so:

    void __fastcall TForm1::Button7Click(TObject *Sender)
    {
        ...
        MyClass *x = new MyClass(Button7Click);
        ...
    }
    


  • F98 schrieb:

    Wenn dann so: ...

    Wieso?



  • dschensky schrieb:

    el Clio,

    el Clio schrieb:

    Wie muss dann die Deklaration aussehen?

    ...
    public:
            Tasten(TForm* Dest_Form, TPanel* Dest_Panel, ???, ???, ???);
    ...
    

    ein Beispiel:

    //Klassen-Deklation/Definition
    class MyClass
    {
        TImage* Image1;
    public:
        MyClass(TNotifyEvent clickEvent)
        {
            //...
            Image1->OnClick = clickEvent;
        }
    };
    
    //Instanz anlegen
    void __fastcall TForm1::Button7Click(TObject *Sender)
    {
        MyClass x(&Button7Click);
    }
    

    Dann kommt das hier:

    [C++ Fehler] Form_Tastatur.cpp(18): E2285 Keine Übereinstimmung für 'Tasten::Tasten(TFormTastatur * const,TPanel *,void (_fastcall * (_closure )(TObject *,TMouseButton,TShiftState,int,int))(TObject *,TMouseButton,TShiftState,int,int))' gefunden
    


  • el Clio,
    jetzt setz Dich bitte mal hin und überlege, ob in Deinem letzen Posting vielleicht irgend welche Informationen fehlen könnten.🙄
    Versetze Dich dazu in die Lage des Lesers, der geneigt sein könnte, Dir bei Deinem Problem zu helfen.



  • dschensky schrieb:

    el Clio,
    jetzt setz Dich bitte mal hin und überlege, ob in Deinem letzen Posting vielleicht irgend welche Informationen fehlen könnten.🙄
    Versetze Dich dazu in die Lage des Lesers, der geneigt sein könnte, Dir bei Deinem Problem zu helfen.

    Sorry. Wenn ich deinen Vorschlag (siehe Zitat im bemängelten Beitrag) übernehme wird beim copilieren der o.g. Fehler gezeigt.

    (Hoffe, so isses besser ;-))



  • el Clio schrieb:

    (Hoffe, so isses besser ;-))

    Ach, was soll's: Eigentlich hatte ich gehofft, daß Du auf die Idee kommst, ein Stück Deines Quellcodes zu posten - als da wäre vor allem die Signatur Deiner Methode.
    (Es könnte auch eine gute Idee sein, vor dem Posten mal zu überprüfen, ob die Signatur in Deklaration und Definition tatsächlich identisch ist!?)



  • dschensky schrieb:

    Ach, was soll's: Eigentlich hatte ich gehofft, daß Du auf die Idee kommst, ein Stück Deines Quellcodes zu posten - als da wäre vor allem die Signatur Deiner Methode.
    (Es könnte auch eine gute Idee sein, vor dem Posten mal zu überprüfen, ob die Signatur in Deklaration und Definition tatsächlich identisch ist!?)

    Ach so! Naja, der Quellcode ist immernoch der gleiche, wie einige Posts vorher (ca. Anfang der 2. Seite). Habe "nur", wie gesagt, im Konstruktor das "TNotifyEvent ..." bzw. abgeändert in "TMouseEvent..." gemäss deinem Vorschlag übernommen. Sowohl in der Deklaration als auch beim Aufruf. Und bei beiden Versuchen hab ich das gepostete Ergebnis erhalten. Aber egal!

    Der ganze Aufwand passt langsam nicht mehr zum Gesamtaufwand. Ich belass es jetzt so, wies ist.

    Trotzdem ein dickes Danke an alle, die sich beteiligt haben!!!


Anmelden zum Antworten