You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 15:42:46