web-dev-qa-db-ja.com

ドロップダウンメニュー付きのWindows.Formsボタン

.NET上のWindows.Formsを使用して、簡単なC#アプリケーションを開発しています。 ToolStripMenuによく似ていますが、ボタンを知っているように、サブカテゴリを含むドロップダウンメニューを表示するボタンが必要です。私はそれを検索し、バリアントを見つけることができませんでした。

私の質問は、これを行う方法はありますか、メニューをアタッチできる秘密のボタンプロパティがありますか?

任意の助けをいただければ幸いです。

35
tonytony

クリックイベントでContextMenuStripを表示できます。

private void button1_Click(object sender, EventArgs e) {
  contextMenuStrip1.Show(button1, new Point(0, button1.Height));
}

ボタンの上または下にメニューを表示するかどうかを独自に決定するには、このコードを使用してみてください。このコードは、メニューを測定し、部分的にオフスクリーンかどうかを決定します。

private void button1_Click(object sender, EventArgs e) {
  Point screenPoint = button1.PointToScreen(new Point(button1.Left, button1.Bottom));
  if (screenPoint.Y + contextMenuStrip1.Size.Height > Screen.PrimaryScreen.WorkingArea.Height) {
    contextMenuStrip1.Show(button1, new Point(0, -contextMenuStrip1.Size.Height));
  } else {
    contextMenuStrip1.Show(button1, new Point(0, button1.Height));
  }    
}
45
LarsTech

ボタンの右側に下矢印があり、デザイナーからメニューを設定できます。

ss

ShowMenuUnderCursorの場合:

ss

MenuButtonクラス:

public class MenuButton : Button
{
    [DefaultValue(null)]
    public ContextMenuStrip Menu { get; set; }

    [DefaultValue(false)]
    public bool ShowMenuUnderCursor { get; set; }

    protected override void OnMouseDown(MouseEventArgs mevent)
    {
        base.OnMouseDown(mevent);

        if (Menu != null && mevent.Button == MouseButtons.Left)
        {
            Point menuLocation;

            if (ShowMenuUnderCursor)
            {
                menuLocation = mevent.Location;
            }
            else
            {
                menuLocation = new Point(0, Height);
            }

            Menu.Show(this, menuLocation);
        }
    }

    protected override void OnPaint(PaintEventArgs pevent)
    {
        base.OnPaint(pevent);

        if (Menu != null)
        {
            int arrowX = ClientRectangle.Width - 14;
            int arrowY = ClientRectangle.Height / 2 - 1;

            Brush brush = Enabled ? SystemBrushes.ControlText : SystemBrushes.ControlDark;
            Point[] arrows = new Point[] { new Point(arrowX, arrowY), new Point(arrowX + 7, arrowY), new Point(arrowX + 3, arrowY + 4) };
            pevent.Graphics.FillPolygon(brush, arrows);
        }
    }
}
57
Jaex

@ Jaex answer を展開して、セパレータライン、何も設定されていない場合の矢印の条件付き描画、およびメインボタン本体とメニュー矢印の個別のクリックイベントを許可します。

アライメントを改善するために、button.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

enter image description here

ここに私のわずかな改善があります

public class SplitButton : Button
{
    [DefaultValue(null), Browsable(true),
    DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    public ContextMenuStrip Menu { get; set; }

    [DefaultValue(20), Browsable(true),
    DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    public int SplitWidth { get; set; }

    public SplitButton() 
    {
        SplitWidth = 20;
    }

    protected override void OnMouseDown(MouseEventArgs mevent)
    {
        var splitRect = new Rectangle(this.Width - this.SplitWidth, 0, this.SplitWidth, this.Height);

        // Figure out if the button click was on the button itself or the menu split
        if (Menu != null && 
            mevent.Button == MouseButtons.Left &&
            splitRect.Contains(mevent.Location) )
        {
            Menu.Show(this, 0, this.Height);    // Shows menu under button
            //Menu.Show(this, mevent.Location); // Shows menu at click location
        }
        else
        {
            base.OnMouseDown(mevent);
        }
    }

    protected override void OnPaint(PaintEventArgs pevent)
    {
        base.OnPaint(pevent);

        if (this.Menu != null && this.SplitWidth > 0)
        { 
            // Draw the arrow glyph on the right side of the button
            int arrowX = ClientRectangle.Width - 14;
            int arrowY = ClientRectangle.Height / 2 - 1;

            var arrowBrush = Enabled ? SystemBrushes.ControlText : SystemBrushes.ButtonShadow;
            var arrows = new[] { new Point(arrowX, arrowY), new Point(arrowX + 7, arrowY), new Point(arrowX + 3, arrowY + 4) };
            pevent.Graphics.FillPolygon(arrowBrush, arrows);

            // Draw a dashed separator on the left of the arrow
            int lineX = ClientRectangle.Width - this.SplitWidth;
            int lineYFrom = arrowY - 4;
            int lineYTo = arrowY + 8;
            using( var separatorPen = new Pen(Brushes.DarkGray){DashStyle = DashStyle.Dot})
            {
                pevent.Graphics.DrawLine(separatorPen, lineX, lineYFrom, lineX, lineYTo);
            }
        }
    }
}
15

簡単にできました。これは役立つかもしれません:)

ContextMenuStrip contextMenuStrip1 = new ContextMenuStrip();

        private void button1_Click(object sender, EventArgs e)
        {
            contextMenuStrip1.Items.Clear();
            contextMenuStrip1.Items.Add("item1");
            contextMenuStrip1.Items.Add("item2");

            contextMenuStrip1.Show(button1, new Point(0, button1.Height));
        }

        private void contextMenuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            if (e.ClickedItem.Text == "item1")
            {
                MessageBox.Show(e.ClickedItem.Text);
            }
        }
6
Mou

最も単純なオプションは、単一のボタンのみを表示するドッキングされていないToolStripでToolStripDropDownButtonを使用することです。次に、サブアイテムなどを追加できます。これを行うには:-ツールストリップをコントロール/フォームにドラッグします-レイアウトヘルパーを使用してDropDownButtonを追加します-GripStyleをHiddenに設定します-DockをNoneに設定します

結果は、説明したドロップダウン動作をサポートするスタンドアロンのツールバースタイルのボタンです。

5
JoshL

ボタンがクリックされたときに、ボタンの下にコンテキストメニューを表示します。

2
clearpath

上記のJaexのMenuButtonクラスは私にとって完璧でした。下のロジックをOnMouseDownに追加して、矢印をクリックした場合にのみコンテキストメニューが表示されるようにしました。大きな部分をクリックすると、通常のクリックイベントがトリガーされます。 「デフォルト」クリックアクションが許可されます。

if (Menu != null && mevent.Button == MouseButtons.Left)
{
    if (mevent.Location.X >= this.Width - 14)
    {
        System.Drawing.Point menuLocation;

        if (ShowMenuUnderCursor)
        {
            menuLocation = mevent.Location; 
        }
        else
        {
            menuLocation = new System.Drawing.Point(0, Height);
        }

        Menu.Show(this, menuLocation);
    }
}

これは誰かに役立つかもしれないと思った。ありがとうJaex

1
Jeff Scott

InfragisticsにはWinDropDownButtonがあります。 http://help.infragistics.com/Help/NetAdvantage/WinForms/2012.1/CLR2.0/html/WinDropDownButton_About_WinDropDownButton.html

確かに存在しますが、有料のサードパーティコントロールを探しているわけではありません。

0
roken

私もこの問題をいじっていて、非常に簡単な解決策を見つけました(少し汚いハッキングですが):ComboBoxButtonの下に置き、すぐ下にドロップダウン矢印が表示されるようにしますボタン。

次に、SelectedIndexChangedComboBoxを使用してButtonの動作を変更するか、すぐにやりたいことを行います。

0