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等のビジュアルスタイルをサポートしたレンダラクラスでは共通にサポートされている機能なので、同様に描画処理を記述できるだろう。