ton*_*ony 37 c# winforms drop-down-menu
我正在使用.NET上的Windows.Forms开发简单的C#应用程序.我需要一些按钮,它会显示一个包含子类别的下拉菜单 - 很像ToolStripMenu,但是按钮,你知道.我搜索它并找不到任何变种.
我的问题是:有没有办法做到这一点,也许一些秘密按钮属性,允许附加菜单吗?
任何帮助将不胜感激.
Jae*_*aex 58
按钮右下方有箭头,你可以从设计师设置它的菜单:

使用ShowMenuUnderCursor:

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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
Lar*_*ech 45
您可以在click事件上显示ContextMenuStrip:
private void button1_Click(object sender, EventArgs e) {
contextMenuStrip1.Show(button1, new Point(0, button1.Height));
}
Run Code Online (Sandbox Code Playgroud)
要自行确定是否在按钮上方或下方显示菜单,您可以尝试使用此代码来测量菜单并确定它是否部分在屏幕外:
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));
}
}
Run Code Online (Sandbox Code Playgroud)
Sve*_*son 16
扩展@Jaex回答一点,以允许分隔线,如果没有配置任何箭头的条件绘图和主按钮主体和菜单箭头的单独点击事件.
应该注意的是,为了更好地对齐,你可以设置 button.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
这是我的微小改进
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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我们能做到这一点很容易.这可能有帮助:)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
最简单的选择是在仅展示单个按钮的未停靠的ToolStrip中使用ToolStripDropDownButton.然后你可以添加子项,等等.为此: - 将一个Toolstrip拖到你的控件/窗体上 - 使用布局助手添加一个DropDownButton - 将GripStyle设置为隐藏 - 将Dock设置为None
结果是一个独立的工具栏样式按钮,它支持您描述的下拉行为.