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

Contribuez Delphi Discussion :

case of messages


Sujet :

Contribuez Delphi

  1. #1
    Membre éprouvé
    Avatar de Montor
    Homme Profil pro
    Autre
    Inscrit en
    Avril 2008
    Messages
    879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Avril 2008
    Messages : 879
    Points : 963
    Points
    963
    Par défaut case of messages
    voici ce petit code qui permet de sélectionner une opération parmi d'autres...
    la solution que jamais vu quelqu'un l'utilise (hormis le VCL et opérations liées aux handles mais pas sur un TList ,TDataSet)consistait à utiliser des messages pour selectionner ladite operation.
    Le but c'est pour enlever une zone d'ombre sur le traitement des messages...
    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
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    unit Unit2;
    interface
     
    const
       OP_ADD =   1;
       OP_SUS =   2;
       OP_MUL =   3;
       OP_DIV =   4;
    type
     
     TOperationStruct=record
      OperationKind :Word;
      Operand1      :Integer;
      Operand2      :Integer;
      Result        :Integer;
     end;
     
     TMathOperation=class
     private
       procedure xAdd(var Data:TOperationStruct);message OP_ADD;
       procedure xSus(var Data:TOperationStruct);message OP_SUS;
       procedure xMul(var Data:TOperationStruct);message OP_MUL;
       procedure xDiv(var Data:TOperationStruct);message OP_DIV;
     public
       procedure DefaultHandler(var message);override;
       function Calc(Opd1,Opd2:integer;Okind:Word):integer;
     end;
     
    implementation
     uses SysUtils;
    { TMathOperation }
     
    function TMathOperation.Calc(Opd1, Opd2: integer;
      Okind: Word): integer;
    var
      V:TOperationStruct;
    begin
       V.OperationKind :=Okind;
       V.Operand1      :=Opd1;
       V.Operand2      :=Opd2;
       Dispatch(V);
       Result :=V.Result;
    end;
     
    procedure TMathOperation.DefaultHandler(var message);
    begin
     raise Exception.Create('Opération non supportée !');
    end;
     
    procedure TMathOperation.xAdd(var Data: TOperationStruct);
    begin
       with Data do
        Result :=Operand1+Operand2;
    end;
     
    procedure TMathOperation.xDiv(var Data: TOperationStruct);
    begin
       with Data do
        Result :=Operand1 div Operand2;
    end;
     
    procedure TMathOperation.xMul(var Data: TOperationStruct);
    begin
      with Data do
        Result :=Operand1 * Operand2;
    end;
     
    procedure TMathOperation.xSus(var Data: TOperationStruct);
    begin
       with Data do
        Result :=Operand1 - Operand2;
    end;
     
     
    end.
    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    uses unit2;
    procedure TForm1.Button1Click(Sender: TObject);
    var
     C:TMathOperation;
    begin
      C:=TMathOperation.Create;
      try
        ShowmessageFmt('%d',[C.Calc(10,2,OP_ADD)]);
      finally
        C.Free;
      end;
    end;

  2. #2
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 692
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 692
    Points : 13 122
    Points
    13 122
    Par défaut
    Disons que tu appliques l'exemple de l'aide Delphi (Dispatch) en fournissant d'autres méthodes. Dire que ça retire certaines zones d'ombre est peut-être surfait. Les messages étant tout de même destinés à la communication inter-composants ou inter-processus .

    De plus, si nous parlons vraiment de messages (contrôles fenêtrés => handle), des constantes inférieur à WM_USER sont à proscrire...

  3. #3
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Perso j'utilise ça énormément dans mon logiciel FunLabyrinthe.

    Mais donner un exemple de moins de deux mille lignes qui montre en quoi ça répond à une problématique qu'on ne peut pas résoudre avec des méthodes virtual, c'est vraiment très dur...
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  4. #4
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Salut,

    Je trouve normal que personne l'utilise....
    Ca apporte quoi de plus (peut une migraine inutile) que la déclaration d'un type énuméré et un case sur ce type avec appel des méthodes appropriées?
    Akim Merabet

  5. #5
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Comme je l'ai dit, je ne peux pas te donner un exemple court qui exprime bien le besoin.

    Mais les méthodes message apporte ceci : tu peux "appeler des méthodes" sur un objet alors que ces méthodes n'ont jamais été déclarées. Et certaines sous-classes choisissent d'attraper certains de ces messages.

    Imaginons une hiérarchie de classes relativement complexe dont la classe racine est TRootObject. À un certain point, tu veux qu'une classe TSomeObject propose une méthode TrucMachin. Et à un autre point, tu veux appeler la méthode TrucMachin sur un objet de type TRootObject.

    Tu pourrais bien sûr faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if Obj is TSomeObject then
      TSomeObject(Obj).TrucMachin;
    Mais quid si à cet endroit tu ne peux pas avoir de référence à la classe TSomeObject (par exemple parce que celle-ci est définie dans un plugin de ton application). Tu ne peux donc pas savoir comment appeler la méthode TrucMachin.
    Tu as aussi un problème si beaucoup de classes descendantes de TRootObject veulent proposer la méthode TrucMachin. Tu n'as pas envie de devoir toutes les tester.

    Pour remédier à cela, tu vas déclarer TrucMachin comme une méthode message CM_TRUCMACHIN. Et tu pourras écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Msg.MsgID := CM_TRUCMACHIN;
    Obj.Dispatch(Msg);
    Ainsi, si la classe effective de Obj est TSomeObject ou toute autre classe (inconnue au moment de la compilation) qui propose la méthode de message CM_TRUCMACHIN, eh bien elle sera appelée, et sinon rien ne se passera. Et c'est gagné !
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  6. #6
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    En fait à la base, les procédures de message ont été introduites pour avoir un code plus lisible pour répondre aux messages Windows.

    Lorsque Windows a été conçu, la programmation objet existait à peine. La technique de l'époque pour avoir du polymorphisme consistait à travailler par messages qu'on envoyait à un point d'entrée unique.

    Au moment de développer la VCL, Borland devait gérer tous les messages windows dans les composants. Ils ont dû trouver plus claire et plus lisible d'implémenter le case du numéro de message et l'appel à la méthode correspondante directement dans le langage plutôt que dans les procédures de fenêtre.

    Personnellement aujourd'hui, mis à part pour dialoguer avec les messages Windows, ou pour exécuter un code après le traitement courant (avec un PostMessage), je ne vois pas trop l'utilité de la chose non plus.
    On dispose de beaucoup mieux : Les interfaces permettent de résoudre le problème de sjrd bien plus efficacement. De même pour l'exemple de Montor, ce serait plus simple et plus performant avec un pointeur de procédure.

  7. #7
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Citation Envoyé par Franck SORIANO Voir le message
    On dispose de beaucoup mieux : Les interfaces permettent de résoudre le problème de sjrd bien plus efficacement.
    En te lisant, j'ai hésité, et j'ai bien cru que j'avais fait une monstrueuse erreur de conception dans FunLabyrinthe.

    Il est vrai que les interfaces répondent au problème que j'ai décrit plus haut... Bien qu'il faille pour ça avoir une classe de base implémentant IInterface, et il faut souvent annihiler le comptage de références des interfaces.

    Mais dans FunLabyrinthe, mon problème est encore beaucoup plus complexe. Et, je ne pourrais pas l'expliquer en moins de trois pages d'arguments, mais dans mon cas les messages offrent une solution que les interfaces ne permettent pas.
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  8. #8
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Citation Envoyé par sjrd Voir le message
    Bien qu'il faille pour ça avoir une classe de base implémentant IInterface
    Je ne vois pas de quoi tu parles. Tu implémentes l'interface directement dans la classe qui doit implémenter les méthodes en question...

    Citation Envoyé par sjrd Voir le message
    et il faut souvent annihiler le comptage de références des interfaces.
    Malheureusement en Delphi c'est vrai. On ne peut pas définir d'interface qui ne dérivent pas de IUnknown. Ce qui oblige à déclarer et implémenter les trois méthodes QueryInterface, _AddRef et _Release. En revanche dans d'autres langages, il n'y a pas cette limitation.

    Citation Envoyé par sjrd Voir le message
    Mais dans FunLabyrinthe, mon problème est encore beaucoup plus complexe. Et, je ne pourrais pas l'expliquer en moins de trois pages d'arguments, mais dans mon cas les messages offrent une solution que les interfaces ne permettent pas.
    Evidemment, je répondais par rapport au besoin que tu décrivais dans l'exemple. Toi seul peut décider de la meilleure solution pour FunLabyrinthe .

  9. #9
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Oui suis d'accord, les interfaces sont plutôt un bon outil, surtout dans le cas d'une conception d'application modulaire sous forme de plugins.

    il faut souvent annihiler le comptage de références des interfaces
    Pourquoi se passer d'une gestion automatique de la mémoire. Perso j'ai toujours trouver cette fonctionnalité cool et j'ai jamais eu besoin de l'annihiler
    Akim Merabet

  10. #10
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Citation Envoyé par Kaféine Voir le message
    Pourquoi se passer d'une gestion automatique de la mémoire. Perso j'ai toujours trouver cette fonctionnalité cool et j'ai jamais eu besoin de l'annihiler
    Parce que parfois tu veux utiliser les interfaces pour justement ce dont on parle, mais que tu gères quand même la majorité de test objets avec des variables classes.

    Donc, si tu laisses le comptage de références, voici ce qui se passe.
    Tu travailles avec objets, bien gentillement. Leur compteur de références est à 0, mais ils ne sont pas détruits parce que tu n'appelles pas _Release.

    Puis tu transmets ton objet à une méthode générique qui travaille par interfaces. Celle-ci fait _AddRef au début... Et _Release à la fin. Paf, ton objet est détruit !

    Plus tard, tu continues à utiliser ton objet tranquillement... Et tu te tapes une AV

    Alors la gestion automatique de la mémoire, oui c'est cool, bien sûr ... Mais quand tout est géré automatiquement, pas seulement la moitié
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  11. #11
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    La destruction automatique des objets par les interfaces repose sur un comptage de références.
    Ce dernier possède également ses limites. En particulier si tu as des boucles dans tes références : A référence B et B référence A. Chaque objet est référencé au moins une fois, donc ni A ni B ne sont détruit.
    Sauf que si personne ne référence le cycle quelque part, ben les objets ne seront jamais détruits...

    De plus, tu as parfois des graphes de dépendances assez tordus. Avec des références pas toujours évidentes à suivre. Dans ce cas, on a recours à un objet maitre qui référence tous les autres, et lorsqu'on détruit l'objet maitre, on veut que tous les objets liés soient détruits en même temps, et ce sans avoir besoin de reparcourir tous les liens du graph pour les casser un par un...

    Enfin, comme l'a fait remarquer sjrd, tu peux très bien avoir ajouté une interface à un objet qui possède son propre cycle de vie.
    Par exemple, tu ajoutes une interface à un TForm...

  12. #12
    Membre éprouvé
    Avatar de Montor
    Homme Profil pro
    Autre
    Inscrit en
    Avril 2008
    Messages
    879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Avril 2008
    Messages : 879
    Points : 963
    Points
    963
    Par défaut
    Les messages windows ne sont pas si moches on peut les utilisées pour récupérer un membre privé...seul exemple que je peux citer TDataLink dans les contrôles DB

Discussions similaires

  1. Ajout d'une case à cocher dans un message box
    Par Jahjouh dans le forum MFC
    Réponses: 1
    Dernier message: 31/08/2007, 11h46
  2. affichage message avec case à cocher
    Par manu486 dans le forum Modélisation
    Réponses: 1
    Dernier message: 28/07/2007, 19h44
  3. [Formulaire] Message d'erreur case à cocher
    Par atlantideD dans le forum IHM
    Réponses: 1
    Dernier message: 06/07/2007, 19h12
  4. Afficher un message d'alerte dès que la sixième case est cochée
    Par JackBeauregard dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 16/01/2007, 17h03

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