How can I set the datetimepicker dropdown to show Months only

前端 未结 5 892
夕颜
夕颜 2020-12-17 16:45

So instead of this showing up on clicking the dropdown menu.

I want the dropdown to be like this when clicked.

Thanks a lot for any help.

相关标签:
5条回答
  • 2020-12-17 16:52

    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;
        }
    }
    
    0 讨论(0)
  • 2020-12-17 17:04

    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 + "' 
    
    0 讨论(0)
  • 2020-12-17 17:10

    Try using Format properties:

     dateTimePicker.Format = DateTimePickerFormat.Custom;
     dateTimePicker.CustomFormat = "MM";
    
    0 讨论(0)
  • 2020-12-17 17:13

    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
    
    0 讨论(0)
  • 2020-12-17 17:15

    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

    0 讨论(0)
提交回复
热议问题