ToolStripLayoutStyle.Table 在 ContextMenuStrip 中不工作
ToolStripLayoutStyle.Table not working in ContextMenuStrip
我想显示一个上下文菜单,其中菜单项是在网格中布置的图像。但是,当我在菜单的 ToolStripDropDown 中将 LayoutStyle
设置为 ToolStripLayoutStyle.Table
时,如果创建了新的 ToolStripDropDown 对象,它只会给出菜单项的网格布局。
我的问题是我可以为子菜单创建并分配一个新的 ToolStripDropDown,但不能为 ContextMenuStrip,因为它是 ToolStripDropDown。
下面的代码演示了这个问题。它将显示一个上下文菜单,其中包含颜色样本图像以及两个具有相同图像的子菜单。所有三个菜单都将 LayoutStyle
属性 设置为 ToolStripLayoutStyle.Table
,但实际上只有一个会显示为网格。
private void FillDropDown(ToolStripDropDown drop_down)
{
// Set the drop down to a 2 column table layout
drop_down.LayoutStyle = ToolStripLayoutStyle.Table;
TableLayoutSettings table_layout_settings = (TableLayoutSettings)drop_down.LayoutSettings;
table_layout_settings.ColumnCount = 2;
// Fill the menu with some colour swatches
Color[] colours = { Color.Red, Color.Orange, Color.Yellow, Color.Green, Color.Blue, Color.Purple };
foreach (Color colour in colours) {
ToolStripMenuItem item = new ToolStripMenuItem();
Bitmap swatch = new Bitmap(64, 64);
using (Graphics g = Graphics.FromImage(swatch))
using (SolidBrush b = new SolidBrush(colour)) {
g.FillRectangle(b, 0, 0, 64, 64);
}
item.Image = swatch;
item.DisplayStyle = ToolStripItemDisplayStyle.Image;
item.Margin = new Padding(2, 2, 2, 2);
drop_down.Items.Add(item);
}
}
private void ShowColorMenu(Point screen_location)
{
ContextMenuStrip context_menu = new ContextMenuStrip();
// The root context menu will not layout as a grid
FillDropDown(context_menu);
// This sub-menu will not layout as a grid
ToolStripMenuItem sub_menu = new ToolStripMenuItem("Sub-menu");
FillDropDown(sub_menu.DropDown);
context_menu.Items.Add(sub_menu);
// A sub-menu will layout as a grid if we create a new ToolStripDropDown for it
ToolStripMenuItem grid_sub_menu = new ToolStripMenuItem("Grid Sub-menu");
ToolStripDropDown new_drop_down = new ToolStripDropDown();
FillDropDown(new_drop_down);
grid_sub_menu.DropDown = new_drop_down;
context_menu.Items.Add(grid_sub_menu);
context_menu.Show(screen_location);
}
在我的机器上结果如下:
我想在上下文菜单的根目录中有一个图像网格。理解它为什么会这样也很好。我查看了 .NET 参考源,但这对这次没有帮助。
ContextMenuStrip cannot show its ToolStripMenuItems in a Table layout, because of a limitation in Menu presentation/layout and you also cannot cast ContextMenuStrip to ToolStripDropDown (or the other way around; it's a wrapper around ToolStripDropDownMenu,它不能转换到它的间接祖先:它将保留其特定功能(例如,您可以查看 TextBox 和 ListBox 都为 Control
,但这并不意味着,现在,设置 ListBox 的 Text 实际上会在某处显示文本,只是因为 Text 属性 属于控件 class).
但是您可以像使用 ContextMenuStrip 一样直接使用和显示 ToolStripDropDown。完全支持 ToolStripDropDown 的 LayoutSettings can be cast directly to TableLayoutSettings and a LayoutStyle of type ToolStripLayoutStyle.Table。
在示例中,包含以 Table 布局排列的 ToolStripMenuItem 的 ToolStripDropDown 对象用作 ContextMenuStrip 以 select 彩色图像应用于 PictureBox 控件,而 Color名称显示在 Label 控件中。
下拉菜单在窗体初始化时创建,在窗体的 ClientArea 中单击鼠标右键显示,在窗体关闭时删除:
Note1:在这里,我使用 Lambda 来订阅 ToolStripDropDown.ItemClicked
事件。但是,对于这种类型的控件,最好改用方法委托。
注2:ToolStripDropDown 处理调用contextColorMenu.Dispose();
。如果频繁打开和关闭容器窗体,显式处理 ToolStripMenuItems Images 可能会更好。
using System.Drawing;
using System.Windows.Forms;
public partial class SomeForm : Form
{
private ToolStripDropDown contextColorMenu = null;
public SomeForm()
{
InitializeComponent();
contextColorMenu = new ToolStripDropDown();
contextColorMenu.ItemClicked += (o, a) => {
// Assign the selected Bitmap to a PitureBox.Image
picColor.Image = a.ClickedItem.Image;
// Show the Color description in a Label
lblColor.Text = ((Color)a.ClickedItem.Tag).ToString();
};
FillDropDown(contextColorMenu);
}
private void ShowColorMenu(Point location) => contextColorMenu.Show(location);
private void FillDropDown(ToolStripDropDown dropDown)
{
dropDown.LayoutStyle = ToolStripLayoutStyle.Table;
(dropDown.LayoutSettings as TableLayoutSettings).ColumnCount = 2;
(dropDown.LayoutSettings as TableLayoutSettings).GrowStyle = TableLayoutPanelGrowStyle.AddRows;
Color[] colors = { Color.Red, Color.Orange, Color.Yellow, Color.Green, Color.Blue, Color.Purple };
foreach (Color color in colors) {
var swatch = new Bitmap(64, 64);
using (var g = Graphics.FromImage(swatch)) {
g.Clear(color);
}
var item = new ToolStripMenuItem() {
DisplayStyle = ToolStripItemDisplayStyle.Image,
Image = swatch,
Tag = color,
Margin = new Padding(2),
Padding = new Padding(2, 1, 2, 1) // Fine tune the Items' Cell border
};
dropDown.Items.Add(item);
}
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Right) {
ShowColorMenu(MousePosition);
}
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
contextColorMenu?.Dispose();
}
}
我想显示一个上下文菜单,其中菜单项是在网格中布置的图像。但是,当我在菜单的 ToolStripDropDown 中将 LayoutStyle
设置为 ToolStripLayoutStyle.Table
时,如果创建了新的 ToolStripDropDown 对象,它只会给出菜单项的网格布局。
我的问题是我可以为子菜单创建并分配一个新的 ToolStripDropDown,但不能为 ContextMenuStrip,因为它是 ToolStripDropDown。
下面的代码演示了这个问题。它将显示一个上下文菜单,其中包含颜色样本图像以及两个具有相同图像的子菜单。所有三个菜单都将 LayoutStyle
属性 设置为 ToolStripLayoutStyle.Table
,但实际上只有一个会显示为网格。
private void FillDropDown(ToolStripDropDown drop_down)
{
// Set the drop down to a 2 column table layout
drop_down.LayoutStyle = ToolStripLayoutStyle.Table;
TableLayoutSettings table_layout_settings = (TableLayoutSettings)drop_down.LayoutSettings;
table_layout_settings.ColumnCount = 2;
// Fill the menu with some colour swatches
Color[] colours = { Color.Red, Color.Orange, Color.Yellow, Color.Green, Color.Blue, Color.Purple };
foreach (Color colour in colours) {
ToolStripMenuItem item = new ToolStripMenuItem();
Bitmap swatch = new Bitmap(64, 64);
using (Graphics g = Graphics.FromImage(swatch))
using (SolidBrush b = new SolidBrush(colour)) {
g.FillRectangle(b, 0, 0, 64, 64);
}
item.Image = swatch;
item.DisplayStyle = ToolStripItemDisplayStyle.Image;
item.Margin = new Padding(2, 2, 2, 2);
drop_down.Items.Add(item);
}
}
private void ShowColorMenu(Point screen_location)
{
ContextMenuStrip context_menu = new ContextMenuStrip();
// The root context menu will not layout as a grid
FillDropDown(context_menu);
// This sub-menu will not layout as a grid
ToolStripMenuItem sub_menu = new ToolStripMenuItem("Sub-menu");
FillDropDown(sub_menu.DropDown);
context_menu.Items.Add(sub_menu);
// A sub-menu will layout as a grid if we create a new ToolStripDropDown for it
ToolStripMenuItem grid_sub_menu = new ToolStripMenuItem("Grid Sub-menu");
ToolStripDropDown new_drop_down = new ToolStripDropDown();
FillDropDown(new_drop_down);
grid_sub_menu.DropDown = new_drop_down;
context_menu.Items.Add(grid_sub_menu);
context_menu.Show(screen_location);
}
在我的机器上结果如下:
我想在上下文菜单的根目录中有一个图像网格。理解它为什么会这样也很好。我查看了 .NET 参考源,但这对这次没有帮助。
ContextMenuStrip cannot show its ToolStripMenuItems in a Table layout, because of a limitation in Menu presentation/layout and you also cannot cast ContextMenuStrip to ToolStripDropDown (or the other way around; it's a wrapper around ToolStripDropDownMenu,它不能转换到它的间接祖先:它将保留其特定功能(例如,您可以查看 TextBox 和 ListBox 都为 Control
,但这并不意味着,现在,设置 ListBox 的 Text 实际上会在某处显示文本,只是因为 Text 属性 属于控件 class).
但是您可以像使用 ContextMenuStrip 一样直接使用和显示 ToolStripDropDown。完全支持 ToolStripDropDown 的 LayoutSettings can be cast directly to TableLayoutSettings and a LayoutStyle of type ToolStripLayoutStyle.Table。
在示例中,包含以 Table 布局排列的 ToolStripMenuItem 的 ToolStripDropDown 对象用作 ContextMenuStrip 以 select 彩色图像应用于 PictureBox 控件,而 Color名称显示在 Label 控件中。
下拉菜单在窗体初始化时创建,在窗体的 ClientArea 中单击鼠标右键显示,在窗体关闭时删除:
Note1:在这里,我使用 Lambda 来订阅 ToolStripDropDown.ItemClicked
事件。但是,对于这种类型的控件,最好改用方法委托。
注2:ToolStripDropDown 处理调用contextColorMenu.Dispose();
。如果频繁打开和关闭容器窗体,显式处理 ToolStripMenuItems Images 可能会更好。
using System.Drawing;
using System.Windows.Forms;
public partial class SomeForm : Form
{
private ToolStripDropDown contextColorMenu = null;
public SomeForm()
{
InitializeComponent();
contextColorMenu = new ToolStripDropDown();
contextColorMenu.ItemClicked += (o, a) => {
// Assign the selected Bitmap to a PitureBox.Image
picColor.Image = a.ClickedItem.Image;
// Show the Color description in a Label
lblColor.Text = ((Color)a.ClickedItem.Tag).ToString();
};
FillDropDown(contextColorMenu);
}
private void ShowColorMenu(Point location) => contextColorMenu.Show(location);
private void FillDropDown(ToolStripDropDown dropDown)
{
dropDown.LayoutStyle = ToolStripLayoutStyle.Table;
(dropDown.LayoutSettings as TableLayoutSettings).ColumnCount = 2;
(dropDown.LayoutSettings as TableLayoutSettings).GrowStyle = TableLayoutPanelGrowStyle.AddRows;
Color[] colors = { Color.Red, Color.Orange, Color.Yellow, Color.Green, Color.Blue, Color.Purple };
foreach (Color color in colors) {
var swatch = new Bitmap(64, 64);
using (var g = Graphics.FromImage(swatch)) {
g.Clear(color);
}
var item = new ToolStripMenuItem() {
DisplayStyle = ToolStripItemDisplayStyle.Image,
Image = swatch,
Tag = color,
Margin = new Padding(2),
Padding = new Padding(2, 1, 2, 1) // Fine tune the Items' Cell border
};
dropDown.Items.Add(item);
}
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Right) {
ShowColorMenu(MousePosition);
}
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
contextColorMenu?.Dispose();
}
}