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

Composants VCL Delphi Discussion :

Mimer TStringGrid.OnValidateEntry de Lazarus


Sujet :

Composants VCL Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 931
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 931
    Billets dans le blog
    6
    Par défaut Mimer TStringGrid.OnValidateEntry de Lazarus
    Bonjour,

    Une petite question, car j'ai de la suite dans les idées, ou de la suite, mais pas d'idées !

    Est-il possible d'adjoindre à un TStringGrid un comportement mimant l'événement se produisant en fin d'édition du contenu d'une cellule, permettant au choix de l'utilisateur le retour à la valeur antérieure ou à une valeur arbitraire (comme pour les StringGrid de Lazarus) ?

    Sans dériver la classe, sinon, ce serait facile !
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  2. #2
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 931
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 931
    Billets dans le blog
    6
    Par défaut
    J'ai pensé à utiliser des approches suggérées par cette discussion, ou à biaiser comme suggéré ici.

    Sinon, je peux envisager d'utiliser un objet qui gèrera des StringGrids qu'on lui aura confiées : il associera l'état de chacun aux événements qu'il en recevra, pour détecter l'entrée en mode édition et la sortie (OnEditingDone mais EditorMode False ?) en détournant leurs événements OnSelectCell et OnEditingDone. Mais est-ce bien propre ?

    En dérivant la grille, il suffit de :
    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
      // type natif sous Lazarus, dont les StringGrids permettent la validation de saisie
      TValidateEntryEvent = procedure(Sender: TObject; aCol, aRow: Integer; const aOldValue: string; var aNewValue: String) of Object;
     
      // descendant implémentant les fonctionnalités présentes sous Lazarus
      TdySQliteGrid = class(TStringGrid)
       private
        EditorPrevMode   : Boolean;
        EditorPrevCol    : LongInt;
        EditorPrevRow    : LongInt;
        EditorPrevValue  : string;
        FOnValidateEntry : TValidateEntryEvent;
       protected
        procedure WndProc(var Message: TMessage); override;
       public
        constructor Create(AOwner: TComponent); override;
        procedure Clear;
        property OnValidateEntry : TValidateEntryEvent read FOnValidateEntry write FOnValidateEntry;
      end;
     
    //...
     
    constructor TdySQliteGrid.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      EditorPrevCol    := Col;
      EditorPrevRow    := Row;
      EditorPrevMode   := False;
      EditorPrevValue  := '';
    end;
     
    procedure TdySQliteGrid.WndProc(var Message: TMessage);
    var
      NewValue : string;
    begin
     inherited;
     if EditorMode <> EditorPrevMode then
      begin
        EditorPrevMode := EditorMode;
        if EditorMode then
         begin // entrée dans le mode édition
           EditorPrevCol   := Col;
           EditorPrevRow   := Row;
           EditorPrevValue := Cells[Col, Row];
         end
        else
         begin // sortie du mode édition
           NewValue := Cells[EditorPrevCol, EditorPrevRow];
           if (NewValue <> EditorPrevValue) and Assigned(FOnValidateEntry) then
           begin // demande de validation de la saisie
             FOnValidateEntry(self, EditorPrevCol, EditorPrevRow, EditorPrevValue, NewValue);
             if NewValue <> Cells[EditorPrevCol, EditorPrevRow] then
               Cells[EditorPrevCol, EditorPrevRow] := NewValue; // entrée non validée
           end;
         end;
      end;
    end;
    mais je trouverais plus simple d'utiliser le type natif...
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  3. #3
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 489
    Par défaut
    salut

    perso je passerais par le TInplaceEdit

    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
     
    TStringGrid = Class(Grids.TStringGrid)
        function CreateEditor: TInplaceEdit; Override;
     
       ....
       Property OnEnterEdit ....
       Property OnExitEdit ....
      end;
    ....
    function TStringGrid.CreateEditor: TInplaceEdit;
    var
      Scaling : Boolean;
    begin
      result := Inherited CreateEditor;
      Result.onEnter := OnEnterEdit;
      Result.onExit    :=OnExitEdit;
    end;

  4. #4
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 931
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 931
    Billets dans le blog
    6
    Par défaut
    Bonjour,
    Je n'ai malheureusement pas réussi à l'implémenter de cette façon :
    - sous Tokyo 10.2, les événements TInPlaceEDit.OnEnter et OnExit sont protected ;
    - en utilisant un transtypage dans une classe de hack les exposant, pas de passage à l'exécution dans les événements affectés !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    type
      TMyInplaceEdit = class(Vcl.Grids.TInplaceEdit)
       public
        property OnEnter;
        property OnExit;
      end;
     
    function TMyStringGrid.CreateEditor: TInplaceEdit;
    begin
      Result := inherited CreateEditor;
      TMyInplaceEdit(Result).OnEnter := OnEnterEdit;
      TMyInplaceEdit(Result).OnExit  := OnExitEdit;
    end;
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  5. #5
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 593
    Billets dans le blog
    65
    Par défaut
    Bonjour,

    le problème n'est pas récent. Sur un autre site dont je tairai le nom j'ai trouvé ce code
    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
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    ...
    const
      WM_INPLACEEDIT_EXIT = WM_USER + $100;
     
    type
      TStringGridHelper = Class(TStringGrid);
     
    ...
    TForm1 = class(TForm)
    ...
        procedure FormCreate(Sender: TObject);
        procedure StringGrid1GetEditText(Sender: TObject; ACol, ARow: Integer;
          var Value: String);
        procedure StringGrid1Exit(Sender: TObject);
    ...
        OldWndProc, NewWndProc: TFarProc;
        hCurrentInplaceEdit: HWND;
        procedure HookInplaceEdit(hw: HWND);
        procedure InplaceEditWndProc(var Message: TMessage);
        procedure UnHookInplaceEdit(hw: HWND);
        procedure InplaceEditOnExit(var Message: TMessage); message WM_INPLACEEDIT_EXIT;
    ...
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      hCurrentInplaceEdit := 0;
      OldWndProc := nil;
      NewWndProc := nil;
    end;
     
    procedure TForm1.StringGrid1GetEditText(Sender: TObject; ACol,
      ARow: Integer; var Value: String);
    begin
      if Assigned(TStringGridHelper(StringGrid1).InplaceEditor) then
        HookInplaceEdit(TStringGridHelper(StringGrid1).InplaceEditor.Handle);
    end;
     
    procedure TForm1.StringGrid1Exit(Sender: TObject);
    begin
      if Assigned(TStringGridHelper(StringGrid1).InplaceEditor) then
        UnHookInplaceEdit(TStringGridHelper(StringGrid1).InplaceEditor.Handle);
    end;
     
    procedure TForm1.HookInplaceEdit(hw: HWND);
    begin
      if hCurrentInplaceEdit = 0 then
      begin
        OldWndProc := TFarProc(GetWindowLong(hw, GWL_WNDPROC));
        NewWndProc := Classes.MakeObjectInstance(InplaceEditWndProc);
        SetWindowLong(hw, GWL_WNDPROC, LongInt(NewWndProc));
        hCurrentInplaceEdit := hw;
        //SendMessage(Self.Handle, WM_INPLACEEDIT_EXIT, 1, 0);
      end;
    end;
     
    procedure TForm1.UnHookInplaceEdit(hw: HWND);
    begin
      if hCurrentInplaceEdit > 0 then
      begin
        SetWindowLong(hw, GWL_WNDPROC, LongInt(OldWndProc));
        hCurrentInplaceEdit := 0;
        if Assigned(NewWndProc) then
        begin
          Classes.FreeObjectInstance(NewWndProc);
          NewWndProc := nil;
        end;
        //SendMessage(Self.Handle, WM_INPLACEEDIT_EXIT, 2, 0);
      end;
    end;
     
    procedure TForm1.InplaceEditWndProc(var Message: TMessage);
    begin
      //call old proc
      Message.Result := CallWindowProc(OldWndProc, hCurrentInplaceEdit, Message.Msg,
        Message.wParam, Message.lParam);
     
      if Message.Msg = WM_KILLFOCUS then
      begin
        PostMessage(Self.Handle, WM_INPLACEEDIT_EXIT, 0, MakeLong(StringGrid1.Col, StringGrid1.Row));
      end;
    end;
     
    procedure TForm1.InplaceEditOnExit(var Message: TMessage);
    begin
      if Message.WParam = 0 then
      begin
        StringGrid1.Cells[Message.LParamLo, Message.LParamHi] := '111';
      end;
    end;
    Ce que j'aime c'est qu'il ne nécessite aucun développement de composant à vérifier si cela fonctionne et peut convenir

  6. #6
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 931
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 931
    Billets dans le blog
    6
    Par défaut
    Merci, Serge ; à étudier et adapter au besoin. Ce ne sera pas immédiat !
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Equivalent TStringGrid.OnValidateEntry de Lazarus
    Par tourlourou dans le forum Composants VCL
    Réponses: 3
    Dernier message: 06/10/2018, 16h55
  2. Réponses: 10
    Dernier message: 30/09/2014, 16h51
  3. [Lazarus] Editeur Pascal sous Linux
    Par jlambert dans le forum Lazarus
    Réponses: 3
    Dernier message: 05/02/2004, 12h32
  4. Delphi 7 et les TStringGrid
    Par Claude HENRY dans le forum Composants VCL
    Réponses: 6
    Dernier message: 28/05/2003, 09h18
  5. Comment imprimer le contenu d'un TStringGrid
    Par scorpiwolf dans le forum C++Builder
    Réponses: 2
    Dernier message: 19/06/2002, 15h41

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