.NET上のWindows.Formsを使用して、簡単なC#アプリケーションを開発しています。 ToolStripMenuによく似ていますが、ボタンを知っているように、サブカテゴリを含むドロップダウンメニューを表示するボタンが必要です。私はそれを検索し、バリアントを見つけることができませんでした。
私の質問は、これを行う方法はありますか、メニューをアタッチできる秘密のボタンプロパティがありますか?
任意の助けをいただければ幸いです。
クリックイベントで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));
}
}
ボタンの右側に下矢印があり、デザイナーからメニューを設定できます。
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);
}
}
}
@ Jaex answer を展開して、セパレータライン、何も設定されていない場合の矢印の条件付き描画、およびメインボタン本体とメニュー矢印の個別のクリックイベントを許可します。
アライメントを改善するために、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);
}
}
}
}
簡単にできました。これは役立つかもしれません:)
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);
}
}
最も単純なオプションは、単一のボタンのみを表示するドッキングされていないToolStripでToolStripDropDownButtonを使用することです。次に、サブアイテムなどを追加できます。これを行うには:-ツールストリップをコントロール/フォームにドラッグします-レイアウトヘルパーを使用してDropDownButtonを追加します-GripStyleをHiddenに設定します-DockをNoneに設定します
結果は、説明したドロップダウン動作をサポートするスタンドアロンのツールバースタイルのボタンです。
ボタンがクリックされたときに、ボタンの下にコンテキストメニューを表示します。
上記の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
InfragisticsにはWinDropDownButtonがあります。 http://help.infragistics.com/Help/NetAdvantage/WinForms/2012.1/CLR2.0/html/WinDropDownButton_About_WinDropDownButton.html
確かに存在しますが、有料のサードパーティコントロールを探しているわけではありません。
私もこの問題をいじっていて、非常に簡単な解決策を見つけました(少し汚いハッキングですが):ComboBox
をButton
の下に置き、すぐ下にドロップダウン矢印が表示されるようにしますボタン。
次に、SelectedIndexChanged
のComboBox
を使用してButton
の動作を変更するか、すぐにやりたいことを行います。