ReadOnlyの時にチカチカしないNumericUpDownを作る
NumericUpDown
GUIで数値を上下に変化させて指定することができる、
NumericUpDownというFormコントロールがあります。
NumericUpDown クラス (System.Windows.Forms)
アプリケーションでユーザーに数値を入力してもらう際に、
ボタンを押せば一定間隔で指定ができるので、
開発側としても変な入力がされにくい便利なコントロール。
ReadOnly時のチカチカがいらないよね
ユーザが直接値を指定して変更させないために、
ReadOnlyのプロパティが用意されていますが、
ReadOnly時でもフォーカスに入るとカーソルがチカチカと点滅。
これじゃユーザが入力できると勘違いする恐れがあります。
チカチカしないNumericUpDownを作る
今回はSystem.Windows.Forms.NumericUpDownクラスを継承して、
ReadOnly時にキャレットを表示させないコントロールを実装してみました。
NumericUpDown継承クラスの作成
NumericUpDownクラスを継承した以下のクラスを作成します。
NumericUpDownNoBlinking.cs
using System; using System.Runtime.InteropServices; using System.Windows.Forms; using System.ComponentModel; namespace NumericUpDownNoBlinking { public partial class NumericUpDownNoBlinking : NumericUpDown { [DllImport("user32.dll")] static extern bool HideCaret(IntPtr hWnd); //キャレット表示の有無を指定 private bool caretVisible = true; //ReadOnlyメソッドを上書き public new bool ReadOnly { get { return base.ReadOnly; } set { base.ReadOnly = value; //キャレットの有無をReadOnly属性に応じて変更 caretVisible = !value; //ReadOnly有効時、NumericUpDownのTextBoxコントロールにカーソルを変化させない。 foreach (Control cntr in this.Controls) { if (cntr is TextBox) { if (caretVisible) { cntr.Cursor = Cursors.IBeam; } else { cntr.Cursor = Cursors.Arrow; } } } } } public NumericUpDownNoBlinking() { InitializeComponent(); } public NumericUpDownNoBlinking(IContainer container) { container.Add(this); InitializeComponent(); } //フォーカス取得時にキャレットを消去 protected override void OnGotFocus(EventArgs e) { base.OnGotFocus(e); if (!caretVisible) { //NumericUpDownのTextBoxコントロールのキャレットを非表示にする foreach (Control cntr in this.Controls) { if (cntr is TextBox) { HideCaret(cntr.Handle); } } } } } }
解説
Windwos APIのHideCaret関数を使えるように、
宣言しておきます。
[DllImport("user32.dll")] static extern bool HideCaret(IntPtr hWnd);
コントロールのOnGotFocusメソッドをオーバーライドし、
フォーカス取得時にControlsプロパティに格納されている
TextBoxのHandleをHideCaret関数の引数に渡せばOK。
protected override void OnGotFocus(EventArgs e) { base.OnGotFocus(e); if (!caretVisible) { //NumericUpDownのTextBoxコントロールのキャレットを非表示にする foreach (Control cntr in this.Controls) { if (cntr is TextBox) { HideCaret(cntr.Handle); } } } }
NumericUpDownのHandleではなくTextBoxを指定することがポイント!
また上記プログラムでは、
テキストボックス上にマウスカーソルが移動しても、
マウスポインタの形状を矢印のままにしています。
こちらもControlsプロパティに格納されているTextBoxに対して、
プロパティを変更することで対処しています。
参考
ネコキス: NumericUpDown のキャレットを消す
[C#] 独自に作成したウィンドウコントロールのコンポーネントにキャレットを表示する