IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Lazarus Pascal Discussion :

Indirection sur des TForms et appel de procédures


Sujet :

Lazarus Pascal

  1. #1
    Invité
    Invité(e)
    Par défaut Indirection sur des TForms et appel de procédures
    Bonjour,

    je n'arrive pas à créer - mais je ne sais pas si c'est possible dans ce cas - une indirection sur les TForms permettant d'utiliser des procedures contenues dans ces dernières.

    J'ai 2 Forms, Form1 et Form2 qui contiennent chacune une procedure disons ProcHomonyme() définie ainsi
    * procedure TForm1.ProcHomonyme(Sender: TObject); //dans l'unit1;
    * procedure TForm2.ProcHomonyme(Sender: TObject); //dans l'unit2;
    Evidemment bien qu'elles soient homonymes, elles ont des contenus différents. Elles sont appelées lors de la création de chacune des Forms 1 et 2 et ces 2 procédures sont également appelées par une autre Form, TFormMain, ainsi :

    uses ...., unit1, unit2;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var
        i : integer;
    begin
      for i := 0 to Screen.FormCount-1 do
        // uses StrUtils;
        case AnsiIndexStr(Screen.Forms[i].UnitName, ['unit1', 'unit2']) of
             0 : Form1.ProcHomonyme(nil);
             1 : Form2.ProcHomonyme(nil);
          //-1 : Aucun cas
        end;
    end;
    Cela fonctionne.


    Je me suis demandé si je pouvais faire une indirection sur une TForm avec Lazarus. C'est peut-être un peu osé voire même complètement idiot dans ce cas [appel d'une procédure] ?

    Donc, toujours dans TFormMain :

    type
    P = ^TForm;

    et dans la procédure d'appel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    var
        i : integer;
        F : P;
    begin
      for i := 0 to Screen.FormCount-1 do 
        begin
          new(F);
          F^ := screen.Forms[i];
          F^.Caption := 'Truc '+ IntToStr(i);  //Fonctionne bien. Le caption des 
          //Forms est bien changé.
          //Par contre 
          //F^.Name.ProcHomonyme(nil); :oops:
          // Peut-on appeler les fonctions ProcHomonyme(nil) ?
          // Si oui, comment ?
          // Faut-il les déclarer d'une manière spécifique dans les Forms 1 et 2 
          // (surchargées) pour qu'elles soient appelables avec cette méthode ? 
          dispose(F);
        end;
    end;
    Merci. Cordialement.
    Gilles
    Dernière modification par Invité ; 07/07/2010 à 14h30. Motif: Précisions

  2. #2
    Membre chevronné
    Homme Profil pro
    Inscrit en
    Janvier 2010
    Messages
    235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 235
    Par défaut
    Citation Envoyé par selzig Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
          //F^.Name.ProcHomonyme(nil); :oops:
          // Peut-on appeler les fonctions ProcHomonyme(nil) ?
          // Si oui, comment ?
          // Faut-il les déclarer d'une manière spécifique dans les Forms 1 et 2 
          // (surchargées) pour qu'elles soient appelables avec cette méthode ? 
          dispose(F);
        end;
    end;
    F^.Name retourne une valeur de type TComponentName qui en fait est une chaîne. Et comme une chaîne n'est pas un type objet et n'a donc pas de méthode ProcHomonyme cela ne peut effectivement pas marcher.

    Je ne suis pas certain de bien comprendre ce que tu veux faire mais je vais essayer.

    Je crois comprendre que ton but est de créer une méthode ProcHomonyme pour différentes fenêtres (TForm) définies dans différentes unités puis de créer un tableau de ces fenêtres et d'appeler la méthode ProcHomonyme pour chaque élément du tableau. C'est bien ça ?

  3. #3
    Invité
    Invité(e)
    Par défaut
    En effet, pour être clair,

    J'utilise un sdi maison et je gère les fenêtres ouvertes... à partir de uMain. Donc, en fonction du bouton sélectionné, toutes les fenêtres se réduisent ou se mettent en cascade,... ou depuis peu, on change de langue (pour les captions, title & co).

    J'ai déjà une solution rudimentaire avec mon case Of mais pour me faire plaisir, j'avais envie de voir ce que je valais en class derivée, méthode surchargée... Ben, c'est plus trop brillant... Enfin c'est ce qu'on voudrait pouvoir se dire. On sublime toujours le passé. Bon, ce n'est PAS brillant.

    J'ai donc créé une class dérivée de Tform (*pour tester, j'ai pris procShow à la place de ProcHomonyme...) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    type   
    TFormHomonyme = Class(TForm)
        private
          { private declarations }
        public
          { public declarations }
         Procedure procShow(Sender : TObject, sMess : string);
        end;
    Et c'est là qu'après, je ne suis plus...

    J'arrive bien à déclencher la ProcHomonyme dans une TForm1 par exemple, mais pas dans TForm2. Et d'un autre côté, cette ProcHomonyme doit également exister dans TFormMain... J'ai quelques bouts de code qui fonctionnent avec des TFormHomonyme(Tform1).ProcHomonyme(nil); Mais rien qui fonctionne globalement et dans les 3 fenêtres en même temps.

    Avec quelque chose du genre [dans un bouton de TformMain]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    procedure TFormMain.Button1Click(Sender: TObject);
    //Bouton de Test
    begin    
     TFormHomonyme(FormMain).TFormHomonyme(FormMain).procShow(nil,'en local');  
    {la ligne du dessus paraît idiote (puisque je suis dans TFormMain, 
    mais je ne veux pas différencier le code dans la boucle qui parcourt 
    les screen.Form[x]. 
    Que ce soit uMain ou unit1 et unit2 appelées par uMain, 
    la procédure d'appel de la fonction prosShow doit être identique.}
     Application.CreateForm(TForm1, Form1);
     Form1.Show;TFormHomonyme(Form1).procShow(nil,'en appel');   
     Application.CreateForm(TForm2, Form2);
     Form2.Show;TFormHomonyme(Form2).procShow(nil,'en appel');  
    end;
    en simplifiant au départ dans FormMain,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Procedure TFormHomonyme.procShow(Sender: TObject;sMess:string);
    begin
      FormMain.label1.caption:= smess;
    end;
    Je suis arrivé à quelques choses de plus satisfaisant en appelant les fonctions
    procShowMain, procShowForm1, ProcShowForm2 toujours avec des TFormHomonyme mais cela s'emboite mal dans le reste du code et c'est peu satisfaisant. Ce n'est pas ce que je cherchais.

    J'ai vainement essayé de dériver TFormHomonyme de uMain en sous classes
    TFormHomonyme1 dans unit1 et TFormHomonyme2 dans unit2 sans succès... et de plus cela semble compliquer abominablement le code... que j'essaie de maintenir simple.

    J'étais sur autre chose. Je regroupe ce que j'ai fait... et on en reparle si vous le voulez bien.

    Merci. Cordialement.
    Gilles
    Dernière modification par Invité ; 07/07/2010 à 20h01.

  4. #4
    Invité
    Invité(e)
    Par défaut
    Revoilà. Bon alors j'ai regardé. Ce qui fonctionne, c'est un truc (j'ai pas d'autres mots sinon ) de ce genre là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    unit uMain;
     
    {$mode objfpc}{$H+}
     
    interface
     
    uses
      Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
      unit1, unit2, {....} unitx;
    type
     
      { TFormMain }
       TFormuMain = class(TForm)
        private
          { private declarations }
          Procedure procShow(Sender: TObject;sMess:string);
        public
          { public declarations }
     
     
        end;
     
     
      TFormMain = class(TForm)
        Button1: TButton;
        Label1: TLabel;
        procedure Button1Click(Sender: TObject);
        private
        { private declarations }
     
      public
        { public declarations }
      end; 
     
    var
      FormMain: TFormMain;
     
     
    implementation
     
    {$R *.lfm}
     
    { TFormMain }
    Procedure TFormumain.procShow(Sender: TObject;sMess:string);
    begin
      FormMain.label1.caption:= smess;
    end;
     
    procedure TFormMain.Button1Click(Sender: TObject);
    begin
     
      TFormuMain(Formmain).procShow(nil,'en local');
      Application.CreateForm(Tform1, Form1);
      Form1.Show;
      TFormUnit1(Form1).procShow(nil, 'en appel');
    end;
     
    end.
    et pour chaque unit1, unit2,... unitx
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    unit Unitx; 
    
    {$mode objfpc}{$H+}
    
    interface
    
    uses
      Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
    
    type
    
      TFormunitx = class(TForm) // C'est malin !
        private
          { private declarations }
    
        public
          { public declarations }
          Procedure procShow(Sender: TObject;sMess:string);
    
        end;
    
      { TForm1 }
    
      TFormx = class(TForm)
        Button1: TButton;
        Label1: TLabel;
        procedure Button1Click(Sender: TObject);
      private
        { private declarations }
    
      public
        { public declarations }
    
      end;
    
    var
      Formx: TFormx;
    implementation
    uses uMain;
    {$R *.lfm}
    
    Procedure TFormUnitx.procShow(Sender: TObject;sMess:string);
    
    begin
      Formx.label1.caption:= smess;
    end;
    { TForm1 }
    
    procedure TFormx.Button1Click(Sender: TObject);
    begin
       TFormunitx(Formx).procShow(nil,'en local');
    end;
    
    end.

    ... et cela n'a absolument aucun intérêt Pas besoin de la classe dérivée ! On fait la même chose sans : on en revient au code Case Of

    D'un autre côté, il n'est pas question d'utiliser non plus procedure proSshow(Sender: TObject;sMess:string); overload; puisque toutes les procédures sont exactement identiques (dans leurs noms) et dans leurs variables.

    Resterait éventuellement à dériver dans unit1, unit2, ...initx, une TFormHomonyme déclarée dans umain et de la même façon que dans l'exemple ci-dessus on pourrait appeler la procedure contenue... Mais là encore, le code sera différent pour chaque fenêtre... Je crois donc que cela n'a aucun intéret avec les contraintes que je me suis fixé.

    Il semble finalement que c'est une mauvaise idée l'indirection dans ce cas-là... Batyann811, vous partagez cet avis ?

    Merci pour votre aide. Cordialement.
    Gilles
    Dernière modification par Invité ; 07/07/2010 à 20h55.

  5. #5
    Rédacteur
    Avatar de darrylsite
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2007
    Messages : 1 299
    Par défaut
    Il serait bien de prendre le temps de comprendre un peu mieux la programmation objet, et aussi celui utilisé par Free Pascal. ça te permettrait d'avoir du code plus propre.

    Il n'est pas aussi tres propre d'appeler directement les méthodes de tes TForm en dehors de leurs classes.
    En Free Pascal, on utilise la notion de Classe ce qui signifie que les objets sont transmis directement par référence ou par adresse.

    ton premier code peut juste s'écrire comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    var F : TForm;
    begin
      for i := 0 to Screen.FormCount-1 do 
        begin
          F := screen.Forms[i];
          F.Caption := 'Truc '+ IntToStr(i);
          //..............
    Pourquoi le reste du code ne marche pas?
    F est une instance de la classe TForm. Donc tu n'as accès qu'aux méthodes TForm des classes dérivées, les autres méthodes procShow, ... n'existe pas pour un objet de type TForm.

    Pour arriver au résultat que tu veux, il y a deux possibilité :
    • hériter d'une classe abstraite

    • Implementer une interface


    Je vais presenter ici la méthode de l'interface car elle est plus élégante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     IShow = Interface
      procedure procShow(); // pas besoin de l'implémenter
    end;                            //la déclaration suffit
     
    {........}
     Fenetre1 = class(TForm, IShow)
                     public
                       procedure procShow(); // méthode de l'interface à implémenter
                       {...}
                     end;
    Ton code devient alors
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    var
        i  : integer;
        F : TForm;
    begin
      for i := 0 to Screen.FormCount-1 do 
        begin
          F := screen.Forms[i];
          F.Caption := 'Truc '+ IntToStr(i);
          IShow(F).showProc();
        end;
    La méthode showproc de l'interface se charge d'appeler la méthode spécifique à l'affichage de la fenêtre.

    La deuxième solution que je ne vais pas présenter ici pour manque de place, consiste à passer par une classe abstraite.

    [DNK]
    Une des habitudes que j'ai eues en programmation java est d'utiliser une seule classe par fichier. ça aide beaucoup à se retrouver dans un projet contenant plusieurs classes.
    [/DNK]
    Le langage pascal est un langage élégant, alors utilisons le de manière élégante

  6. #6
    Membre chevronné
    Homme Profil pro
    Inscrit en
    Janvier 2010
    Messages
    235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 235
    Par défaut
    Pour ton problème de SDI maison je pense que pour faire ce genre de choses il faut passer par la création de composants. Je verrai bien un système avec 2 composants tous les 2 dérivé de TForm. Le premier (disons TFormMaster) serait utilisé comme fenêtre principale et ajouterait à une TForm normale la possibilité de gérer une liste de TFormSlave (le 2eme composant) avec des méthodes genre AddSlave, DeleteSlave. Il aurait en outre la capacité de passer des évenement à tous ses esclaves (genre fermeture, réduction, ...). Le 2eme composant (TSlave) devrait lui s'inscrire auprès de sa fenêtre principale (par AddSlave) à sa création, traiter les messages reçus de sa fenêtre principale et se désinscrire auprès de sa fenêtre principale (parDeleteSlave) lors de sa destruction.

    Je pense qu'un système comme ça doit être faisable avec Lazarus non ? J'ai quand même un doute sur la possibilité de faire l'enregistrement auprès de la fenêtre principale de façon graphique mais au pire ce serait une ligne de code dans le FormCreate de l'esclave.

  7. #7
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Merci batyann811,

    J'ai essayé un composant libre mais il ne convenait à cause des comportements "inégaux" disons des fenêtres iconisées sous Win et Nux et des superpositions des Forms en fonction des évènements.
    D'autre part le projet est déjà aboutit. J'en suis là.

    C'est à dire à intégrer dans mon code le nouveau menu langue et son code "actif".

    Donc comme je l'ai écrit, je fonctionne correctement en procedure "procedurale"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    { for i:=0 to Screen.FormCount-1 do
        // uses StrUtils;
        case AnsiIndexStr(Screen.Forms[i].UnitName, ['fmain', 'fsdeco']) of
             0 : FormMain.ChargerLangue(nil);
             1 : FormSDeco.ChargerLangue(nil);
            //-1 : //Aucun cas
        end;  }
    et donc je me suis demandé s'il était concevable de créer quelque chose du genre ci-dessous.

    La méthode qui m'est venue à l'idée avec les acquis dont je dispose et les quelques variations que j'ai tentées ne fonctionnent pas. Avant de bidouiller dans toutes les directions, j'ai donc fait appel aux spécialistes. Donc pour en revenir à ma question initiale :
    • faisable oui/non ?
      1. si non, pourquoi ?
      2. si oui, comment ?


    Cela me semble rationnel comme approche... et ce sont les questions que j'ai posées et dans cet ordre.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for i:=0 to Screen.FormCount-1 do begin
      new(F);
      F^ := TFormHomonyme(screen.Forms[i]);
      //F^.Caption:= 'truc';
      F^.ChargerLangue(nil);
      Dispose(F);
    end;
    Cordialement. Gilles
    Dernière modification par Invité ; 08/07/2010 à 12h42. Motif: Propos suffisants, impertinents et involontairement potentiellement blessants. Mes excuses à ceux qui les ont lus avant correction.

  8. #8
    Membre chevronné
    Homme Profil pro
    Inscrit en
    Janvier 2010
    Messages
    235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 235
    Par défaut
    Citation Envoyé par selzig Voir le message

    Cela me semble rationnel comme approche... et ce sont les questions que j'ai posées et dans cet ordre.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for i:=0 to Screen.FormCount-1 do begin
      new(F);
      F^ := TFormHomonyme(screen.Forms[i]);
      //F^.Caption:= 'truc';
      F^.ChargerLangue(nil);
      Dispose(F);
    end;
    En remarquant qu'il était possible de modifier ici la propriété caption de chaque Form mais que je ne voyais pas comment charger une procédure de même nom figurant dans chaque Form. Voilà avec une propriété intégrée dans le composant TForm cela fonctionne et la propriété s'appelle 'caption dans chacune d'elle. L'overload sur ChargerLangue ne peut pas être utilisé pour les raisons déjà invoquées. Je vais examiner vos explications et peut-être apprendre quelque chose. Auquel cas, j'aurai le plaisir de vous remercier...
    Première remarque : Les composant de la LCL sont des objets créé avec le mot clé 'class'. Ce type d'objet est manipulé par des pointeurs (on parle d'ailleurs plutôt de références dans ce contexte) donc quand tu déclares une variable P de type ^TForm c'est un pointeur de pointeur. Tu peux faire plus simple. Par exemple ce qui suit doit être équivalent à ton exemple.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    var 
      F: TForm;
     
    begin
      for i:=0 to Screen.FormCount-1 do 
      begin
        F := TFormHomonyme(screen.Forms[i]);
        //F.Caption:= 'truc';
        F.ChargerLangue(nil);
      end;
    end;
    2eme remarque: Quand tu crées une nouvelle unité fiche avec Lazarus en réalité tu crées un nouveau type. En créant une fiche Form1 et une fiche Form2 tu crées aussi les types TForm1 et TForm2. Ces 2 types héritent de TForm. Ils ont donc tous les 2 toutes les méthodes et toutes les propriétés de TForm. Tu peux donc utiliser Form1 et Form2 comme des TForm et utiliser la propriété Caption car c'est une propriété de TForm (polymorphisme). En revanche si tu ajoutes une méthode MaMethode à TForm1 et TForm2 tu ne peux pas utiliser Form1 et Form2 comme des TForm et espérer utiliser la méthode MaMethod car (même si MaMethod a le même protoptype dans les cas) ces 2 types sont vus comme différents par le compilateur. La seule façon de faire est de donner un ancêtre commun (TNewForm par exemple) à TForm1 et TForm2 ayant une méthode MaMethode. Pour cela tu dois créé un nouveau composant TNewForm et faire que Form1 et Form2 soit dérivés de ce composant. En fait on peut aussi se passer de créé un composant mais il faut renoncer au développement graphique et tous gérer à la main.

  9. #9
    Invité
    Invité(e)
    Par défaut
    "heula" comme disent les normands... je pense (enfin) avoir compris par différenciation de mes codes.

    En faisant le parallèle avec ce qui fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    unit fmain;
    {$mode objfpc}{$H+}
     
    interface
     
    uses uses ....,fsdeco; 
    Resourcestring
      rsFormcaption = 'Main Menu'; 
    type
      { TFormMain }
      TFormMain = class(TForm)
           procedure FormCreate(Sender: TObject);
           procedure ChargerLangue(Sender: TObject);
      private
        { private declarations }
     
      public
        { public declarations }
      end;      
     
    implementation
     
    procedure TFormMain.FormCreate(Sender: TObject);
    var i : integer;
    begin
      for i:=0 to Screen.FormCount-1 do
        // uses StrUtils;
        case AnsiIndexStr(Screen.Forms[i].UnitName, ['fmain', 'fsdeco']) of
             0 : FormMain.ChargerLangue(nil);
             1 : FormSDeco.ChargerLangue(nil);
            //-1 : //Aucun cas
        end;  
    end;     
     
    procedure TFormMain.ChargerLangue(Sender: TObject);
    begin
      FormMain.Caption := rsFormcaption;
    end;   
     
    initialization
      {$I fmain.lrs}
     
    end.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    unit fsdeco;
    {fen N° 2 (pour les messages)}
    {$mode objfpc}{$H+}
     
    interface
     
    uses
      [...] //N'inclut pas uMain  (--> dans implementation sinon ref. circ. et rien à voir avec le prob évoqué);
     
    resourcestring
        rsFormcaption = 'Management of environmental taxes';
    type
     
      { TFormSDeco }
        TFormSDeco = class(TForm)
        Procedure ChargerLangue(Sender: TObject);
      private
        { private declarations }
     
      public
     
        { public declarations }
      end; 
     
    var
      FormSDeco: TFormSDeco;
    implementation
     
    uses fmain;
    { TFormSDeco }
     
     
     
     
    Procedure TFormSDeco.ChargerLangue(Sender: TObject);
    begin
      FormSDeco.Caption                := rsFormcaption;
    end;
     
     
    initialization
      {$I fsdeco.lrs}
     
    end.
    Les 2 procédures ChargerLangues() portent bien le même nom. Elles sont dans la partie interface (et pas dans la partie private de chaque Form). Il n'y a pas de conflit et cela fonctionne, car Lazarus fait la différence entre FormMain.ChargerLangues(nil) et FormSDeco.ChargerLangue(nil) dans la procedure TFormMain.FormCreate(Sender: TObject);

    Le fait d'espérer que, de la même manière, il y ait moyen de différencier la surcharge TFormHomonyme déclarée dans FormMain contenant la procedure ChargerLangues de la surcharge TFormHomonyme déclarée dans Formsdeco contenant une autre procedure ChargerLangues est une ineptie complète. Donc je comprends les propos de Darrylsite en la matière... "Il serait temps de..."

    Pour l'autre solution, je comprends enfin j'espère. On inverse le problème. C'est la TForm de Lazarus qui dériverait d'une autre... Mais on se coupe du TForm de Lazarus.

    Cordialement. Gilles
    Dernière modification par Invité ; 08/07/2010 à 12h16.

  10. #10
    Membre chevronné
    Homme Profil pro
    Inscrit en
    Janvier 2010
    Messages
    235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 235
    Par défaut
    Citation Envoyé par selzig Voir le message
    J'essayer de dériver une class TFormHomonyme dans chaque TForm qui normalement est un objet à part entière...
    Tu peux développer un peu ça ? Je suis pas certain de comprendre ce que tu as fait.

  11. #11
    Invité
    Invité(e)
    Par défaut
    Oui, aucune pitié ces jeunes qui ont appris l'informatique au "biberon" POO alors que pour moi, il s'agit d'un apprentissage par "surchage". Bon, je m'enfonce...
    Quand je déclare
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    unit fmain;
    {$mode objfpc}{$H+}
     
    interface
     
    uses....
     
      TFormunit = class(TForm) 
        private
          { private declarations }
     
        public
          { public declarations }
          Procedure procShow(Sender: TObject;sMess:string);
     
        end;
     
      { TFormmain }
    la class TFormunit a sa déclaration "encapsulée" dans TFormMain : faut bien la déclarer quelque part... Mais quand on l'utilise, on applique la surcharge de la class à la FormMain... donc TFormunit(FormMain)... et donc il n'y a aucun parrallèle possible avec l'autre méthode (initiale qui fonctionne) ou avec une écriture comme Form1.label1.caption qui lui (le Tcaption) aussi est déclaré dans la Form... Re- Comme l'écrit Darrylsite... Bref, à force d'utiliser les objets tous les jours avec les composants tous prêt faits, j'avais oublié lors de cette tentative l'essence même et les rouages du concept... Ce qui n'est pas une excuse : Être curieux, c'est bien mais sans être c.., c'est mieux !

    Bon, j'assume mais on passe à autre chose, hein... La piqure de rappel est faite. C'est tout bon... jusqu'à la prochaine...

    Merci pour votre aide... et votre patience.
    Cordialement. Gilles
    Dernière modification par Invité ; 08/07/2010 à 12h30.

  12. #12
    Membre chevronné
    Homme Profil pro
    Inscrit en
    Janvier 2010
    Messages
    235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 235
    Par défaut
    Après réflexion (manger ça stimule) tu peux peut être te débrouiller sans devoir créer de nouveaux composants.

    1 - Tu ajoutes à ta fenêtre principale (MainForm) les méthodes AddSlave(Form : TForm) et DelSlave(Form: TForm)

    2 - Plutôt que d'appeler une méthode commune pour chaque esclave (ce qui t'obliges à les dériver d'un ancêtre commun) tu leurs envois un message. Regarde du coté de SendSimpleMessage, SendMessage, autres ?

    2 bis - Chaque fenêtre esclave implémente une interface (http://laurent-dardenne.developpez.c...hi/Interfaces/)

  13. #13
    Invité
    Invité(e)
    Par défaut
    Re-merci...
    Pour que j'arrive à assimiler ceci... va falloir être patient .

    Merci pour tout. Bonne fin de journée.
    Cordialement. Gilles

  14. #14
    Rédacteur
    Avatar de darrylsite
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2007
    Messages : 1 299
    Par défaut
    Citation Envoyé par selzig Voir le message
    Oui, aucune pitié ces jeunes qui ont appris l'informatique au "biberon" POO alors que pour moi, il s'agit d'un apprentissage par "surchage". Bon, je m'enfonce...


    Juste quelques définitions pour qu'on se comprenne et pour t'aider dans la chose:
    • Une classe ne peux encapsuler pas une autre. Mais on peut encapsuler (cacher) des données d'une classe pour qu'elle ne soit pas visible de l'extérieur.

    • On ne surcharge pas une classe, mais les méthodes d'une classe. Le procédé consiste à définir une méthode de même nom qu'une autre dans la classe.


    Sinon faire ClassA(ObjetClassB), est un cast ou transtypage. Ce qui permet d'utiliser la ObjetClassB comme ayant pour classe ClassA.

  15. #15
    Invité
    Invité(e)
    Par défaut
    Bonsoir Darrylsite,

    Oui, ce fait beaucoup de chemin finalement à partir de cette indirection...

    Je me suis rendu compte que finalement en Lazarus, j'utilise les fonctions et les procédures des objets, mais sans réellement "jouer" avec les classes... ce qui explique notamment ma difficulté à créer des composants.

    En mettant en relation cette discussion et le travail que j'étais en train de faire, je regardais en fin d'après midi, par curiosité (encore), les speedbutton.inc et autres buttons.pp pour voir comment était agencé le code. Je cherchais un SpeedButton à 4 états (images) [Over (enfin Enter), Leave, Selected (MouseDown) et Disabled]. C'est ce que j'écrivais à Batyann811... Va falloir du temps...

    Je réalise cela avec l'actuel TSpeedButton et une TImageList de Lazarus en 6 lignes : 2 à l'extérieur du TSpeedButton. 4 à l'intérieur [1 ligne x 4 évènements]. Mais actuellement, je n'imagine même pas d'où partir et encore moins le temps qu'il me faudrait pour créer un TSpeedButtonX4 qui modifie les 4 évènements (enfin qui fasse apparaître les 4 états correctement en fonction des évènements ou/et de la propriété Enabled)... et qui intègre 4 glyphs au lieu d'1 dans l'Inspecteur d'Objet... Je deviens gourmand. C'est vraiment une autre approche.

    Je termine mon programme actuel et je m'y mets juste après. Enfin, je commencerai par un composant non visuel à partir de Tcomponent donnant version, copyright &co des projects sous Nux et Mac (et Windows -mais cela en Windows en passant par les API cela se fait déjà). Le code "procédural" est prêt. J'ai corrigé et amélioré un petit utilitaire que j'avais réalisé il y a qqs temps et placé sur le forum. J'ai enfin réussi à intégrer l'image du composant. Mais c'est pas gagné du tout... On aura certainement l'occasion d'en reparler... en employant de mon côté les termes appropriés (enfin j'espère).

    Cordialement. Gilles
    Dernière modification par Invité ; 08/07/2010 à 21h03.

Discussions similaires

  1. Clés primaires sur des tables externes, alternatives par procédures stockées ?
    Par Jean-Philippe André dans le forum Développement
    Réponses: 18
    Dernier message: 10/07/2012, 17h21
  2. Etablir des liens sur des niuméros pour appels automatiques
    Par zerobug dans le forum Général Dotnet
    Réponses: 3
    Dernier message: 17/11/2008, 11h13
  3. Réponses: 12
    Dernier message: 19/08/2007, 19h26
  4. [SQL-Server] requête sur des procédures stockées
    Par babap1 dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 05/07/2007, 13h23
  5. Réponses: 1
    Dernier message: 26/02/2007, 09h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo