Méthodes de l'inspecteur d'objet

sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 - 10 sept. 2013 à 14:24
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 - 13 sept. 2013 à 09:19
Bonjour,

Sur un projet, j'ai des traitements qui reviennent sur plusieurs Edit qui sont sur des forms différentes.
Pour le moment, je fais une procedure sur chaque unité que je rattache au contrôle par l'inspecteur d'objet à l'événement onKeyPress (en terme de maintenabilité, ce n'est quand même pas terrible)
Serait-il possible de déclarer une méthode sur la fiche principale de l'appli par exemple et de la rattacher par l'inspecteur d'objet ?
Ou suis-je obligé de faire une classe "TPersoEdit" avec ma gestion du keypress et dériver les compos dessus ?

8 réponses

jderf Messages postés 189 Date d'inscription mercredi 29 décembre 2004 Statut Membre Dernière intervention 2 octobre 2014 1
10 sept. 2013 à 16:06
Bonjour Simon,

Moi je ne sais faire que comme cela :

Dans mon unité générale

  
procedure MonEditKeyPress(Sender: TObject; var Key: Char);
var Edt : TEdit absolute Sender;
begin
   Edt.Text :=  'Modif générale';
   Edt.Color := ClBlue;
end;


Dans mes autres unités :
(en ajoutant dans les uses l'unité générale)
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  MonEditKeyPress(Sender, Key);
end;


Si il existe une façon de faire direct, je suis aussi preneur.

A+
Jderf
0
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
10 sept. 2013 à 16:33
Ok jderf, merci.

J'ai pris mon courage à deux mains et, suivant la technique que nous avait montré l'excellent Delphiprog, créé cette unité :

unit UMdf_Edit;

interface

  uses System.Classes, Vcl.StdCtrls, System.SysUtils;

Type
  edTypeEdit = (edNormal, edEntier, edReel);

  TEdit = class(Vcl.StdCtrls.TEdit)
     private
        FTypeEdit : edTypeEdit;
        procedure KeyPress(Sender: TObject; var Key: Char);
     public
        constructor Create(AOwner : TComponent); override;
     published
        property TypeEdit : edTypeEdit read FTypeEdit write FTypeEdit;
  end;

implementation

const
     Entiers = ['1'..'9', #8, '0', #13];
     Reels   = ['1'..'9', #8, ',', '0', '.', #13];

{ TEdit }

constructor TEdit.Create(AOwner : TComponent);
begin
     // Creation composant
     // * Initialisation du type d'edit
     // * Dérivation contrôle saisie
     inherited Create(AOwner);
     FTypeEdit  := edNormal;
     OnKeyPress := KeyPress;
end;

procedure TEdit.KeyPress(Sender: TObject; var Key: Char);
var
   Autorized : set of Char;
begin
     if FTypeEdit = edNormal then Exit; // >>> Saisie normale : Sortie
     // Choix des caractères autorisés
     case FTypeEdit of
          edEntier: Autorized := Entiers;
          edReel:   Autorized := Reels;
     end;
     // Contrôle frappe autorisée
     if not (key in Autorized)
        then key := #0;
     // Cas particulier saisie réel
     if FTypeEdit = edReel then begin
        if Key in ['.', ',']
           then key := DecimalSeparator;
     end;
end;

end.


Puis sur dans les types des unités de mon projet, j'ajoute :
  TEdit = class(UMdf_Edit.TEdit);


Et sur le FormCreate par exemple :
  MonEdit.TypeEdit := edEntier;


L'avantage, c'est que c'est réutilisable directement dans d'autres projets...
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
Modifié par Cirec le 10/09/2013 à 19:35
Salut,

oui c'est la méthode de Delphiprog qui est la meilleur pour ce cas de figure
mais j'y apporterai une petite modification.
je remplacerai l'affectation d'un OnKeyPress dans le constructeur par une surcharge de WMChar

Parce que si pour une raison X tu dois affecter le gestionnaire OnKeyPress d'un des TEdit tu perdras le traitement de ta surcharge !!!!

alors qu'avec le code qui suit tu peux sans rien perdre.
unit UMdf_Edit;

interface

  uses Classes, StdCtrls, SysUtils, Messages;

Type
  edTypeEdit = (edNormal, edEntier, edReel);

  TEdit = class(StdCtrls.TEdit)
     private
       FTypeEdit : edTypeEdit;
       procedure WMChar(var Message: TWMChar); message WM_CHAR;
     public
        constructor Create(AOwner : TComponent); override;
     published
        property TypeEdit : edTypeEdit read FTypeEdit write FTypeEdit;
  end;

implementation

const
     Entiers = ['1'..'9', #8, '0', #13];
     Reels   = ['1'..'9', #8, ',', '0', '.', #13];

{ TEdit }

constructor TEdit.Create(AOwner : TComponent);
begin
     // Creation composant
     // * Initialisation du type d'edit
     // * Dérivation contrôle saisie
     inherited Create(AOwner);
     FTypeEdit  := edNormal;
//     OnKeyPress := KeyPress;
end;

procedure TEdit.WMChar(var Message: TWMChar);
var
  Autorized : set of Char;
begin
  if FTypeEdit = edNormal then inherited; // >>> Saisie normale : Traitement par défaut
     // Choix des caractères autorisés
  case FTypeEdit of
    edEntier: Autorized := Entiers;
    edReel:   Autorized := Reels;
  end;
  // Contrôle frappe autorisée
  if Chr(Message.CharCode) in Autorized then
  begin
  // Cas particulier saisie réel
    if FTypeEdit = edReel then
    begin
      if Chr(Message.CharCode) in ['.', ','] then
        Message.CharCode := Ord(DecimalSeparator);
    end;
    inherited;
  end;
end;

end.


@+Cirec
0
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
11 sept. 2013 à 10:38
Salut Cirec et merci pour le code.

Effectivement ma "méthode" perd tout effet si on affecte un traitement à l'événement onKeyPress, alors que la tienne le prend en compte... sauf si la saisie ne répond pas aux critères de restriction. Ceci dit, à priori, si la saisie est mauvaise, il ne doit pas y avoir de traitement onKeyPress sur l'unité. De toutes façons, je ne vois pas trop comment lui dire de traiter l'événement onKeyPress malgré tout en conservant les restrictions de la dérivation de classe... Peut être en surchargeant l'événement "onKeyPress" ? (mais je n'ai jamais fait, je ne sais pas comment faire ni si c'est possible... Si tu as un exemple de surcharge d'événement, je suis preneur !)
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
11 sept. 2013 à 14:10
euh, petit bug Cirec... :)

Dans procedure TEdit.WMChar(var Message: TWMChar), dans le cas où on est en mode edNormal, Autorized n'est pas initialisé. Par défaut, il s'initialise avec certains caractères. Du coup, si on tape ces certains caractères ('e' par exemple), il appelle deux fois le "inherited", et la lettre tapée apparaît donc deux fois dans l'edit...

Fix :
procedure TEdit.WMChar(var Message: TWMChar);
var
   Autorized : set of Char;
begin
     if FTypeEdit = edNormal then inherited; // >>> Saisie normale : Traitement par défaut
        // Choix des caractères autorisés
     case FTypeEdit of
          edEntier: Autorized := Entiers;
          edReel:   Autorized := Reels;
     end;
     // Contrôle frappe autorisée
     if (FTypeEdit <> edNormal) // Contrôle si on est en mode restreint
        and (Chr(Message.CharCode) in Autorized) then begin
        // Cas particulier saisie réel
        if FTypeEdit = edReel then begin
           if Chr(Message.CharCode) in ['.', ',']
              then Message.CharCode := Ord(DecimalSeparator);
        end;
        inherited;
     end;
end;


0
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
11 sept. 2013 à 14:32
Et une petite question subsidiaire...

Pour étendre ce code au combobox, j'ai copié collé (beurk) et changé TEdit en TCombobox. Ce sont exactement les même traitements, mais je ne vois pas comment je peux factoriser ça...
Partant du fait que :
TEdit > TCustomEdit > TWinControl
et TComboBox > TCustomComboBox > TCustomCombo > TCustomListControl > TWinControl
J'ai essayé (naïvement) ça :

Type
  edTypeEdit = (edNormal, edEntier, edReel);


  TWinControl = class(Vcl.Controls.TControl)
     private
       FTypeEdit : edTypeEdit;
       procedure WMChar(var Message: TWMChar); message WM_CHAR;
     public
        constructor Create(AOwner : TComponent); override;
     published
        property TypeEdit : edTypeEdit read FTypeEdit write FTypeEdit;
  end;

  TCustomEdit = class(TWinControl);
  TEdit = class(TCustomEdit);

  TCustomListControl = class(TWinControl);
  TCustomCombo = class(TCustomListControl);
  TCustomComboBox = class(TCustomCombo);
  TComboBox = class(TCustomComboBox);


Mais le compilateur ne reconnait pas la propriété "items" du combobox qui est dans la classe TCustomListControl. Je perds toutes les propriétés et méthodes déclarées dans Vcl.StdCtrls,

J'ai aussi essayé en déclarant :
TWinControl = class(UMdf_CtrlSaisie.TWinControl);

dans l'unité de mon projet, mais là il ne reconnait plus la propriété TypeEdit de mes edit et combo...

N'y a t'il donc que le copier/coller qui peut fonctionner ?
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
11 sept. 2013 à 19:45
pour exécuter malgré tout l'évènement OnKeyPress voici la solution:
unit UMdf_Edit;

interface

  uses Classes, StdCtrls, SysUtils, Messages;

Type
  edTypeEdit = (edNormal, edEntier, edReel);

  TEdit = class(StdCtrls.TEdit)
  private
    FTypeEdit : edTypeEdit;
  protected
    procedure KeyPress(var Key: Char); override;
  public
    constructor Create(AOwner : TComponent); override;
  published
    property TypeEdit : edTypeEdit read FTypeEdit write FTypeEdit;
  end;

implementation

const
     Entiers = ['1'..'9', #8, '0', #13];
     Reels   = ['1'..'9', #8, ',', '0', '.', #13];

{ TEdit }

constructor TEdit.Create(AOwner : TComponent);
begin
     // Creation composant
     // * Initialisation du type d'edit
     // * Dérivation contrôle saisie
     inherited Create(AOwner);
     FTypeEdit  := edNormal;
end;

procedure TEdit.KeyPress(var Key: Char);
var
   Autorized : set of AnsiChar;
begin
  { au début ******}
  inherited; // si OnKeyPress est affecté il est déclanché
  if FTypeEdit = edNormal then Exit; // >>> Saisie normale : Sortie
  // Choix des caractères autorisés
  case FTypeEdit of
    edEntier: Autorized := Entiers;
    edReel:   Autorized := Reels;
  end;
  // Contrôle frappe autorisée
  if not {$ifdef UNICODE}CharInSet(key, Autorized){$else}
    (key in Autorized){$endif} then
      key := #0;
  // Cas particulier saisie réel
  if FTypeEdit = edReel then begin
    if {$ifdef UNICODE}CharInSet(key, ['.', ',']){$else}
      (key in ['.', ',']){$endif} then
        key := DecimalSeparator;
  end;
  { ****** ou en fin de traitement au choix}
  //inherited; // si OnKeyPress est affecté il est déclanché
end;

end.


cette version corrige le bug précédant qui d'ailleurs est des plus bizarre ... la répétition ne se fait pas sur tous les caractères et pas les mêmes que toi !!! enfin pas d'importance.

ps: les modification "CharInSet" son pour faire taire les messages du compilateur ;)
et "{$ifdef UNICODE}" pour permettre une compilation sur les version antérieurs à D2009

pour le reste je ne vois que le copier coller
0
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
13 sept. 2013 à 09:19
ok, merci Cirec !
0
Rejoignez-nous