DOBON.NET DOBON.NETプログラミング掲示板過去ログ

DateTimePickerのインクリメント・ディクリメントについて

環境/言語:[Windows2000 VB.NET .NET Framework1.1]
分類:[.NET]

okaと申します。
いつも大変参考にしております。
本日はDateTimePickerについてご質問させてください。

DateTimePickerコントロールにフォーカスがあるときに、↑↓キー押下によりカーソル位置の値のインクリメントとディクリメントが発生しますが、このとき繰り上げと繰り下げ処理を行う事が出来ません。
例えば、「2005/01/01」という表示状態で日付の「01」にカーソルがあるとき、↓キーを押下すると「2004/12/31」と表示させたいのです。
現在の動きは「2005/01/31」となってしまいます。

つまり、カーソル位置のみのインクリメント・ディクリメントではなく、月末日や月初日、年末日等にカーソルがあたっていない箇所にも繰り上げ、繰り下げとして反映させたいのです。

上記問題の解決方法をご存知の方がいらっしゃれば、ご教授いただけないでしょうか?
よろしくお願いいたします。
#そうやって意図しない動きにすること自体使いやすいとは思いませんが・・・
ValueChangedをオーバーライドして、前回の値を保持するようにして、前回の値との差が1日で、1->31なら月もデクリメント、31->1なら月をインクリメントするようにすれば出来るでしょう。
カレンダーを利用して1->31しても月が替わってしまうかもしれません。

#もちろん日は28〜31日まであるので一様じゃないですし、月も年も考慮しないと駄目ですよ。


------------------------------------------------------
中博俊 MSMVP Visual Studio C# Since 2004/04-2005/03, MCP
http://naka.wankuma.com/
http://naka.wankuma.com/blog/
naka@wankuma.com
■No9011に返信(中 博俊さんの記事)

中 博俊さん 早速のレスありがとうございます。

> #そうやって意図しない動きにすること自体使いやすいとは思いませんが・・・
はい。確かにそうなんですけど、今稼動中のシステムのアップグレード版を作っていまして、その旧システムではインプットマンを使用していて、そのような動きになっているらしく、オペレーターが覚えてしまっているため、基本的な動きは引き継ぐという仕様なのです・・・。

> ValueChangedをオーバーライドして、前回の値を保持するようにして、前回の値との差が1日で、1->31なら月もデクリメント、31->1なら月をインクリメントするようにすれば出来るでしょう。
> カレンダーを利用して1->31しても月が替わってしまうかもしれません。
>
> #もちろん日は28〜31日まであるので一様じゃないですし、月も年も考慮しないと駄目ですよ。

これに関しては、似たようなことを試してみたのですが、カレンダーからだけでなくキーボードから直接数字を入力されても変更されてしまいます。
↑↓キーの値変更時のみ対応する必要があるので、困っています。

DateTimePickerのKeyDownイベント発生時(↑↓キー押下時)に、カーソル位置が年か月か日かわかれば何とかなりそうなんですが・・・。

ご存知ないでしょうか?
KeyDownなんかと組み合わせて、事前にどのキーが入力されたのかキープしておけば出来るんじゃ?
■No9018に返信(okaさんの記事)

平ちゃんです。こんにちは

> これに関しては、似たようなことを試してみたのですが、カレンダーからだけでなくキーボードから直接数字を入力されても変更されてしまいます。
> ↑↓キーの値変更時のみ対応する必要があるので、困っています。
>
> DateTimePickerのKeyDownイベント発生時(↑↓キー押下時)に、カーソル位置が年か月か日かわかれば何とかなりそうなんですが・・・。
>


中 博俊さんが仰るようにDateTimePicker.ValueChanged イベント で値を管理すること位でしょうか。
(日付はDateTime構造体で簡単に管理できます。)

#DateTimePicker.ValueChanged イベントで下手打つと訳の解らない現象になりますが、しっかりと管理すれば大丈夫です。

#再帰的な呼び出し防止にフラグ等も必要になります。
■No9023に返信(平ちゃんさんの記事)

中 博俊さん、平ちゃんさんレスありがとうございます。

やはりお二人のおっしゃる通り自分で管理するしかないのですね。
なにか、プロパティかイベントで使えそうなやつがないかずっと探していたのですが・・・。
何とか自分で制御してみることにします。

お二人には大変感謝しております。
今後ともよろしくお願いいたします。
ありがとうございました。
解決済み!
皆さんのご意見をまとめると (C# ですけど) こんな感じでしょうか。

実験してみると OnKeyPress も override しておく必要があるようです。
たとえば、↓キーで 2005/2/1 まで下げた後、
テンキーで日の部分に 28 と入力すると
override すると 2005/2/28 となりますが、
しておかないと 2005/1/31 となってしまい、不自然な感じがします。

    public class MyDateTimePicker : System.Windows.Forms.DateTimePicker
    {
        private DateTime oldValue;

        public MyDateTimePicker() : base()
        {
            this.oldValue = this.Value;
        }

        private bool UpDownPressed = false;

        protected override void OnKeyDown(KeyEventArgs e)
        {
            if      ( ( e.KeyCode & Keys.Down ) == Keys.Down )
                this.UpDownPressed = true;
            else if ( ( e.KeyCode & Keys.Up ) == Keys.Up )
                this.UpDownPressed = true;
            else
                this.UpDownPressed = false;
            base.OnKeyDown (e);
        }

        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            this.UpDownPressed = false;
            base.OnKeyPress (e);
        }

        private bool ValueChanging = false;

        protected override void OnValueChanged(EventArgs eventargs)
        {
            if ( this.ValueChanging )
                return;
            this.ValueChanging = true;
            try
            {
                if ( this.UpDownPressed )
                {
                    if      ( this.oldValue.Day == 1 && this.Value.Day > 2 )
                        this.Value = this.oldValue.AddDays( -1 );
                    else if ( this.oldValue.Day > 2 && this.Value.Day == 1 )
                        this.Value = this.oldValue.AddDays( +1 );
                    else if ( this.oldValue.Month == 1 && this.Value.Month > 2 )
                        this.Value = this.oldValue.AddMonths( -1 );
                    else if ( this.oldValue.Month > 2 && this.Value.Month == 1 )
                        this.Value = this.oldValue.AddMonths( +1 );
                }
            }
            finally
            {
                this.ValueChanging = false;
            }
            base.OnValueChanged (eventargs);
            this.oldValue = this.Value;
        }
    }
■No9036に返信(通りすがりのもですがさんの記事)

通りすがりのもですが さんレスありがとうございます。
しかもソースまで書いていただいて大変感謝です。
早速試してみたいかと思います。

後日結果を書き込みます。
ありがとうございました。
■No9040に返信(okaさんの記事)

自己レスです。
すみません。結果報告が大変遅くなってしまいました。

通りすがりのものですがさんに頂いたサンプルソースが完璧に機能しました。
あれから、別の処理に追われてやっと組み込むことが出来ましたので、そのお礼と報告を申し上げます。

通りすがりのものですがさん、大変ありがとうございました。
ならびに、中 博俊さん、平ちゃんさんありがとうございました。

今後ともよろしくお願いいたします。
■No9204に返信(okaさんの記事)

すみません。解決済みです。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板