7 votes

DateTimePicker se déplace automatiquement vers la prochaine partie de la date

Actuellement, lors de l'utilisation du datetimepicker, après avoir saisi le mois, vous devez soit appuyer sur la flèche droite, soit sur "/" pour passer au jour. Existe-t-il une propriété que je peux définir ou une façon de savoir que le mois est terminé et de passer au jour, puis de passer à l'année après que l'utilisateur a terminé avec le jour? C'est le même comportement avec les applications écrites à l'époque de FoxPro/Clipper.

11voto

lc. Points 50297

Comme le dit @Wael Dalloul, il n'y a pas de propriété pour faire ce que vous voulez. Après beaucoup de bricolage et de travail avec Spy ++, je suis arrivé à la solution suivante :

  1. Héritage de System.Windows.Forms.DateTimePicker, et déclaration de champs privés pour les drapeaux :

    public class DPDateTimePicker : DateTimePicker
    {
        private bool selectionComplete = false;
        private bool numberKeyPressed = false;
  2. Définition de constantes et de structures pour Win API :

        private const int WM_KEYUP = 0x0101;
        private const int WM_KEYDOWN = 0x0100;
        private const int WM_REFLECT = 0x2000;
        private const int WM_NOTIFY = 0x004e;
    
        [StructLayout(LayoutKind.Sequential)]
        private struct NMHDR
        {
           public IntPtr hwndFrom;
           public IntPtr idFrom;
           public int Code;
        }    

    Il est également nécessaire d'inclure une instruction using pour System.Runtime.InteropServices afin d'utiliser Win API.

  3. Remplacer OnKeyDown et définir ou effacer un drapeau en fonction de la touche pressée (et effacer le deuxième drapeau ci-dessous).

    protected override void OnKeyDown(KeyEventArgs e)
    {
        numberKeyPressed = (e.Modifiers == Keys.None && ((e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9) || (e.KeyCode != Keys.Back && e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9)));
        selectionComplete = false;
        base.OnKeyDown(e);
    }
  4. Remplacer WndProc et piéger le message WM_REFLECT+WM_NOTIFY, extraire le NMHDR de lParam, puis définir un autre drapeau si le code est -759 (cet événement est déclenché après qu'un des champs est entièrement rempli avec le clavier et une date est sélectionnée).

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_REFLECT + WM_NOTIFY)
        {
            var hdr = (NMHDR)m.GetLParam(typeof(NMHDR));
            if (hdr.Code == -759) //date choisie (par clavier)
                selectionComplete = true;
        }
        base.WndProc(ref m);
    }
  5. Remplacer OnKeyUp et si les deux drapeaux sont définis et que la touche pressée était un nombre, appeler manuellement base.WndProc avec un WM_KEYDOWN suivi d'un WM_KEYUP avec Keys.Right, puis effacer vos drapeaux. Vous pouvez définir le lParam de ces messages à 0 et ne pas vous en préoccuper, et HWnd est bien sûr this.Handle.

    protected override void OnKeyUp(KeyEventArgs e)
    {
        base.OnKeyUp(e);
        if (numberKeyPressed && selectionComplete &&
            (e.Modifiers == Keys.None && ((e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9) || (e.KeyCode != Keys.Back && e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9))))
        {
            Message m = new Message();
            m.HWnd = this.Handle;
            m.LParam = IntPtr.Zero;
            m.WParam = new IntPtr((int)Keys.Right); //touche de la flèche droite
            m.Msg = WM_KEYDOWN;
            base.WndProc(ref m);
            m.Msg = WM_KEYUP;
            base.WndProc(ref m);
            numberKeyPressed = false;
            selectionComplete = false;
        }
    }

Désolé pour le manque de lignes vides dans le code, mais cela n'affichait pas correctement avec les lignes vides, donc je les ai supprimées. Faites-moi confiance, c'est la version la plus lisible.

3voto

Taja_100 Points 21

Cela fonctionnera sur le datetimepicker de WinForms

Sur l'événement de changement de valeur, collez le code ci-dessous

sendkeys.send(".");

0voto

Wael Dalloul Points 7995

Il n'y a pas de propriété pour le faire fonctionner comme vous le souhaitez, je pense que vous devez gérer l'événement keypress et le faire par code.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X