我有一个带有MonthCalendar
控件的 WinForm 应用程序。该MaxSelectionCount
属性设置为1
天。
我想改变某种行为。如果视图是这样的,控件显示 12 个月并且用户单击一个月,它将展开该月并且所选日期成为该月的最后一天。我想将其更改为该月的第一天。我怎样才能做到这一点?
另外,当我以这种方式扩展一个月时会引发什么事件?它有特定的事件吗?
谢谢。
我有一个带有MonthCalendar
控件的 WinForm 应用程序。该MaxSelectionCount
属性设置为1
天。
我想改变某种行为。如果视图是这样的,控件显示 12 个月并且用户单击一个月,它将展开该月并且所选日期成为该月的最后一天。我想将其更改为该月的第一天。我怎样才能做到这一点?
另外,当我以这种方式扩展一个月时会引发什么事件?它有特定的事件吗?
谢谢。
这在技术上是可行的,因为 Vista 的本机控件会在视图更改时发送通知 (MCM_VIEWCHANGE)。您可以捕获此通知并将其转换为事件。向您的项目添加一个新类并粘贴如下所示的代码。我预先准备了选择第一天的代码。编译。将新控件从工具箱顶部拖放到表单上。在 Windows 8 上测试,您需要检查它在 Vista 和 Win7 上是否正常工作。
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
class MonthCalendarEx : MonthCalendar {
public enum View { Month, Year, Decade, Century };
public class ViewEventArgs : EventArgs {
public ViewEventArgs(View newv, View oldv) { NewView = newv; OldView = oldv; }
public View NewView { get; private set; }
public View OldView { get; private set; }
}
public event EventHandler<ViewEventArgs> ViewChange;
protected virtual void OnViewChange(ViewEventArgs e) {
if (ViewChange == null) return;
// NOTE: I saw painting problems if this is done when MCM_VIEWCHANGE fires, delay it
this.BeginInvoke(new Action(() => {
// Select first day when switching to Month view:
if (e.NewView == View.Month) {
this.SetDate(this.GetDisplayRange(true).Start);
}
ViewChange(this, e);
}));
}
protected override void WndProc(ref Message m) {
if (m.Msg == 0x204e) { // Trap WMREFLECT + WM_NOTIFY
var hdr = (NMHDR)Marshal.PtrToStructure(m.LParam, typeof(NMHDR));
if (hdr.code == -750) { // Trap MCM_VIEWCHANGE
var vc = (NMVIEWCHANGE)Marshal.PtrToStructure(m.LParam, typeof(NMVIEWCHANGE));
OnViewChange(new ViewEventArgs(vc.dwNewView, vc.dwOldView));
}
}
base.WndProc(ref m);
}
private struct NMHDR {
public IntPtr hwndFrom;
public IntPtr idFrom;
public int code;
}
private struct NMVIEWCHANGE {
public NMHDR hdr;
public View dwOldView;
public View dwNewView;
}
}