如何修改WinForms中DateTimePicker控件的周显示范围为周二至周一?
嗨,这个需求我之前刚好做过,原生WinForms的DateTimePicker确实没直接提供修改周起始日的属性,但通过自定义控件拦截Windows消息就能搞定,其实没你想的那么复杂,我给你一步步拆解:
实现思路
核心是利用Windows API消息,给DateTimePicker弹出的日历控件发送MCM_SETFIRSTDAYOFWEEK指令,强制把一周的起始天设为周二,这样日历就会自动显示周二到周一的周范围了。
具体实现步骤
1. 创建自定义DateTimePicker控件
不管用C#还是VB.NET,都要继承原生的DateTimePicker,然后重写WndProc方法来拦截系统消息。
C# 代码示例
using System; using System.Windows.Forms; using System.Runtime.InteropServices; public class CustomDateTimePicker : DateTimePicker { // Windows API常量 private const int WM_PARENTNOTIFY = 0x0210; private const int WM_CREATE = 0x0001; private const int MCM_SETFIRSTDAYOFWEEK = 0x1008; [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); protected override void WndProc(ref Message m) { base.WndProc(ref m); // 监听日历控件创建的消息 if (m.Msg == WM_PARENTNOTIFY && m.WParam.ToInt32() == WM_CREATE) { // 获取日历控件的句柄 IntPtr calendarHandle = m.LParam; // 设置一周的第一天为周二(0=周日,1=周一,2=周二...) SendMessage(calendarHandle, MCM_SETFIRSTDAYOFWEEK, IntPtr.Zero, (IntPtr)2); } } }
VB.NET 代码示例
Imports System.Windows.Forms Imports System.Runtime.InteropServices Public Class CustomDateTimePicker Inherits DateTimePicker ' Windows API常量 Private Const WM_PARENTNOTIFY As Integer = &H210 Private Const WM_CREATE As Integer = &H1 Private Const MCM_SETFIRSTDAYOFWEEK As Integer = &H1008 <DllImport("user32.dll", CharSet:=CharSet.Auto)> Private Shared Function SendMessage(hWnd As IntPtr, msg As Integer, wParam As IntPtr, lParam As IntPtr) As IntPtr End Function Protected Overrides Sub WndProc(ByRef m As Message) MyBase.WndProc(m) ' 监听日历控件创建的消息 If m.Msg = WM_PARENTNOTIFY AndAlso m.WParam.ToInt32() = WM_CREATE Then ' 获取日历控件的句柄 Dim calendarHandle As IntPtr = m.LParam ' 设置一周的第一天为周二(0=周日,1=周一,2=周二...) SendMessage(calendarHandle, MCM_SETFIRSTDAYOFWEEK, IntPtr.Zero, CType(2, IntPtr)) End If End Sub End Class
2. 使用自定义控件
把这个自定义控件编译后,会自动出现在WinForms工具箱里,直接拖到窗体上用就行,和原生DateTimePicker的用法完全一样,只是弹出的日历会显示周二到周一的周范围了。
关键说明
- 为什么用
WM_PARENTNOTIFY?因为DateTimePicker弹出的日历是它的子窗口,当子窗口创建时,系统会给父窗口(也就是DateTimePicker)发送这个消息,我们就能在这个时机拿到日历控件的句柄。 MCM_SETFIRSTDAYOFWEEK是日历控件的专属消息,用来设置一周的起始天,参数2对应周二,你如果要改其他起始日,直接调整这个数字就行(0=周日,1=周一,...6=周六)。
这样实现的好处是完全基于原生控件扩展,没有额外的第三方依赖,性能也和原生控件一致。
内容的提问来源于stack exchange,提问作者KJM
相关产品推荐
相关产品推荐

