C# 如何将DateTimePicker下拉列表设置为仅选择年或月?
如中所述,有可能覆盖C# 如何将DateTimePicker下拉列表设置为仅选择年或月?,c#,winforms,datetimepicker,C#,Winforms,Datetimepicker,如中所述,有可能覆盖DateTimePicker以获得MonthPicker 我读过很多网站,但没有想到如何做类似的事情来获得一个年鉴 也许有人能帮上忙。这个自定义控件稍微调整了标准的日期时间选择器,使其只能选择年份或月份 ► 标准DateTimePicker的CustomFormat和Format属性被禁用,在内部将前者设置为yyyy或MMMM(简单的修改可以添加不同的格式),后者设置为DateTimePickPerformat.Custom。这些属性对PropertyGrid隐藏,无法更改
DateTimePicker
以获得MonthPicker
我读过很多网站,但没有想到如何做类似的事情来获得一个年鉴
也许有人能帮上忙。这个自定义控件稍微调整了标准的日期时间选择器,使其只能选择年份或月份 ► 标准DateTimePicker的
CustomFormat
和Format
属性被禁用,在内部将前者设置为yyyy
或MMMM
(简单的修改可以添加不同的格式),后者设置为DateTimePickPerformat.Custom
。这些属性对PropertyGrid隐藏,无法更改
► 浏览功能将得到维护,但仅限于十年/年或十年/年/月选择。单击DTP的标题区域,将显示“十年选择器”,当然,“上一个”和“下一个”按钮可以正常工作(这些按钮只能显示年份) ► 当通知通过结构中的当前选择级别显示当前选择已达到由
SelectionMode
属性设置的查看模式时,DTP将关闭并设置当前值。此属性值是一个枚举数,它反过来反映MonthCalendar的消息值 ► 当前视图设置为每次显示MonthCalendar控件时,向MonthCalendar控件发送一条
MCM\u SETCURRENTVIEW
消息,将默认视图更改为MCMV\u Deced
或MCMV\u YEAR
(取决于当前的选择模式
)。然后将保留打开的动画
► 唯一更改的样式是,在OnHandleCreated
方法中设置。它可以随时打开/关闭,调用ShowMonCalToday()
方法。此样式在DateTimerPicker的底部显示今天的日期。它设置单击时的当前年份或月份值
这就是它的工作原理: 在VisualStudio 2017上测试。
.Net Framework 4.8(仅限)
使用System.ComponentModel;
使用System.Runtime.InteropServices;
使用System.Windows.Forms;
[设计分类(“代码”)]
公共类MonthYearPicker:DateTimePicker
{
私有字符串m_CustomFormat=“yyyy”;
私有DateTimePickPerformat m_格式=DateTimePickPerformat.Custom;
private SelectionViewMode m_SelectionMode=SelectionViewMode.Year;
private bool m_ShowToday=假;
私有IntPtr hWndCal=IntPtr.Zero;
公共蒙蒂耳机(){
base.CustomFormat=m_CustomFormat;
base.Format=m_格式;
}
[默认值(选择ViewMode.Year)]
[可浏览(true)、可编辑可浏览(editorbrowsebleState.Always)]
[类别(“外观”)、说明(“将当前选择模式设置为月份或年份”)]
公共选择查看模式选择模式{
get=>m_选择模式;
设置{
如果(值!=m_选择模式){
m_SelectionMode=值;
m_CustomFormat=m_SelectionMode==SelectionViewMode.Year?“yyyy”:“MMMM”;
base.CustomFormat=m_CustomFormat;
}
}
}
[默认值(false)]
[可浏览(true)、可编辑可浏览(editorbrowsebleState.Always)]
[类别(“外观”)、说明(“在日历控件底部显示或隐藏\“今天\”日期”)]
今天的公众集会{
get=>m_ShowToday;
设置{
如果(值!=m_ShowToday){
m_showtody=价值;
ShowMonCalToday(m_ShowToday);
}
}
}
[默认值(“yyyy”)]
[可浏览(false)、可编辑可浏览(editorbrowseblestate.Never)]
公共新字符串格式{
get=>base.CustomFormat;
set=>base.CustomFormat=m_CustomFormat;
}
[默认值(DateTimePickPerformat.Custom)]
[可浏览(false)、可编辑可浏览(editorbrowseblestate.Never)]
公共新DateTimePickPerformat格式{
get=>base.Format;
set=>base.Format=m_格式;
}
已创建受保护的重写无效OnHandleCreated(EventArgs e)
{
碱基。根据HandleCreated(e);
ShowMonCalToday(m_ShowToday);
}
受保护的覆盖无效OnDropDown(事件参数e)
{
hWndCal=SendMessage(this.Handle,DTM_GETMONTHCAL,0,0);
如果(hWndCal!=IntPtr.Zero){
发送消息(hWndCal,MCM_设置当前视图,0,(int)(MonCalStyles)m_选择模式);
}
基础.降速(e);
}
今天的私人void show(bool show)
{
int styles=SendMessage(this.Handle,DTM_GETMCSTYLE,0,0).ToInt32();
styles=show?styles&~(int)MonCalStyles.MCS_notaday:styles |(int)MonCalStyles.MCS_notaday;
SendMessage(this.Handle,DTM_SETMCSTYLE,0,style);
}
受保护的覆盖无效WndProc(参考消息m)
{
开关(m.Msg){
案件通知:
var nmh=(NMHDR)m.GetLParam(typeof(NMHDR));
交换机(nmh.代码){
案例MCN_视图更改:
var nmView=(NMVIEWCHANGE)m.GetLParam(typeof(NMVIEWCHANGE));
如果(nmView.dwNewView<(MonCalView)m_选择模式){
SendMessage(this.Handle,DTM_CLOSEMONTHCAL,0,0);
}
打破
违约:
//否:添加更多通知处理程序。。。
打破
}
打破
违约:
//否:添加更多消息处理程序。。。
打破
}
基准WndProc(参考m);
}
公共枚举选择视图模式:int
{
月=MonCalView.MCMV炭年,
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;
[DesignerCategory("Code")]
public class MonthYearPicker : DateTimePicker
{
private string m_CustomFormat = "yyyy";
private DateTimePickerFormat m_Format = DateTimePickerFormat.Custom;
private SelectionViewMode m_SelectionMode = SelectionViewMode.Year;
private bool m_ShowToday = false;
private IntPtr hWndCal = IntPtr.Zero;
public MonthYearPicker() {
base.CustomFormat = m_CustomFormat;
base.Format = m_Format;
}
[DefaultValue(SelectionViewMode.Year)]
[Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
[Category("Appearance"), Description("Set the current selection mode to either Month or Year")]
public SelectionViewMode SelectionMode {
get => m_SelectionMode;
set {
if (value != m_SelectionMode) {
m_SelectionMode = value;
m_CustomFormat = m_SelectionMode == SelectionViewMode.Year ? "yyyy" : "MMMM";
base.CustomFormat = m_CustomFormat;
}
}
}
[DefaultValue(false)]
[Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
[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);
}
}
}
[DefaultValue("yyyy")]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public new string CustomFormat {
get => base.CustomFormat;
set => base.CustomFormat = m_CustomFormat;
}
[DefaultValue(DateTimePickerFormat.Custom)]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public new DateTimePickerFormat Format {
get => base.Format;
set => base.Format = m_Format;
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
ShowMonCalToday(m_ShowToday);
}
protected override void OnDropDown(EventArgs e)
{
hWndCal = SendMessage(this.Handle, DTM_GETMONTHCAL, 0, 0);
if (hWndCal != IntPtr.Zero) {
SendMessage(hWndCal, MCM_SETCURRENTVIEW, 0, (int)(MonCalStyles)m_SelectionMode);
}
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);
}
protected override void WndProc(ref Message m)
{
switch (m.Msg) {
case WM_NOTIFY:
var nmh = (NMHDR)m.GetLParam(typeof(NMHDR));
switch (nmh.code) {
case MCN_VIEWCHANGE:
var nmView = (NMVIEWCHANGE)m.GetLParam(typeof(NMVIEWCHANGE));
if (nmView.dwNewView < (MonCalView)m_SelectionMode) {
SendMessage(this.Handle, DTM_CLOSEMONTHCAL, 0, 0);
}
break;
default:
// NOP: Add more notifications handlers...
break;
}
break;
default:
// NOP: Add more message handlers...
break;
}
base.WndProc(ref m);
}
public enum SelectionViewMode : int
{
Month = MonCalView.MCMV_YEAR,
Year = MonCalView.MCMV_DECADE,
}
// Move to a NativeMethods class, eventually
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
internal const int WM_NOTIFY = 0x004E;
internal const int MCN_VIEWCHANGE = -750;
internal const int DTM_FIRST = 0x1000;
internal const int DTM_GETMONTHCAL = DTM_FIRST + 8;
internal const int DTM_SETMCSTYLE = DTM_FIRST + 11;
internal const int DTM_GETMCSTYLE = DTM_FIRST + 12;
internal const int DTM_CLOSEMONTHCAL = DTM_FIRST + 13;
internal const int MCM_FIRST = 0x1000;
internal const int MCM_GETCURRENTVIEW = MCM_FIRST + 22;
internal const int MCM_SETCURRENTVIEW = MCM_FIRST + 32;
[StructLayout(LayoutKind.Sequential)]
internal struct NMHDR
{
public IntPtr hwndFrom;
public UIntPtr idFrom;
public int code;
}
[StructLayout(LayoutKind.Sequential)]
internal struct NMVIEWCHANGE
{
public NMHDR nmhdr;
public MonCalView dwOldView;
public MonCalView dwNewView;
}
internal enum MonCalView : int
{
MCMV_MONTH = 0,
MCMV_YEAR = 1,
MCMV_DECADE = 2,
MCMV_CENTURY = 3
}
internal 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
}
}