[英]How to add Controls, as a toolbar, to a ContextMenuStrip?
這是一個自定義組件,繼承了承載 UserControl 而不是標准控件的ToolStripControlHost (如 .Net 的ToolStripTextBox 、 ToolStripComboBox等)。
▶ 構建一個 UserControl,您可以將任何其他控件添加到其表面並照常管理它們的操作,除了 UserControl 的事件通過ToolStripControlHost
派生的 object 公開,因此實施者不需要了解有關底層托管控件的任何信息。
您要公開的托管控件的事件訂閱覆蓋OnSubscribeControlEvents() (當然取消訂閱覆蓋OnUnsubscribeControlEvents ),然后引發相關或組合事件,根據需要返回值。
▶ 這顯示在ToolStripControlHost
class 中,請參閱public event EventHandler<UserActionArgs> ButtonAction
事件,該事件返回自定義EventArgs
參數,其中包括確定單擊按鈕執行的操作所需的元素。
需要時,托管控件通過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
派生的 class:
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 object :
public class UserActionArgs : EventArgs
{
public UserActionArgs(ButtonAction action, Control control)
{
this.UserAction = action;
this.TriggerControl = control;
}
public ButtonAction UserAction { get; }
public Control TriggerControl { get; }
}
動作枚舉器:
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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.