ラジオボタンの「ホット状態」を描画する
WindowsXPのビジュアルスタイルが有効なGUIでは、「ホット(Hot)状態」と呼ばれる、マウスがコントロール上をポイントしている際に、強調表示するエフェクトが描画される。
これを知った当初はああ、また実装するコードが増えるじゃないか、なんて面倒な機能を追加してくれたもんだと嘆いたのだが、先日のエントリカスタムコントロール(その3)で紹介した、RadioButtonRendererクラス等のビジュアルスタイルに対応した描画クラスは、この"ホット状態"を容易に描画することができる。
protected override void OnPaint(PaintEventArgs e) { string caption = "ホット状態に対応"; Size textSize = TextRenderer.MeasureText(caption, this.Font); RadioButtonState buttonState = RadioButtonState.UncheckedNormal; if (this.Enabled) { if (ボタンは選択状態か?) { if (マウスカーソルがボタンの矩形上をポイントしているか?) { buttonState = RadioButtonState.CheckedHot; } else { buttonState = RadioButtonState.CheckedNormal; } } else { if (マウスカーソルがボタンの矩形上をポイントしているか?) { buttonState = RadioButtonState.UncheckedHot; } } } else { if (ボタンは選択状態か?) { buttonState = RadioButtonState.CheckedDisabled; } else { buttonState = RadioButtonState.UncheckedDisabled; } } RadioButtonRenderer.DrawRadioButton(e.Graphics, new Point(0, 0), new Rectangle(10, 0, textSize .Width, textSize .Height), caption, this.Font, TextFormatFlags.PreserveGraphicsTranslateTransform, true, buttonState); }
RadioButtonStateには、ホット状態を示す列挙メンバ、UncheckedHotやCheckedHot等が用意されており、これを適切に描画時に指定するだけだ。
サンプルではRadioButtonStateを決定する条件を日本語で書いたが、System.Windows.Forms.Controlを継承したクラスであれば、protected定義されているOnMouseMoveメソッドやOnMouseLeave中で、上記条件を満たしているかを判定するのは簡単に書けるだろう。メソッド中で条件を満たしたと判定できたら、Invalidateメソッド等で再描画を促せばよい。
private int mouseEnter = -1; protected override void OnMouseMove(MouseEventArgs e) { Point mouseLoc = e.Location; this.mouseEnter = this.HitTest(mouseLoc); if ( this.mouseEnter != -1) { this.Invalidate(); } base.OnMouseMove(e); } protected override void OnMouseLeave(EventArgs e) { this.mouseEnter = -1; this.Invalidate(); base.OnMouseLeave(e); } private int HitTest(Point loc) { //ヒットしたボタンの座標などを返すヒットテスト(内容は省略) if (found) { return i; } else { return -1; } }
なお、この手法はCheckBoxRenderer等のビジュアルスタイルをサポートしたレンダラクラスでは共通にサポートされている機能なので、同様に描画処理を記述できるだろう。