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 :

Soucis de tabulation et TDateTimePicker.


Sujet :

Composants VCL Delphi

  1. #1
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2021
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2021
    Messages : 20
    Points : 13
    Points
    13
    Par défaut Soucis de tabulation et TDateTimePicker.
    Bonjour ! J'ai un petit soucis avec les TDateTimePicker, au niveau de la tabulation. En effet, mon TDateTimePicker est dans un tableau (DBGrid), dans une certaine colonne. Quand on passe dans la colonne, je mets le focus dans le DateTimePicker pour que l'utilisateur puisse saisir sa date sans soucis. Sauf qu'ensuite, j'ai un petit problème au niveau de la tabulation. Les utilisateurs naviguant entièrement via la touche TAB, j'aimerai pouvoir leur faire quitter la saisie et leur faire changer de colonne en appuyant une fois sur TAB. Le problème, c'est que je n'y arrive pas. Le plus proche ou je suis arrivé, c'est qu'ils doivent appuyer deux fois sur TAB. Une fois, ça semble "quitter" la saisie (ce n'est plus surligné en bleu) et ensuite le deuxième TAB les passe à la colonne d'après. J'ai essayé de modifier le comportement de la tabulation dans les événements KeyPress, KeyDown, KeyUp, mais ils ne détectent pas la touche TAB dans les événements. (semble être fait exprès selon internet...)

    Y'a t-il une petite solution ou un workaround pour combler ce soucis ?

    Merci d'avance

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 634
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 634
    Points : 25 352
    Points
    25 352
    Par défaut
    TDateTimePicker utilisé comme un inplace editor d'un TDBGrid avec une gestion du défilement horizontale et vertical, le bon positionnement peut être délicat et pourra changer selon le comportement de la VCL impacté par Windows, les Styles ...
    En plus pour une saisie rapide où l'utilisateur enchaine les données, le TDateTimePicker en plus est un peu capricieux sur sa saisie, son masque est très rigide.

    C'est le bouton calendrier qui vous est nécessaire
    Si oui, voir plus bas ButtonStyle
    Si non, un Format suffit largement sans créer un control via TDateField EditMask pour la saisie et DisplayFormat pour l'affichage + OnValidate pour vérifier que c'est une date valide
    un champ TDateField devrait contenir le mask date de l'OS ... cela ne serait pas une saisie dans un TStringField par hasard ?

    la version EditMask permet de supprimer tout besoin d'un controle et donc tout problème de Focus et de "Next Control" lors du TAB


    ButtonStyle : Il faut mettre une column en ButtonStyle to cbsEllipsis pour créer un bouton et gérer OnEditButtonClick

    J'ai fourni le code complet : DBGridEventDatesEditButtonClick qui va créer à la volée un TDateTimePicker dans une fenêtre de dialogue qui ressemble à un InputQuery mais on peut faire quelque chose de plus réduit à presque donner l'impression que le champ est dans la grille.

    Les deux peuvent être combiner évidemment, c'est ce qui donne l'impression d'avoir un TDateTimePicker dans la grille mais en réalité c'est EditMask + cbsEllipsis combiné qui donne cette illusion.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2021
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2021
    Messages : 20
    Points : 13
    Points
    13
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    TDateTimePicker utilisé comme un inplace editor d'un TDBGrid avec une gestion du défilement horizontale et vertical, le bon positionnement peut être délicat et pourra changer selon le comportement de la VCL impacté par Windows, les Styles ...
    En plus pour une saisie rapide où l'utilisateur enchaine les données, le TDateTimePicker en plus est un peu capricieux sur sa saisie, son masque est très rigide.

    C'est le bouton calendrier qui vous est nécessaire
    Si oui, voir plus bas ButtonStyle
    Si non, un Format suffit largement sans créer un control via TDateField EditMask pour la saisie et DisplayFormat pour l'affichage + OnValidate pour vérifier que c'est une date valide
    un champ TDateField devrait contenir le mask date de l'OS ... cela ne serait pas une saisie dans un TStringField par hasard ?

    la version EditMask permet de supprimer tout besoin d'un controle et donc tout problème de Focus et de "Next Control" lors du TAB


    ButtonStyle : Il faut mettre une column en ButtonStyle to cbsEllipsis pour créer un bouton et gérer OnEditButtonClick

    J'ai fourni le code complet : DBGridEventDatesEditButtonClick qui va créer à la volée un TDateTimePicker dans une fenêtre de dialogue qui ressemble à un InputQuery mais on peut faire quelque chose de plus réduit à presque donner l'impression que le champ est dans la grille.

    Les deux peuvent être combiner évidemment, c'est ce qui donne l'impression d'avoir un TDateTimePicker dans la grille mais en réalité c'est EditMask + cbsEllipsis combiné qui donne cette illusion.
    Merci pour la quantité incroyable d'information. En effet, avant j'utilisais un masque dans un tdatetimepicker pour ne pas avoir de problèmes de focus, mais la solution est capricieuse elle aussi.. Si j'ai bien compris, la solution dans votre autre post inclut un pop-up (input query) pour rentrer les infos, donc ce n'est pas exactement la solution que je recherche. J'essaie de trouver une solution qui me permet de gérer simplement le champ dans la DBGRID (TDateTimeField) tout en permettant à l'utilisateur d'utiliser un calendrier si ça lui parait plus pratique. Donc, si j'ai bien suivi, il faudrait que je mette en place un EditMask + le système de cbsEllipsis et class helper ?

    Merci beaucoup

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 634
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 634
    Points : 25 352
    Points
    25 352
    Par défaut
    Oui
    Avec un TDateTimeField, le EditMask devrait déjà être défini mais on peut le changer, et la validation de la valeur se fait à la sortie de la colonne (sur le Tab donc)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        EditMask := '!00/00/0000 00:00:00;1;_';

    En fait, le TDBGrid met en place un InplaceEditor, on peut l'améliorer mais ce n'est pas évident.
    Regarde TDBGridInplaceEdit dans le code mais cela oblige à redéfinir beaucoup de chose ...
    En D3 et D7, j'avais même bricoler un truc inverse, les utilisateurs avaient du mal avec le comportement au clavier du TDateTimePicker, et je superposais un TMaskEdit par dessus pour un comportement à la frappe plus fluide que le TDateTimePicker de WinXP tout en conservant le bouton pour le calendrier et aussi cela incluait la gestion d'une Date Nulle et non d'une Date par défaut (0 par exemple)

    Mais par défaut avec le TDateTimeField il manque un bouton pour ceux qui préfère un calendrier visuel, là, on peut utiliser pour juste une Date un TMonthCalendar que l'on peut faire apparaître comme un Popup, avec OnMouseLeave, on peut gérer la "fin de la saisie" ou lors d'un OnClick du DBGrid, gérer la fermeture du composant, en fait on simule le comportement du TDateTimePicker.

    Il faut voir l'ergonomie en mode rapide et en mode click de façon différente, ne pas chercher à optimiser l'une avec l'autre.
    Pour moi, il faut optimiser à fond le mode saisie de masse avec des TAB pour une saisie rapide, pour ça TDateTimeField et son EditMask reste le meilleur moyen car c'est fait pour
    Et pour ceux qui sont plus habitués à cliquer, le cbsEllipsis leur affichant un popup fera le travail mais dans ce cas, on oublie le TAB

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      for I := 0 to DBGrid.Columns.Count - 1 do
        if DBGrid.Columns[I].Field is TDateTimeField then
          DBGrid.Columns[I].ButtonStyle := cbsEllipsis;
      DBGrid.OnEditButtonClick := DBGridDateTimeFieldEventHandler;
    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
    procedure TDBGridKeyIncMainForm.DBGridDateTimeFieldEventHandler(Sender: TObject);
     
      procedure ShowDateEditor(AGrid: TDBGrid; AField: TDateTimeField);
     
        function GetCol(): Integer;
        var
          I: Integer;
        begin
          for I := 0 to AGrid.Columns.Count - 1 do
            if AGrid.Columns[I].Field = AField then
              Exit(AGrid.Columns[I].Index);
     
          Result := -1;
        end;
     
      var
        Col, Row: Integer;
        Form: TForm;
        Editor: TDateTimePicker;
        CellRect: TRect;
      begin
        Col := GetCol();
        if dgIndicator in DBGrid.Options then
          Inc(Col);
        Row := TDBGridHack(DBGrid).Row;
     
        CellRect := TDBGridHack(DBGrid).CellRect(Col, Row);
     
        Form := TForm.Create(nil);
        Form.BorderStyle := bsNone;
        Form.AutoSize := True;
        Form.Position := poDesigned;
        Form.Left := CellRect.Left;
        Form.Top := CellRect.Top;
     
        Editor := TDateTimePicker.Create(Form);
        Editor.Parent := Form;
        Editor.OnKeyDown := DBGridDateTimeFieldKeyDownEventHandler;
        Editor.OnCloseUp := DBGridDateTimeFieldCloseUpEventHandler;
        Editor.Tag := NativeUInt(AField);
        Editor.DateTime := AField.Value;
        Editor.Kind := dtkDate;
     
        Form.Parent := AGrid;
        Form.Show();
      end;
     
    begin
      if Sender is TDBGrid then
        if TDBGrid(Sender).SelectedField is TDateTimeField then
          ShowDateEditor(TDBGrid(Sender), TDateTimeField(TDBGrid(Sender).SelectedField));
    end;
     
    procedure TDBGridKeyIncMainForm.DBGridDateTimeFieldKeyDownEventHandler(Sender: TObject; var Key: Word; Shift: TShiftState);
    begin
      if Key in [VK_TAB, VK_RETURN] then
        DBGridDateTimeFieldCloseUpEventHandler(Sender);
    end;
     
    procedure TDBGridKeyIncMainForm.DBGridDateTimeFieldCloseUpEventHandler(Sender: TObject);
    begin
      if Sender is TDateTimePicker then
      begin
        with TDateTimeField(TDateTimePicker(Sender).Tag) do
        begin
          DataSet.Edit();
          Value := TDateTimePicker(Sender).DateTime;
          DataSet.Post();
        end;
     
        TForm(TDateTimePicker(Sender).Owner).Release();
      end;
    end;

  5. #5
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2021
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2021
    Messages : 20
    Points : 13
    Points
    13
    Par défaut
    Salut ! Merci beaucoup pour ton aide ! Tout fonctionne parfaitement avec la tabulation, j'ai juste un dernier petit soucis assez pénible... Quand je change de colonne en appuyant sur Entrée, tout fonctionne parfaitement sauf sur le champ ou il y a mon datetimepicker, le onDrawcolumnCell ne se fait pas correctement, et la colonne est toujours paramétrée sur la précédente et non sur celle ou j'arrive, ce qui empêche le bon fonctionnement de mon code (le datetimepicker n'apparait pas et on est en saisie normale). As-tu déjà rencontré un problème de ce type ? J'ai testé beauuucoup de choses, de focus, de repaint etc... sans aucun succès.

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 634
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 634
    Points : 25 352
    Points
    25 352
    Par défaut
    Non cela ne m'arrive plus car j'ai abandonné dans le TDBGrid de changer le InplaceEditor, Mask et rien d'autres + OnValidate + OnSetText pour les controles\patch
    La dernière fois que j'ai eu de la saisie de masse, c'était avec des grilles des TtsGrid si je me souviens bien, un composant trainé depuis D5 vers XE2 et plus
    Ou alors du TMS TAdvGrid

    Je suis même revenu à un TStringGrid pour certaines saisies

    Et pour une très grosse saisie, c'était de la TDBCtrlGrid + TDBGrid, par chance, que des montants ou des coefs à saisir : Gérer l'affichage dans TDbCtrlGrid
    Au pire, tu devrais avoir dans la TDbCtrlGrid 4..9 x 2 x 50 TDBEdit, et au final, une bonne partie était dans un Excel et j'avais donc prévu un import



    MAis avec la TListView, certains dessins en dernière colonne provoque un effet de bord comme changer la police ... par manque de temps, je mettais en dernier une colonne sans texte ou un colonne avec un bouton dessiné qui permettait de consulter le détail de l'élément en cours.

Discussions similaires

  1. [XL-MAC 2011] souci tabulation sur EXCEL
    Par mariok dans le forum Conception
    Réponses: 15
    Dernier message: 12/03/2014, 15h28
  2. [XL-2003] Souci de tabulation
    Par phal2ip dans le forum Excel
    Réponses: 2
    Dernier message: 03/02/2010, 18h52
  3. soucis de tabulation
    Par presser dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 12/03/2009, 10h37
  4. [VB6] Touche de tabulation
    Par BernardMatthey dans le forum VB 6 et antérieur
    Réponses: 9
    Dernier message: 26/11/2002, 22h06
  5. Réponses: 2
    Dernier message: 03/10/2002, 17h24

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