【发布时间】:2020-05-09 12:49:41
【问题描述】:
在 vb.net 或 c# 应用程序的 winforms 环境中使用传统的 DateTimePicker 控件,我需要将星期的显示方式从正常的星期日到星期六更改为星期二到星期一。我搜索了 Google 和 Stack 并没有发现任何内容。我对创建自定义控件没有任何问题。我只是不知道从哪里开始。
【问题讨论】:
标签: c# vb.net winforms datetimepicker
在 vb.net 或 c# 应用程序的 winforms 环境中使用传统的 DateTimePicker 控件,我需要将星期的显示方式从正常的星期日到星期六更改为星期二到星期一。我搜索了 Google 和 Stack 并没有发现任何内容。我对创建自定义控件没有任何问题。我只是不知道从哪里开始。
【问题讨论】:
标签: c# vb.net winforms datetimepicker
您可以使用SendMessage 向 DateTimePicker 的 MonthCalendar 发送 MCM_SETFIRSTDAYOFWEEK 消息(阅读文档中与此消息相关的注释)。
您首先发送DTM_GETMONTHCAL 消息以获取MonthCalendar 控件的句柄。如图所示,您可以在 DateTimePicker 的 DropDown 事件处理程序中发送此消息。
如果句柄有效,设置第一天发送MCM_SETFIRSTDAYOFWEEK。lParam 值确定 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
【讨论】:
SendMessage 的使用并不意味着表单激活。如果某些原因导致表单失去焦点并重新获取它,那不是这个函数调用,您还有其他原因导致它。 SendMessage 是激活 Win32 控件特定功能的标准方法,它在整个框架中不断使用,您根本无法看到它。