5

DateTimePickerここに示すように、週番号が表示された を作成しようとしています (コード プロジェクトの例)

1 つの細かい点を除いて、かなりうまく機能します。日付を選択しようとしたときに表示されるカレンダーのサイズが適切ではありません。ご覧のとおり、カレンダー領域は、特に右端に沿って、一種の「窮屈」です。

ここに画像の説明を入力

ここで右下隅をクリックし、少しドラッグして、正しく表示されるように拡張します。

ここに画像の説明を入力

カレンダーを最初から正しい/フルサイズにするか、サイズを変更する方法が見つからないようです。

4

3 に答える 3

7

最後に、少なくとも今のところ、うまくいくと思われる解決策を見つけました。

のカレンダー部分に 2 つのウィンドウがあるようDateTimePickerです。どうやら私のコードは、内側の正しいサイズを自動的に見つけますが (多かれ少なかれ少なくとも?)、外側のサイズは見つけません。

少し調べた結果、以下のコードにたどり着きました。次のリンクは、役立つ関連情報を提供します。

  • GetWindowLong 関数(編集するウィンドウに関する情報を取得するために使用されます)
  • GetParent 関数(外側のウィンドウを見つけて、それにも設定を適用できるようにします)

トリックは、(内側の) ウィンドウの高さと幅に少し追加してから、同じ高さと幅を外側のウィンドウ (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);
    }
}
于 2013-01-28T14:09:45.007 に答える
2

私にとってはMCS_WEEKNUMBERS、DateTimePicker のDTM_SETMCSTYLEメッセージを介して設定すると、MonthCal コントロールの正しいサイズが自動的に得られました。

SendMessage(Handle, DTM_FIRST + 11, 0, SendMessage(Handle, DTM_FIRST + 12, 0, 0) | MCS_WEEKNUMBERS);

KjartanのソリューションのどこDTM_FIRST = 0x1000で、どのように。これは、Microsoft のドキュメントに記載されています。MCS_WEEKNUMBERS = 0x4DTM_FIRST + 11DTM_SETMCSTYLEDTM_FIRST + 12DTM_GETMCSTYLE

Kjartan のソリューションとは異なり、この呼び出しは最初のドロップダウンの前に使用する必要がありますが、フォームの初期化の直後にうまくいかない場合があったため、フォームが既に作成されて表示されるまで遅らせました。1 回の呼び出しで十分です。DateTimePicker は、将来のドロップダウンのためにスタイルを保存します。

于 2020-02-27T07:15:09.343 に答える
1

わかりました、Program.cs の行にコメントを付けてみてください

Application.EnableVisualStyles();

そして、実行してみてください。

于 2014-11-05T10:11:57.930 に答える