winforms 如何将控件作为工具栏添加到ContextMenuStrip?

5tmbdcev  于 2023-08-07  发布在  其他
关注(0)|答案(1)|浏览(118)

我正在制作一个Web浏览器,但我不知道如何在其ContextMenuStrip的顶部添加这些按钮:


的数据
分隔符为所有项创建列,但仅为一行创建列。
你知道该怎么做吗?

moiiocjp

moiiocjp1#

这是一个自定义组件,继承了ToolStripControlHost(如.Net的ToolStripTextBoxToolStripComboBox等),它承载了一个UserControl而不是标准Control。
▶构建一个UserControl,你可以添加任何其他控件到它的表面,并像往常一样管理它们的操作,除了UserControl的事件通过ToolStripControlHost派生对象公开,所以实现者不需要知道任何关于底层托管控件的信息。
您要公开的宿主控件的事件订阅覆盖OnSubscribeControlEvents()(当然也取消订阅覆盖OnUnsubscribeControlEvents),然后引发一个相关或 * 合成 * 事件,该事件根据需要返回值。
▶这在ToolStripControlHost类中显示,请参阅public event EventHandler<UserActionArgs> ButtonAction事件,该事件返回自定义EventArgs参数,该参数包括确定所单击的Button执行的操作所需的元素。
当需要时,宿主控件通过ToolStripControlHost.Control属性公开。
您可以在使用它的Form的构造函数中初始化现有的ContextMenuStrip(contextMenuStrip1,这里):

public partial class Form1 : Form
{
    private ToolStripUserControl toolStripUC = new ToolStripUserControl();

    public Form1()
    {
        InitializeComponent();

        // Assigns an existing ContextMenuStrip, to the Form or any other Control
        this.ContextMenuStrip = contextMenuStrip1;

        // Inserts the ToolStripUserControl and a Separator
        contextMenuStrip1.Items.Insert(0, new ToolStripSeparator());
        contextMenuStrip1.Items.Insert(0, toolStripUC);

        // Subscribes to the ButtonAction event
        toolStripUC.ButtonAction += (s, e) 
            => { this.Text = $"Your Action is {e.UserAction}, triggered by {e.TriggerControl.Name}"; };
        contextMenuStrip1.Closed += (s, e) => this.Text = "Right-Click on me";
    }
}

字符串

ToolStripControlHost派生类:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;

[ToolboxItem(false)]
public class ToolStripUserControl : ToolStripControlHost
{
    // Pass the UserControl, MenuStripNavigationBar, to the base class.
    public ToolStripUserControl() : base(new MenuStripNavigationBar()) { }

    public MenuStripNavigationBar NavigatorBar => Control as MenuStripNavigationBar;

    // Exposes the ButtonActions Dictionary, to redefine the Buttons' actions
    public Dictionary<Control, ButtonAction> ButtonActions {
        get => NavigatorBar.ButtonActions;
        set => NavigatorBar.ButtonActions = value;
    }

    // Subscribe to the events you want to expose...
    protected override void OnSubscribeControlEvents(Control ctl)
    {
        base.OnSubscribeControlEvents(ctl);
        var navigatorBar = (MenuStripNavigationBar)ctl;
        navigatorBar.UserAction += OnButtonAction;
    }

    // ...and then unsubscribe. This is called when the Form is destroyed
    protected override void OnUnsubscribeControlEvents(Control ctl)
    {
        base.OnUnsubscribeControlEvents(ctl);
        var navigatorBar = (MenuStripNavigationBar)ctl;
        navigatorBar.UserAction -= OnButtonAction;
    }

    // Exposes a public custom event
    public event EventHandler<UserActionArgs> ButtonAction;

    // Raises the event when an UserAction is triggered
    private void OnButtonAction(object sender, EventArgs e)
    {
        var ctl = sender as Control;
        var userAction = new UserActionArgs(ButtonActions[ctl], ctl);
        ButtonAction?.Invoke(this, userAction);
    }
}

自定义EventArgs对象

public class UserActionArgs : EventArgs
{
    public UserActionArgs(ButtonAction action, Control control)
    {
        this.UserAction = action;
        this.TriggerControl = control;
    }
    public ButtonAction UserAction { get; }
    public Control TriggerControl { get; }
}

Actions枚举器

public enum ButtonAction
{
    MoveBack,
    MoveForward,
    PlayMusic,
    PlayAnimation
}


它是这样工作的:


的数据
这是完整的UserControl,以简化测试:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

public partial class MenuStripNavigationBar : UserControl
{
    public event EventHandler UserAction;

    public MenuStripNavigationBar()
    {
        InitializeComponent();
        this.ButtonActions = new Dictionary<Control, ButtonAction>();

        this.buttonArrowLeft.Text = "⏪";
        ButtonActions.Add(this.buttonArrowLeft, ButtonAction.MoveBack);
        this.buttonArrowLeft.Click += ButtonsActionEvent;

        this.buttonArrowRight.Text = "⏩";
        ButtonActions.Add(this.buttonArrowRight, ButtonAction.MoveBack);
        this.buttonArrowRight.Click += ButtonsActionEvent;

        this.buttonMusicKey.Text = "♬";
        ButtonActions.Add(this.buttonMusicKey, ButtonAction.PlayMusic);
        this.buttonMusicKey.Click += ButtonsActionEvent;

        this.buttonAction.Text = "⛄";
        ButtonActions.Add(this.buttonAction, ButtonAction.PlayAnimation);
        this.buttonAction.Click += ButtonsActionEvent;
    }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public Dictionary<Control, ButtonAction> ButtonActions { get; set; }

    private void ButtonsActionEvent(object sender, EventArgs e) 
        => UserAction?.Invoke(sender, e);

    [ToolboxItem(false)]
    internal class ButtonPanel : Panel
    {
        private Color borderActiveColor = Color.LightSteelBlue;
        private Color borderInactiveColor = Color.Gray;
        private Color borderColor = Color.Transparent;

        public ButtonPanel()
        {
            this.SetStyle(ControlStyles.Selectable | ControlStyles.SupportsTransparentBackColor | 
                          ControlStyles.UserMouse | ControlStyles.StandardClick, true);
            this.UpdateStyles();
            this.BackColor = Color.Transparent;
        }

        protected override void OnMouseEnter(EventArgs e)
        {
            base.OnMouseEnter(e);
            this.OnEnter(e);
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            this.OnLeave(e);
        }

        protected override void OnEnter(EventArgs e)
        {
            base.OnEnter(e);
            bool hovered = this.ClientRectangle.Contains(this.PointToClient(MousePosition));
            borderColor = hovered ? Enabled ? borderActiveColor : borderInactiveColor : Color.Transparent;
            this.Invalidate();
        }

        protected override void OnLeave(EventArgs e)
        {
            if (this.ClientRectangle.Contains(this.PointToClient(MousePosition))) return;
            borderColor = Color.Transparent;
            base.OnLeave(e);
            this.Invalidate();
        }

        TextFormatFlags flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | 
            TextFormatFlags.NoPadding | TextFormatFlags.PreserveGraphicsClipping | TextFormatFlags.SingleLine;

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            var textRect = Rectangle.Inflate(ClientRectangle, 0, -1);
            TextRenderer.DrawText(e.Graphics, Text, Font, textRect, ForeColor, Color.Empty, flags);
            ControlPaint.DrawBorder(e.Graphics, ClientRectangle, borderColor, ButtonBorderStyle.Solid);
        }
    }
}


设计器文件:

partial class MenuStripNavigationBar
{
    private System.ComponentModel.IContainer components = null;

    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null)) {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    private void InitializeComponent()
    {
        this.buttonAction = new MenuStripNavigationBar.ButtonPanel();
        this.buttonArrowLeft = new MenuStripNavigationBar.ButtonPanel();
        this.buttonArrowRight = new MenuStripNavigationBar.ButtonPanel();
        this.buttonMusicKey = new MenuStripNavigationBar.ButtonPanel();
        this.SuspendLayout();
        // 
        // buttonAction
        // 
        this.buttonAction.BackColor = System.Drawing.Color.Transparent;
        this.buttonAction.Font = new System.Drawing.Font("Segoe UI Symbol", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
        this.buttonAction.Location = new System.Drawing.Point(166, 2);
        this.buttonAction.Name = "buttonAction";
        this.buttonAction.Size = new System.Drawing.Size(42, 26);
        this.buttonAction.TabIndex = 0;
        // 
        // buttonArrowLeft
        // 
        this.buttonArrowLeft.BackColor = System.Drawing.Color.Transparent;
        this.buttonArrowLeft.Font = new System.Drawing.Font("Segoe UI Symbol", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
        this.buttonArrowLeft.Location = new System.Drawing.Point(3, 2);
        this.buttonArrowLeft.Name = "buttonArrowLeft";
        this.buttonArrowLeft.Size = new System.Drawing.Size(42, 26);
        this.buttonArrowLeft.TabIndex = 0;
        // 
        // buttonArrowRight
        // 
        this.buttonArrowRight.BackColor = System.Drawing.Color.Transparent;
        this.buttonArrowRight.Font = new System.Drawing.Font("Segoe UI Symbol", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
        this.buttonArrowRight.Location = new System.Drawing.Point(58, 2);
        this.buttonArrowRight.Name = "buttonArrowRight";
        this.buttonArrowRight.Size = new System.Drawing.Size(42, 26);
        this.buttonArrowRight.TabIndex = 0;
        // 
        // buttonMusicKey
        // 
        this.buttonMusicKey.BackColor = System.Drawing.Color.Transparent;
        this.buttonMusicKey.Font = new System.Drawing.Font("Segoe UI Symbol", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
        this.buttonMusicKey.Location = new System.Drawing.Point(112, 2);
        this.buttonMusicKey.Name = "buttonMusicKey";
        this.buttonMusicKey.Size = new System.Drawing.Size(42, 26);
        this.buttonMusicKey.TabIndex = 0;
        // 
        // MenuStripNavigationBar
        // 
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
        this.BackColor = System.Drawing.Color.Transparent;
        this.Controls.Add(this.buttonMusicKey);
        this.Controls.Add(this.buttonArrowRight);
        this.Controls.Add(this.buttonArrowLeft);
        this.Controls.Add(this.buttonAction);
        this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
        this.MaximumSize = new System.Drawing.Size(212, 30);
        this.MinimumSize = new System.Drawing.Size(212, 30);
        this.Name = "MenuStripNavigationBar";
        this.Size = new System.Drawing.Size(212, 30);
        this.ResumeLayout(false);
    }

    private ButtonPanel buttonAction;
    private ButtonPanel buttonArrowLeft;
    private ButtonPanel buttonArrowRight;
    private ButtonPanel buttonMusicKey;
}

相关问题