ComboBox のソースを見ていて面白いものがあったので紹介します。
何かというと、ComboBox で使われている ▼ボタンです。
最小化/最大化のボタンや、閉じるボタンなど、Windows で使われているいろいろなボタンのグラフィックは、実は Marlett というフォントを表示しているボタンです。
VB6.0のとき、ちょっとした部品として使ってたのですが、今回、.NET に移行するということで、どうやって VisualStyle を適用するかと思っていたところ、ComboBoxRenderer に描画している部分がありました。
VisualStyle が適用されていなければ、Marlett フォントの 'u' をキャプションとして表示します。
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
namespace VB6Control
{
// コンボボックス等で使われるドロップダウンボタンと同様のボタン
public class DropDownButton : Button
{
bool m_MouseIsDown;
bool m_MouseIsOver;
const string StaticText = "u"; // 常に "u"
const string StaticFontFamily = "Marlett"; // 常に "Marlett"
private static VisualStyleRenderer renderer = null;
private static readonly VisualStyleElement ComboBoxElement = VisualStyleElement.ComboBox.DropDownButton.Normal;
public DropDownButton()
{
m_MouseIsOver = false;
m_MouseIsDown = false;
// ▼ は Marlett フォントの 'u'
this.Font = base.Font;
base.Text = StaticText;
base.UseVisualStyleBackColor = true;
base.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
}
protected bool MouseIsDown
{
get { return m_MouseIsDown; }
set
{
if (m_MouseIsDown != value)
{
m_MouseIsDown = value;
Invalidate();
}
}
}
protected bool MouseIsOver
{
get { return m_MouseIsOver; }
set
{
if (m_MouseIsOver != value)
{
m_MouseIsOver = value;
Invalidate();
}
}
}
protected override void OnEnabledChanged(EventArgs e)
{
base.OnEnabledChanged(e);
Invalidate();
}
protected override void OnMouseCaptureChanged(EventArgs e)
{
base.OnMouseCaptureChanged(e);
m_MouseIsOver = false;
m_MouseIsDown = false;
Invalidate();
}
protected override void OnMouseDown(MouseEventArgs mevent)
{
base.OnMouseDown(mevent);
if ((mevent.Button & MouseButtons.Left) == MouseButtons.Left)
MouseIsDown = true;
}
protected override void OnMouseHover(EventArgs e)
{
base.OnMouseHover(e);
MouseIsOver = true;
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
MouseIsOver = false;
}
protected override void OnMouseUp(MouseEventArgs mevent)
{
base.OnMouseUp(mevent);
MouseIsDown = false;
}
protected override void OnPaint(PaintEventArgs pevent)
{
// アプリケーションが VisualStyle を適用していれば VisualStyleRenderer で描画
if (Application.RenderWithVisualStyles)
{
ComboBoxState cbState;
if (!base.Enabled)
cbState = ComboBoxState.Disabled;
else
{
if (MouseIsDown)
cbState = ComboBoxState.Pressed;
else if (MouseIsOver)
cbState = ComboBoxState.Hot;
else
cbState = ComboBoxState.Normal;
}
if (renderer == null)
renderer = new VisualStyleRenderer(ComboBoxElement.ClassName, ComboBoxElement.Part, (int)cbState);
else
renderer.SetParameters(ComboBoxElement.ClassName, ComboBoxElement.Part, (int)cbState);
renderer.DrawBackground(pevent.Graphics, this.ClientRectangle);
}
else
base.OnPaint(pevent);
}
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override string Text
{
get { return base.Text; }
set { base.Text = StaticText; }
}
[Browsable(false)]
public override Font Font
{
get { return base.Font; }
set
{
// サイズのみ適用
base.Font = new Font(StaticFontFamily, value.Size, FontStyle.Regular, value.Unit, value.GdiCharSet, false);
}
}
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new bool UseVisualStyleBackColor
{
get { return base.UseVisualStyleBackColor; }
set { base.UseVisualStyleBackColor = true; }
}
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new System.Drawing.ContentAlignment TextAlign
{
get { return System.Drawing.ContentAlignment.MiddleCenter; }
set { base.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; }
}
}
}