在 DateTimePicker 控件中更改周显示

Posted

技术标签:

【中文标题】在 DateTimePicker 控件中更改周显示【英文标题】:Change Week Display in DateTimePicker Control 【发布时间】:2020-05-09 12:49:41 【问题描述】:

在 vb.net 或 c# 应用程序的 winforms 环境中使用传统的 DateTimePicker 控件,我需要将星期的显示方式从正常的星期日到星期六更改为星期二到星期一。我搜索了 Google 和 Stack 并没有发现任何内容。我对创建自定义控件没有任何问题。我只是不知道从哪里开始。

【问题讨论】:

【参考方案1】:

您可以使用SendMessage 向 DateTimePicker 的 MonthCalendar 发送 MCM_SETFIRSTDAYOFWEEK 消息(阅读文档中与此消息相关的注释)。

您首先发送DTM_GETMONTHCAL 消息以获取MonthCalendar 控件的句柄。如图所示,您可以在 DateTimePicker 的 DropDown 事件处理程序中发送此消息。 如果句柄有效,设置第一天发送MCM_SETFIRSTDAYOFWEEKlParam 值确定 MonthCalendar 中显示的第一天:

0 = 星期一,1 = 星期二等。

如果你想构建一个自定义控件(IMO,最好),你可以在这里找到一个预构建的:How can I set the DateTimePicker dropdown to select Years or Months only?

它展示了如何处理 DateTimePicker 及其 MonthCalendar 下拉列表,以更改当前视图和类似任务。

internal const int DTM_FIRST = 0x1000;
internal const int DTM_GETMONTHCAL = DTM_FIRST + 8;
internal const int MCM_FIRST = 0x1000;
internal const int MCM_SETFIRSTDAYOFWEEK = MCM_FIRST + 15;

internal enum MCWeekDay : int 

    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday


[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

internal void MonthCalendarSetFirstDayOfWeek(IntPtr dtpHandle, MCWeekDay weekDay)

    IntPtr hWndCal = SendMessage(dtpHandle, DTM_GETMONTHCAL, 0, 0);
    if (hWndCal != IntPtr.Zero) 
        SendMessage(hWndCal, MCM_SETFIRSTDAYOFWEEK, 0, (int)weekDay);
    


private void dateTimePicker1_DropDown(object sender, EventArgs e)

    MonthCalendarSetFirstDayOfWeek((sender as Control).Handle, MCWeekDay.Tuesday);


VB.Net 版本

Imports System.Runtime.InteropServices

Friend Const DTM_FIRST As Integer = &H1000
Friend Const DTM_GETMONTHCAL As Integer = DTM_FIRST + 8
Friend Const MCM_FIRST As Integer = &H1000
Friend Const MCM_SETFIRSTDAYOFWEEK As Integer = MCM_FIRST + 15

Friend Enum MCWeekDay As Integer
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday
    Sunday
End Enum

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Friend Shared Function SendMessage(hWnd As IntPtr, Msg As Integer, wParam As Integer, lParam As Integer) As IntPtr
End Function

Friend Sub MonthCalendarSetFirstDayOfWeek(dtpHandle As IntPtr, weekDay As MCWeekDay)
    Dim hWndCal As IntPtr = SendMessage(dtpHandle, DTM_GETMONTHCAL, 0, 0)
    If hWndCal <> IntPtr.Zero Then
        SendMessage(hWndCal, MCM_SETFIRSTDAYOFWEEK, 0, weekDay)
    End If
End Sub

Private Sub DateTimePicker1_DropDown(sender As Object, e As EventArgs) Handles DateTimePicker1.DropDown
    MonthCalendarSetFirstDayOfWeek(DirectCast(sender, Control).Handle, MCWeekDay.Tuesday)
End Sub

【讨论】:

我注意到的一件事是,如果您使用 Form_Activated 事件,任何日历更改都会触发它。这对我来说没什么大不了的,但在我试图理解 Jimi 的回答的过程中,我注意到了这一点。再次出色的工作。 SendMessage 的使用并不意味着表单激活。如果某些原因导致表单失去焦点并重新获取它,那不是这个函数调用,您还有其他原因导致它。 SendMessage 是激活 Win32 控件特定功能的标准方法,它在整个框架中不断使用,您根本无法看到它

以上是关于在 DateTimePicker 控件中更改周显示的主要内容,如果未能解决你的问题,请参考以下文章

如何在php中按周显示网格中的天数?

如何对数据进行分组以从选择查询中按周显示平均价格

查找页面中的所有 datetimepicker 控件

按周显示的滚动尾随 30 天窗口中的唯一客户总数

在点击文本字段时显示日期选择器

DateTimePicker在toolStrip控件中添加