最後に、少なくとも今のところ、うまくいくと思われる解決策を見つけました。
のカレンダー部分に 2 つのウィンドウがあるようDateTimePicker
です。どうやら私のコードは、内側の正しいサイズを自動的に見つけますが (多かれ少なかれ少なくとも?)、外側のサイズは見つけません。
少し調べた結果、以下のコードにたどり着きました。次のリンクは、役立つ関連情報を提供します。
トリックは、(内側の) ウィンドウの高さと幅に少し追加してから、同じ高さと幅を外側のウィンドウ (GetParrent()
関数を使用してアクセスします) に適用することでした。試行錯誤して「正しい」サイズを見つけました。サイズがカレンダーの内容に必要なサイズに一致すると、サイズを変更できなくなりました。
はい、これは少しハックのように感じます。いいえ、自分のコンピューター以外のコンピューターで完全に動作することをまだ確認できていません。高さと幅に特定の値を指定しなければならないことが少し心配ですが、これが画面の解像度などの影響を受けないことを願っています。
同様の状況にある他の誰かがコードが役立つことを願っています。
(以下は、通常のカレンダーを直接置き換えて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);
}
}