仅更改月份和年份的 DateTimePicker [英] A DateTimePicker to change only month and year

查看:61
本文介绍了仅更改月份和年份的 DateTimePicker的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

UI 应该保持不变,我不想这样做:

dateTimePicker1.Format = DateTimePickerFormat.Custom;dateTimePicker1.CustomFormat = "mm-yyyy";dateTimePicker1.ShowUpDown = true;

用户可以选择年份和月份,将 DateTimePicker 更改为 Month/Year 选择器,MonthCalendar 也是如此.
我不想使用第三方控件,但如果它是唯一的答案,我会使用任何免费的月/年选择器控件.

解决方案

这里有一个简单的 DateTimePicker 自定义控件,它预定义了自定义 DateTime 格式并修改了


使用 System.ComponentModel;使用 System.Runtime.InteropServices;使用 System.Windows.Forms;[设计师类别(代码")]类 DateTimePickerYearMonth : DateTimePicker{公共 DateTimePickerYearMonth() {this.CustomFormat = "MM-yyyy";this.Format = DateTimePickerFormat.Custom;this.Value = DateTime.Now;}[Browsable(true), EditorBrowsable(EditorBrowsableState.Always), DefaultValue(false),类别(外观"),说明(在日历控件底部显示或隐藏\"今天\日期")]public bool ShowToday {得到 =>m_ShowToday;放 {如果(值!= m_ShowToday){m_ShowToday = 值;ShowMonCalToday(m_ShowToday);}}}protected override void OnHandleCreated(EventArgs e){base.OnHandleCreated(e);ShowMonCalToday(m_ShowToday);}protected override void OnDropDown(EventArgs e){var hWnd = SendMessage(this.Handle, DTM_GETMONTHCAL, 0, 0);如果(hWnd != IntPtr.Zero){SendMessage(hWnd, MCM_SETCURRENTVIEW, 0, (int)MonCalView.MCMV_YEAR);}base.OnDropDown(e);}私人无效 ShowMonCalToday(bool show){int 样式 = SendMessage(this.Handle, DTM_GETMCSTYLE, 0, 0).ToInt32();样式 = 显示?样式 &~(int)MonCalStyles.MCS_NOTODAY :样式 |(int)MonCalStyles.MCS_NOTODAY;SendMessage(this.Handle, DTM_SETMCSTYLE, 0, 样式);}[DllImport(user32.dll")]static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);私有常量 int DTM_FIRST = 0x1000;private const int DTM_GETMONTHCAL = DTM_FIRST + 8;private const int DTM_SETMCSTYLE = DTM_FIRST + 11;private const int DTM_GETMCSTYLE = DTM_FIRST + 12;私有常量 int MCM_FIRST = 0x1000;private const int MCM_GETCURRENTVIEW = MCM_FIRST + 22;private const int MCM_SETCURRENTVIEW = MCM_FIRST + 32;private bool m_ShowToday = false;公共枚举 MonCalView : int{MCMV_MONTH = 0,MCMV_YEAR = 1,MCMV_DECADE = 2,MCMV_CENTURY = 3}公共枚举 MonCalStyles : int{MCS_DAYSTATE = 0x0001,MCS_MULTISELECT = 0x0002,MCS_WEEKNUMBERS = 0x0004,MCS_NOTODAYCIRCLE = 0x0008,MCS_NOTODAY = 0x0010,MCS_NOTRAILINGDATES = 0x0040,MCS_SHORTDAYSOFWEEK = 0x0080,MCS_NOSELCHANGEONNAV = 0x0100}}

UI should remain same I don't want to do this:

dateTimePicker1.Format = DateTimePickerFormat.Custom;
dateTimePicker1.CustomFormat = "mm-yyyy";
dateTimePicker1.ShowUpDown = true; 

A User can pick the year and month, change DateTimePicker to Month/Year picker, the MonthCalendar too.
I don't want to use a third-party control but I will if it will be the only answer point me to any free month/year picker control.

解决方案

Here's a simple DateTimePicker custom control that pre-defines a custom DateTime format and modified the MonthCalendar view, configuring it show just the Months and the Year when is opened.

I've added a public property, ShowToday, that allows to specify whether the MonthCalendar popup should show the Today date at the bottom of the Calendar interface.

The custom control overrides OnDropDown to get the Handle of the MonthCalendar popup, sending a DTM_GETMONTHCAL message and changes its current view sending a MCM_SETCURRENTVIEW, specifying MCMV_YEAR as the value parameter.

This is how it look like:


using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;

[DesignerCategory("Code")]
class DateTimePickerYearMonth : DateTimePicker
{
    public DateTimePickerYearMonth() {
        this.CustomFormat = "MM-yyyy";
        this.Format = DateTimePickerFormat.Custom;
        this.Value = DateTime.Now;
    }

    [
        Browsable(true), EditorBrowsable(EditorBrowsableState.Always), DefaultValue(false),
        Category("Appearance"), 
        Description("Shows or hides \"Today\" date at the bottom of the Calendar Control")
    ]
    public bool ShowToday {
        get => m_ShowToday;
        set {
            if (value != m_ShowToday) {
                m_ShowToday = value;
                ShowMonCalToday(m_ShowToday);
            }
        }
    }

    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        ShowMonCalToday(m_ShowToday);
    }

    protected override void OnDropDown(EventArgs e)
    {
        var hWnd = SendMessage(this.Handle, DTM_GETMONTHCAL, 0, 0);
        if (hWnd != IntPtr.Zero) {
            SendMessage(hWnd, MCM_SETCURRENTVIEW, 0, (int)MonCalView.MCMV_YEAR);
        }
        base.OnDropDown(e);
    }

    private void ShowMonCalToday(bool show)
    {
        int styles = SendMessage(this.Handle, DTM_GETMCSTYLE, 0, 0).ToInt32();
        styles = show ? styles &~(int)MonCalStyles.MCS_NOTODAY : styles | (int)MonCalStyles.MCS_NOTODAY;
        SendMessage(this.Handle, DTM_SETMCSTYLE, 0, styles);
    }
        
    [DllImport("user32.dll")]
    static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

    private const int DTM_FIRST = 0x1000;
    private const int DTM_GETMONTHCAL = DTM_FIRST + 8;
    private const int DTM_SETMCSTYLE = DTM_FIRST + 11;
    private const int DTM_GETMCSTYLE = DTM_FIRST + 12;
    private const int MCM_FIRST = 0x1000;
    private const int MCM_GETCURRENTVIEW = MCM_FIRST + 22;
    private const int MCM_SETCURRENTVIEW = MCM_FIRST + 32;
    private bool m_ShowToday = false;

    public enum MonCalView : int
    {
        MCMV_MONTH = 0,
        MCMV_YEAR = 1,
        MCMV_DECADE = 2,
        MCMV_CENTURY = 3
    }

    public enum MonCalStyles : int
    {
        MCS_DAYSTATE = 0x0001,
        MCS_MULTISELECT = 0x0002,
        MCS_WEEKNUMBERS = 0x0004,
        MCS_NOTODAYCIRCLE = 0x0008,
        MCS_NOTODAY = 0x0010,
        MCS_NOTRAILINGDATES = 0x0040,
        MCS_SHORTDAYSOFWEEK = 0x0080,
        MCS_NOSELCHANGEONNAV = 0x0100
    }
}

这篇关于仅更改月份和年份的 DateTimePicker的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆