Why you need to do this? If you want to display Months only then easier way is to have a list of months in Combox.
However I found something for you on msdn. Have a look here https://social.msdn.microsoft.com/Forums/en-US/7bdca56f-719e-44bf-be6d-a9600dfa8f78/wpf-datepicker-for-months-only?forum=wpf
Using the windows messages approach , you can detect month calendar control display and force month view and you can detect view changes and close the month calendar control on month to day views change (after a month selection).
The easiest way to implement it is to override DateTimePicker.
public class MonthPicker : DateTimePicker
{
// initialize Format/CustomFormat to display only month and year.
public MonthPicker()
{
Format = DateTimePickerFormat.Custom;
CustomFormat = "MMMM yyyy";
}
// override Format to redefine default value (used by designer)
[DefaultValue(DateTimePickerFormat.Custom)]
public new DateTimePickerFormat Format
{
get => base.Format;
set => base.Format = value;
}
// override CustomFormat to redefine default value (used by designer)
[DefaultValue("MMM yyyy")]
public new string CustomFormat
{
get => base.CustomFormat;
set => base.CustomFormat = value;
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_NOFITY)
{
var nmhdr = (NMHDR)Marshal.PtrToStructure(m.LParam, typeof(NMHDR));
switch (nmhdr.code)
{
// detect pop-up display and switch view to month selection
case -950:
{
var cal = SendMessage(Handle, DTM_GETMONTHCAL, IntPtr.Zero, IntPtr.Zero);
SendMessage(cal, MCM_SETCURRENTVIEW, IntPtr.Zero, (IntPtr)1);
break;
}
// detect month selection and close the pop-up
case MCN_VIEWCHANGE:
{
var nmviewchange = (NMVIEWCHANGE)Marshal.PtrToStructure(m.LParam, typeof(NMVIEWCHANGE));
if (nmviewchange.dwOldView == 1 && nmviewchange.dwNewView == 0)
{
SendMessage(Handle, DTM_CLOSEMONTHCAL, IntPtr.Zero, IntPtr.Zero);
}
break;
}
}
}
base.WndProc(ref m);
}
private const int WM_NOFITY = 0x004e;
private const int DTM_CLOSEMONTHCAL = 0x1000 + 13;
private const int DTM_GETMONTHCAL = 0x1000 + 8;
private const int MCM_SETCURRENTVIEW = 0x1000 + 32;
private const int MCN_VIEWCHANGE = -750;
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
[StructLayout(LayoutKind.Sequential)]
private struct NMHDR
{
public IntPtr hwndFrom;
public IntPtr idFrom;
public int code;
}
[StructLayout(LayoutKind.Sequential)]
struct NMVIEWCHANGE
{
public NMHDR nmhdr;
public uint dwOldView;
public uint dwNewView;
}
}
Try the following code:
DateTime newDateValue = new DateTime(dateTimePicker_month.Value.Year, 1, 1);
dateTimePicker_month.Value = newDateValue;
dateTimePicker_month.Format = DateTimePickerFormat.Custom;
dateTimePicker_month.CustomFormat = "MMM-yyyy";
dateTimePicker_month.ShowUpDown = true;
You have to add (1,1) for february month which having 28/29 days to ascertain the all the month values.If you want the query to select month.Following is an example:
string month = dateTimePicker_month.Value.Month.ToString();
string year = dateTimePicker_month.Value.Year.ToString();
use the following query to select month:
select CAST(date AS DATE) from table where DATEPART(month, date) = '" + month + "' and DATEPART(year,date) = '" + year + "'
Try using Format properties:
dateTimePicker.Format = DateTimePickerFormat.Custom;
dateTimePicker.CustomFormat = "MM";
As didn't work in my case I modified Orance's answer, putting this in a class inherited from DateTimePicker :
protected override void WndProc(ref Message m)
{
if (_MonthSelectStyle)
{
if (m.Msg == 0X204E) // = Win32Messages.WM_REFLECT_NOTIFY
{
var nmhdrI = (NMHDR)(Marshal.PtrToStructure(m.LParam, typeof(NMHDR)));
switch (nmhdrI.code)
{
case -754: // Win32Messages.DTN_DROPDOWN
var cal = SendMessage(m.HWnd, WinApi.Win32Messages.DTM_GETMONTHCAL, IntPtr.Zero, IntPtr.Zero);
SendMessage(cal, WinApi.Win32Messages.MCM_SETCURRENTVIEW, IntPtr.Zero, (IntPtr)1);
break;
case -759: // Win32Messages.DTN_DATETIMECHANGE
WinApi.SendMessage(Handle, WinApi.Win32Messages.DTM_CLOSEMONTHCAL, IntPtr.Zero, IntPtr.Zero);
break;
}
}
}
base.WndProc(ref m);
}
And the VB equivalent:
Protected Overrides Sub WndProc(ByRef m As Message)
If _MonthSelectStyle Then
If m.Msg = &H204E Then ' WM_REFLECT_NOTIFY '&H204E
Dim nmhdrI = CType(Marshal.PtrToStructure(m.LParam, GetType(NMHDR)), NMHDR)
Select Case nmhdrI.code
Case -754 ' Win32Messages.DTN_DROPDOWN '-754
Dim cal = SendMessage(m.HWnd, WinApi.Win32Messages.DTM_GETMONTHCAL, IntPtr.Zero, IntPtr.Zero)
SendMessage(cal, WinApi.Win32Messages.MCM_SETCURRENTVIEW, IntPtr.Zero, CType(1, IntPtr))
Case -759 ' Win32Messages.DTN_DATETIMECHANGE '-759
WinApi.SendMessage(Handle, WinApi.Win32Messages.DTM_CLOSEMONTHCAL, IntPtr.Zero, IntPtr.Zero)
End Select
End If
End If
MyBase.WndProc(m)
End Sub
The class "public class MonthPicker: DateTimePicker" inherits from DateTimePicker, It is not a custom user control.
That's why I can't see the MonthPicker in my control box. Am I missing something? How to add the MonthPicker.cs to my code, and use it as a custom control?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.