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.
Réponses
Trop de publicités?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 :
-
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;
-
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. -
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); }
-
Remplacer
WndProc
et piéger le messageWM_REFLECT+WM_NOTIFY
, extraire leNMHDR
delParam
, 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); }
-
Remplacer
OnKeyUp
et si les deux drapeaux sont définis et que la touche pressée était un nombre, appeler manuellementbase.WndProc
avec unWM_KEYDOWN
suivi d'unWM_KEYUP
avecKeys.Right
, puis effacer vos drapeaux. Vous pouvez définir lelParam
de ces messages à 0 et ne pas vous en préoccuper, etHWnd
est bien sûrthis.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.