.NET Frameworkでお手軽SplitButton・その2

3:ドロップダウンメニューを作成
 オリジナルのドロップダウンメニューを作ろうと、コンテキストメニューの代わりにFormを表示させようとするとフォーカスが表示されたフォームに移動してしまい、なんだか不格好です。フォームのような柔軟さを兼ね備えたメニューを作るにはToolStripDropDownが最適です。ちなみにAnchorSelectControlはControlの派生クラスで、このControlに対してデザインを施すことになります。
anchorbtn.cs
private ToolStripDropDown dropdown;
private AnchorSelectControl asctrl;

public AnchorButton()
{
    this.Appearance = Appearance.Button;

    AnchorStyle = AnchorStyles.Left | AnchorStyles.Top;

    dropdown = new ToolStripDropDown();
    asctrl = new AnchorSelectControl();
    dropdown.Items.Add(new ToolStripControlHost(asctrl));
    dropdown.Closed += new ToolStripDropDownClosedEventHandler(dropdown_Closed);

    this.TextAlign = ContentAlignment.MiddleLeft;
}
4:ドロップダウンメニューの挙動を作成
 ボタンをクリックするとメニューが表示されるわけですが、このメニューが閉じられるとき、マウスカーソルがボタンの上にある時は何回やっても閉じられないため、ToolStripDropDownClosedでは、マウスカーソルの位置に応じて処理を変えるようにしています。
dropdown.cs
private void dropdown_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{
    // メニューの設定を反映
    AnchorStyle = asctrl.AnchorResult;

    if (!ClientRectangle.Contains(PointToClient(MousePosition))) {
        Checked = false;
    }
}

protected override void OnCheckedChanged(EventArgs e)
{
    base.OnCheckedChanged(e);

    if (this.Checked == false) {
        dropdown.Close();
    } else {
        asctrl.AnchorResult = AnchorStyle;
        dropdown.Show(this,
            ClientRectangle.Right - 100 - dropdown.GripMargin.Left,
            ClientRectangle.Bottom + 1 - dropdown.GripMargin.Top);
    }
}
 これを応用すれば、いわゆるカラーピッカーボタンも簡単に作れます。ただし、色数分のボタンを作成するとシステムに負担がかかるため、Paintイベントでボタンを描画することで、ボタンの挙動を擬似的に再現させた方がよいでしょう。
2007/10/24