How can I set the datetimepicker dropdown to show Months only

前端 未结 5 977
夕颜
夕颜 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;
        }
    }
    

提交回复
热议问题