DateTimePicker 自动移动到下一个日期部分

发布于 2024-08-24 15:20:33 字数 130 浏览 8 评论 0原文

目前,在使用日期时间选择器时,输入月份后,您必须点击向右箭头或“/”才能将其移至日期。是否有一个我可以设置的属性或一种方法可以知道该月已完成并在用户完成该天后移至该日并移至该年?这与旧 FoxPro/Clipper 时代编写的应用程序的行为相同。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

似梦非梦 2024-08-31 15:20:33

正如@Wael Dalloul 所说,没有财产可以做你想做的事。经过大量的摆弄和 Spy++ 工作后,我找到了以下解决方案:

  1. 继承System.Windows.Forms.DateTimePicker,并声明标志的私有字段:

    公共类 DPDateTimePicker : DateTimePicker
    {
        私人布尔选择完成 = false;
        私有 bool numberKeyPressed = false;
    
  2. 为 Win API 定义常量和结构:

     private const int WM_KEYUP = 0x0101;
        私有常量 int WM_KEYDOWN = 0x0100;
        私有常量 int WM_REFLECT = 0x2000;
        私有常量 int WM_NOTIFY = 0x004e;
    
        [StructLayout(LayoutKind.Sequential)]
        私有结构 NMHDR
        {
           公共 IntPtr hwndFrom;
           公共 IntPtr idFrom;
           公共 int 代码;
        }    
    

    为了使用 Win API,还需要包含 System.Runtime.InteropServices 的 using 语句。

  3. 重写OnKeyDown并根据按下的键是否为数字来设置或清除标志(并清除下面的第二个标志)。

    受保护的覆盖 void OnKeyDown(KeyEventArgs e)
    {
        numberKeyPressed = (e.Modifiers == Keys.None && ((e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9) || (e.KeyCode != Keys.返回 && e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9)));
        选择完成= false;
        Base.OnKeyDown(e);
    }
    
  4. 重写WndProc并捕获WM_REFLECT+WM_NOTIFY消息,从lParam中提取NMHDR,然后设置另一个如果代码为-759,则标记(在用键盘完全填写其中一个字段并选择日期后触发此事件)。

    受保护的覆盖 void WndProc(ref Message m)
    {
        if (m.Msg == WM_REFLECT + WM_NOTIFY)
        {
            var hdr = (NMHDR)m.GetLParam(typeof(NMHDR));
            if (hdr.Code == -759) //选择的日期(通过键盘)
                选择完成=真;
        }
        base.WndProc(ref m);
    }
    
  5. 重写OnKeyUp,如果两个标志都已设置并且按下的键是数字,则使用WM_KEYDOWN手动调用base.WndProc,然后是一个带有 Keys.RightWM_KEYUP,然后清除您的标志。你可以将这些消息的lParam设置为0而不用管它,而HWnd当然是this.Handle

    受保护的覆盖 void OnKeyUp(KeyEventArgs e)
    {
        基.OnKeyUp(e);
        if (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))))
        {
            消息 m = new Message();
            m.HWnd = this.Handle;
            m.LParam = IntPtr.Zero;
            m.WParam = new IntPtr((int)Keys.Right); //右方向键
            m.Msg = WM_KEYDOWN;
            base.WndProc(ref m);
            m.Msg = WM_KEYUP;
            base.WndProc(ref m);
            数字按键按下 = false;
            选择完成= false;
        }
    }
    

对于代码中缺少空白行表示歉意,但它不会与空白行一起正确显示,所以我将它们删除了。相信我,这是更具可读性的版本。

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.

装迷糊 2024-08-31 15:20:33

它将在 winforms datetimepicker 上的

值更改事件上工作,粘贴以下代码

sendkeys.send(".");

It will work on winforms datetimepicker

on value change event paste the below code

sendkeys.send(".");
被翻牌 2024-08-31 15:20:33

没有属性使它像你想要的那样工作,我认为你必须处理按键事件并通过代码来完成。

There is no Property to make it work like what you want, I think you have to handle keypress event and do it by code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文