Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
381 views
in Technique[技术] by (71.8m points)

.net - DateTimePicker automatically move to next datepart

Currently, when using the datetimepicker, after you enter the month you have to either hit the right arrow or the "/" for it to move to the day. Is there a property that I can set or a way to know that the month is done and move to the day and move to the year after the user is done with the day? This is the same behavior with applications written in the old FoxPro/Clipper days.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As @Wael Dalloul says, there is no property to do what you want. After a lot of fiddling and Spy++ work, I came upon the following solution:

  1. Inheriting from System.Windows.Forms.DateTimePicker, and declaring private fields for flags:

    public class DPDateTimePicker : DateTimePicker
    {
        private bool selectionComplete = false;
        private bool numberKeyPressed = false;
    
  2. Defining constants and structs for 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;
        }    
    

    It's also necessary to include a using statement for System.Runtime.InteropServices in order to use Win API.

  3. Override OnKeyDown and set or clear a flag based on if the key pressed was a number (and clear the second flag below).

    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. Override WndProc and trap the WM_REFLECT+WM_NOTIFY message, extract the NMHDR from lParam, then set another flag if the code is -759 (this event is triggered after one of the fields is completely filled in with the keyboard and a date is selected).

    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. Override OnKeyUp and if both flags are set and the key pressed was a number, manually call base.WndProc with a WM_KEYDOWN followed by a WM_KEYUP with Keys.Right, then clear your flags. You can set the lParam of these messages to 0 and not worry about it, and HWnd is of course 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 for the lack of blank lines in the code, but it wouldn't display right with the blank lines, so I took them out. Trust me, this is the more readable version.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...