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:
Inheriting from System.Windows.Forms.DateTimePicker
, and declaring private fields for flags:
public class DPDateTimePicker : DateTimePicker
{
private bool selectionComplete = false;
private bool numberKeyPressed = false;
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.
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);
}
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);
}
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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…