仅更改月份和年份的 DateTimePicker
A DateTimePicker to change only month and year
UI 应该保持不变我不想这样做:
dateTimePicker1.Format = DateTimePickerFormat.Custom;
dateTimePicker1.CustomFormat = "mm-yyyy";
dateTimePicker1.ShowUpDown = true;
用户可以选择年份和月份,将 DateTimePicker 更改为 Month/Year 选择器,MonthCalendar 也可以。
我不想使用第三方控件,但如果它是我指向任何免费 month/year 选择器控件的唯一答案,我会的。
自定义格式用于确定在 system/database 中捕获日期的方式,无论用户选择什么,它不用于限制用户选择月份或年份。
这是一个简单的 DateTimePicker 自定义控件,它预定义了自定义 DateTime 格式并修改了 MonthCalendar 视图,配置 它只显示月份和年份打开。
我添加了 public 属性、ShowToday
,允许指定 MonthCalendar 弹出窗口是否应显示 Today
日历界面底部的日期。
自定义控件覆盖 OnDropDown to get the Handle of the MonthCalendar popup, sending a DTM_GETMONTHCAL
message and changes its current view sending a MCM_SETCURRENTVIEW
,指定 MCMV_YEAR
作为值参数。
这是它的样子:
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
}
}
UI 应该保持不变我不想这样做:
dateTimePicker1.Format = DateTimePickerFormat.Custom;
dateTimePicker1.CustomFormat = "mm-yyyy";
dateTimePicker1.ShowUpDown = true;
用户可以选择年份和月份,将 DateTimePicker 更改为 Month/Year 选择器,MonthCalendar 也可以。
我不想使用第三方控件,但如果它是我指向任何免费 month/year 选择器控件的唯一答案,我会的。
自定义格式用于确定在 system/database 中捕获日期的方式,无论用户选择什么,它不用于限制用户选择月份或年份。
这是一个简单的 DateTimePicker 自定义控件,它预定义了自定义 DateTime 格式并修改了 MonthCalendar 视图,配置 它只显示月份和年份打开。
我添加了 public 属性、ShowToday
,允许指定 MonthCalendar 弹出窗口是否应显示 Today
日历界面底部的日期。
自定义控件覆盖 OnDropDown to get the Handle of the MonthCalendar popup, sending a DTM_GETMONTHCAL
message and changes its current view sending a MCM_SETCURRENTVIEW
,指定 MCMV_YEAR
作为值参数。
这是它的样子:
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
}
}