2010-03-08 6 views
5

Momentan, wenn Sie den DateTimePicker verwenden, müssen Sie nach dem Monat entweder den rechten Pfeil oder das "/" drücken, um zum Tag zu gelangen. Gibt es eine Eigenschaft, die ich festlegen kann oder eine Möglichkeit zu wissen, dass der Monat fertig ist, und gehe zum Tag und bewege mich zu dem Jahr, nachdem der Benutzer mit dem Tag fertig ist? Dies ist das gleiche Verhalten bei Anwendungen, die in den alten FoxPro/Clipper-Tagen geschrieben wurden.DateTimePicker wechselt automatisch zum nächsten Datepart

Antwort

0

Es gibt keine Eigenschaft, damit es funktioniert, wie Sie wollen, ich denke, Sie müssen mit dem Tastenkürzel Ereignis und tun es durch Code.

7

Wie @Wael Dalloul sagt, gibt es keine Eigenschaft zu tun, was Sie wollen. Nach viel Fummelei und Spy ++ Arbeit, kam ich auf die folgende Lösung:

  1. von System.Windows.Forms.DateTimePicker Vererben und erklärt, private Felder für Fahnen:

    public class DPDateTimePicker : DateTimePicker 
    { 
        private bool selectionComplete = false; 
        private bool numberKeyPressed = false; 
    
  2. definieren Konstanten und Strukturen für 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; 
        }  
    

    Es ist auch notwendig, um eine Anweisung using für System.Runtime.InteropServices aufzunehmen, um Win-API zu verwenden.

  3. Überschreiben Sie OnKeyDown und setzen oder löschen Sie ein Flag basierend darauf, ob die gedrückte Taste eine Zahl war (und löschen Sie das zweite Flag unten).

    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. Aufschalten WndProc und trap die WM_REFLECT+WM_NOTIFY Nachricht, extrahieren die NMHDR von lParam, dann ein anderes Flag gesetzt, wenn der Code -759 (dieses Ereignis nach einem der Felder ausgelöst wird, vollständig mit der Tastatur ausgefüllt und ein Datum ist ausgewählt).

    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 chosen (by keyboard) 
          selectionComplete = true; 
        } 
        base.WndProc(ref m); 
    } 
    
  5. Aufschalten OnKeyUp und wenn beide Flags gesetzt sind und die gedrückte Taste war eine Zahl, rufen Sie manuell base.WndProc mit einem WM_KEYDOWN gefolgt von einem WM_KEYUP mit Keys.Right, dann Ihre Fahnen löschen. Sie können die lParam dieser Nachrichten auf 0 setzen und sich nicht darum kümmern, und HWnd ist natürlich 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); //right arrow key 
         m.Msg = WM_KEYDOWN; 
         base.WndProc(ref m); 
         m.Msg = WM_KEYUP; 
         base.WndProc(ref m); 
         numberKeyPressed = false; 
         selectionComplete = false; 
        } 
    } 
    

Apologies für das Fehlen von Leerzeilen im Code, aber es würde mit den Leerzeilen nicht richtig angezeigt werden, so dass sich mich nahm. Vertrau mir, das ist die besser lesbare Version.

1

Es wird auf WinForms arbeiten Datetime

auf Wertänderungsereignis

sendkeys.send("."); 
den folgenden Code einfügen