DateTimePicker автоматически переходит к следующей части даты
В настоящее время при использовании средства выбора даты и времени после ввода месяца вам нужно либо нажать стрелку вправо, либо клавишу "/", чтобы перейти к дню. Есть ли свойство, которое я могу установить, или способ узнать, что месяц закончен, и перейти к дню и перейти к году после того, как пользователь завершил день? Это то же самое поведение с приложениями, написанными в старые времена FoxPro/Clipper.
3 ответа
Как говорит @Wael Dalloul, нет собственности, чтобы делать то, что вы хотите. После долгой работы с Spy++ я нашел следующее решение:
Наследование от
System.Windows.Forms.DateTimePicker
и объявление частных полей для флагов:public class DPDateTimePicker : DateTimePicker { private bool selectionComplete = false; private bool numberKeyPressed = false;
Определение констант и структур для 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; }
Также необходимо включить оператор использования для
System.Runtime.InteropServices
для того, чтобы использовать Win API.Override
OnKeyDown
и установите или очистите флаг, основываясь на том, была ли нажатая клавиша цифрой (и сбросьте второй флаг ниже).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
и пойматьWM_REFLECT+WM_NOTIFY
сообщение, извлекитеNMHDR
отlParam
, затем установите другой флаг, если код -759 (это событие срабатывает после того, как одно из полей полностью заполнено клавиатурой и выбрана дата).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
и если оба флага установлены, и нажатая клавиша была числом, вызовите вручнуюbase.WndProc
сWM_KEYDOWN
с последующимWM_KEYUP
сKeys.Right
, а затем очистите свои флаги. Вы можете установитьlParam
из этих сообщений до 0 и не переживай, аHWnd
конечно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; } }
Извините за отсутствие пустых строк в коде, но он не будет отображаться правильно с пустыми строками, поэтому я их убрал. Поверьте мне, это более читаемая версия.
Это будет работать на winforms datetimepicker
при изменении значения вставьте следующий код
sendkeys.send(".");
Нет свойства, чтобы заставить его работать так, как вы хотите, я думаю, вы должны обработать событие нажатия клавиши и сделать это с помощью кода.