覆盖DateTimePicker时设置日历大小以添加周数

我正在尝试创建一个显示周数的DateTimePicker , 如下所示(代码项目示例) 。

除了一个小细节之外,它运作得相当好; 尝试选择日期时弹出的日历不是正确的大小。 如您所见,日历区域有点“狭窄”,特别是沿着右边缘。

在此处输入图像描述

我可以在这里单击右下角,然后将其拖出一点 – 只需将其展开以使其看起来正确:

在此处输入图像描述

我似乎无法找到任何方法强制日历从一开始就是正确/完整的大小,或调整它的大小。 任何想法将不胜感激。

终于找到了似乎有效的解决方案 – 至少目前是这样。

似乎DateTimePicker的日历部分中有两个窗口。 显然我的代码会自动找到内部的(或多或少至少?)正确的大小,而不是外部的大小。

一些研究导致了下面的代码。 以下链接提供了一些有用且相关的信息:

  • GetWindowLong函数 (用于获取有关要编辑的窗口的信息)
  • GetParent函数 (查找外部窗口,因此我们也可以应用设置)

诀窍是在(内部)窗口的高度和宽度上添加一点,然后将相同的高度和宽度应用于外部窗口(我使用GetParrent()函数访问)。 我通过反复试验找到了“正确”的大小:当大小与日历内容所需的大小相匹配时,它无法再resize。

是的,这感觉有点像黑客,不,我还没有能够validation它在其他计算机上的运行情况还不如我自己。 我有点担心必须给出高度和宽度的具体值,但我希望这不会受到屏幕分辨率或其他任何因素的影响。

希望处于类似情况的其他人会发现代码有用。
以下内容可直接替换常规DateTimePicker以显示日历中的周数

 using System; using System.ComponentModel; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; public class DatePickerWithWeekNumbers : DateTimePicker { [DllImport("User32.dll")] private static extern int GetWindowLong(IntPtr handleToWindow, int offsetToValueToGet); [DllImport("User32.dll")] private static extern int SetWindowLong(IntPtr h, int index, int value); private const int McmFirst = 0x1000; private const int McmGetminreqrect = (McmFirst + 9); private const int McsWeeknumbers = 0x4; private const int DtmFirst = 0x1000; private const int DtmGetmonthcal = (DtmFirst + 8); [DllImport("User32.dll")] private static extern IntPtr SendMessage(IntPtr h, int msg, int param, int data); [DllImport("User32.dll")] private static extern IntPtr GetParent(IntPtr h); [DllImport("User32.dll")] private static extern int SendMessage(IntPtr h, int msg, int param, ref Rectangle data); [DllImport("User32.dll")] private static extern int MoveWindow(IntPtr h, int x, int y, int width, int height, bool repaint); [Browsable(true), DesignerSerializationVisibility( DesignerSerializationVisibility.Visible)] public bool DisplayWeekNumbers { get; set; } protected override void OnDropDown(EventArgs e) { // Hex value to specify that we want the style-attributes // for the window: const int offsetToGetWindowsStyles = (-16); IntPtr pointerToCalenderWindow = SendMessage(Handle, DtmGetmonthcal, 0, 0); int styleForWindow = GetWindowLong(pointerToCalenderWindow, offsetToGetWindowsStyles); // Check properties for the control - matches available // property in the graphical properties for the DateTimePicker: if (DisplayWeekNumbers) { styleForWindow = styleForWindow | McsWeeknumbers; } else { styleForWindow = styleForWindow & ~McsWeeknumbers; } // Get the size needed to display the calendar (inner window) var rect = new Rectangle(); SendMessage(pointerToCalenderWindow, McmGetminreqrect, 0, ref rect); // Add to size as needed (I don't know why // this was not correct initially!) rect.Width = rect.Width + 28; rect.Height = rect.Height + 6; // Set window styles.. SetWindowLong(pointerToCalenderWindow, offsetToGetWindowsStyles, styleForWindow); // Dont move the window - just resize it as needed: MoveWindow(pointerToCalenderWindow, 0, 0, rect.Right, rect.Bottom, true); // Now access the parrent window.. var parentWindow = GetParent(pointerToCalenderWindow); // ...and resize that the same way: MoveWindow(parentWindow, 0, 0, rect.Right, rect.Bottom, true); base.OnDropDown(e); } } 

好的,尝试在Program.cs中注释一行

 Application.EnableVisualStyles(); 

然后尝试执行。