自分のブログ名

sheephumanのブログ

ひつじ好きな人間のブログ。

【C#】DateTimePickerをマウスホイールでインクリメント/デクリメントする

 

大分昔に書いたFC2Blog記事の転載。自作の家計簿アプリに組み込んであるヤツ。

いい記事なんだけど検索にヒットしないんで、はは(;'∀')。

 

 

 



 ひつじ!人間考案のシンプルな方法です。

 このDateTimePicker、実は内部にコンボボックス・テキストボックス等は組み込まれていないらしいです。外部から判別してWindowメッセージ等を拾えるようには作ってないらしく。じゃあ、どうやって内部にカーソルを当ててるのかって根本的な疑問がありますが
 
やっぱりListBoxが組み込まれてるって記述があったんで、ごにょごにょやれば行けるらしいです。
仕組みの把握が大変だな・・・


関連リンク 
TextBoxってReadOnly = trueでもフォーカスあたる。空気読めなさすぎだよね。


C#のDateTimePickerのソースです。
https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/DateTimePicker.cs




 Sender内部を調べたりしましたが、訳わかりませんね(笑) フォーカス時の違いが分からん。



 とりあえずどうしようもないため、内部でクライアント領域の座標から矩形領域を描き、そこにマウスが入っているかどうかを調べます。

  WindowsFormApplicationを使用しています。

 datetimePicker.png

 Paint 3Dで作成しました。

 大体、こんな感じです。
 まずは以下のコードで、各フォーカス時のクライアント座標の値を割り出すことにしました。

  public Form1()
        {
            InitializeComponent();
            this.dateTimePicker1.MouseWheel
              += new MouseEventHandler(this.dateTimePicker1_MouseWheel);
        }


      
        private void dateTimePicker1_MouseWheel(object sender, MouseEventArgs e)
        {
    Point WheelPoint = new Point(e.X, e.Y);
     // マウス座標をクライアント座標系へ変換
            Point mouseClientPos = dateTimePicker1.PointToClient(WheelPoint);

        Text = WheelPoint.ToString();
             
        }

 


 dateTimePicker2.png

 以下はおおまかな座標位置です。これを元にクライアント座標から指定の領域だけを区切れば、判定に成功する筈です。
Year
X=3-26 サイズは23 
Y=3-15 高さはdatetimePickerの高さでOK

Month
X=38-60 ほぼ同じ
Y=3-15

Day
X= 62-83
Y= 3-15


注意:DateTimePickerのLocationプロパティを座標(0,0)にしないと動作しません。
 任意の配置で動かすにはその都度調整が必要です。
 例:Location が X=37,Y= 108 の場合、その分を差し引いてあげるといいみたいです。

   

Rectangle YearRect = new Rectangle(PickerRectLocation.X -37 ,PickerRectLocation.Y + 3 -108  ,23, DTHeight); 

     


軽いので720P以上で見てくだせえ。



使わないともったいないのでSyntax ハイライターを入れた。死ぬ思いで入れた割にあまり使わなかったり・・・・。
<pre class="brush:csharp; height:400px"> コードすぐ忘れる・・・。


 


public Form1()
        {
            InitializeComponent();

            this.dateTimePicker1.MouseWheel
            += new MouseEventHandler(this.dateTimePicker1_MouseWheel);
        }


 
        DateTime DT = new DateTime();


private void dateTimePicker1_MouseWheel(object sender, MouseEventArgs e)
        {
           //dateTimePicker1の高さ
            int DTHeight = dateTimePicker1.Bounds.Height;

     //dateTimePickerのウィンドウ座標をクライアント座標に変換
            Point PickerRectLocation = dateTimePicker1.PointToClient(dateTimePicker1.Bounds.Location);
    

     //マウスホイール時の座標
            Point WheelPoint = new Point(e.X, e.Y);
        
            // マウス座標をDateTimePicker上のクライアント座標系へ変換
            Point mouseClientPos = dateTimePicker1.PointToClient(WheelPoint);

      //dateTimePickerのLocationプロパティの値を引く
            Rectangle YearRect = new Rectangle(PickerRectLocation.X -dateTimePicker1.Location.X ,PickerRectLocation.Y + 3 ,23, DTHeight);

            Rectangle MonthRect = new Rectangle(PickerRectLocation.X -dateTimePicker1.Location.X + 38,PickerRectLocation.Y + 3,23,DTHeight);
//+38は前ボックスとの間隔
            Rectangle DayRect = new Rectangle(PickerRectLocation.X -dateTimePicker1.Location.X+ 62, PickerRectLocation.Y + 3, 23, DTHeight);
        


       //年ボックス判定
      //年、月、日の数値をマウスホイールで1ずつ変える。        
            if (YearRect.Contains(mouseClientPos) == true)
            {

                // スクロール量(方向)の表示

                DT = dateTimePicker1.Value.AddYears(e.Delta / 120);
                dateTimePicker1.Text = DT.ToShortDateString();
            }
    //月ボックス判定
            else if(MonthRect.Contains(mouseClientPos) == true)
            {

                DT = dateTimePicker1.Value.AddMonths(e.Delta / 120);
                dateTimePicker1.Text = DT.ToShortDateString();


            }
   //日ボックス判定
            else if (DayRect.Contains(mouseClientPos) == true)
            {

                DT = dateTimePicker1.Value.AddDays(e.Delta / 120);
                dateTimePicker1.Text = DT.ToShortDateString();


            }
        }




自作の家計簿アプリに組み込んであります。

応用次第で色々出来る筈です。
カーソル位置を疑似的に判定して←キーを送信したり、クリックした年の数値をカーソル位置から判定して取り出すといった方法。Mousedownイベント等にも使えます。
 
 


 参考にしたサイト
  指定した座標がRectangle内か判定する - C#プログラミング
  
  スクリーン座標←→クライアント座標の変換を行うには?
    サンプルソースもある。