我知道可以将图像添加到 aToolStripMenuItem
中,例如下图中的“关闭所有文档”项:
但是,我想要实现的是这样的:
也就是将图像放在项目文本的一侧,但不重叠检查空间。我搜索了一下,但找不到可以执行此操作的 Winforms 控件。你能指点我吗?还是我必须自己实现?谢谢你。
编辑:谢谢大家的回答!我会在周末后接受一份。
您必须使用一些自定义绘画。有一些方法可以实现这一点,但是我想介绍使用一些自定义ToolStripRenderer
的 . 下面只是一个演示代码,大家可以自己改进。为方便起见,我将每个内部图像保存在相应的项目Tag
中:
public class CustomRenderer : ToolStripProfessionalRenderer
{
int innerImagePadding = 2;
protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e) {
Image img = e.Item.Tag as Image;
if(img == null) base.OnRenderItemText(e);
else {
e.Graphics.DrawImage(img, e.Item.ContentRectangle.Left + e.Item.Bounds.Height + innerImagePadding,
e.Item.ContentRectangle.Top + innerImagePadding,
Math.Max(1, e.Item.ContentRectangle.Height - innerImagePadding*2),
Math.Max(1, e.Item.ContentRectangle.Height - innerImagePadding*2));
Rectangle textRect = new Rectangle(e.Item.ContentRectangle.Left + e.Item.Bounds.Height*2,
e.Item.ContentRectangle.Top +1,
e.TextRectangle.Width,
e.TextRectangle.Height);
e.Graphics.DrawString(e.Text, e.TextFont, new SolidBrush(e.TextColor), textRect);
}
}
}
//Usage
ContextMenuStrip cm = new ContextMenuStrip();
cm.Items.Add(new ToolStripMenuItem("Clear all", myImage) {Tag = myImage});
cm.Items.Add(new ToolStripMenuItem("Remove all", myImage){Tag = myImage});
this.ContextMenuStrip = cm; //set the ContextMenuStrip for the form
//set the custom Renderer
cm.Renderer = new CustomRenderer();
您不能从设计器中执行此操作,但您可以通过将父 DropDown 属性转换为 ToolStripDownDownMenu 项来访问 Show 属性来显示额外的边距:
public Form1() {
InitializeComponent();
((ToolStripDropDownMenu)FileMenuItem.DropDown).ShowCheckMargin = true;
((ToolStripDropDownMenu)FileMenuItem.DropDown).ShowImageMargin = true;
}
结果:
paint
您可以使用事件在控件的任何位置绘制任何内容。例如 -
void myToolStripMenuItem1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(Image.FromFile("open_icon.jpg"), 0, 0);
}
这会将图像置于 (0,0) 位置。你可以把它放在你想要的任何地方。
标准 .NET API 中没有具有此功能的控件,因此您必须自己编写它作为新功能。
但是,根据您希望使用此“新”功能的频率,可能会有有效的方法来实现它。我认为可以巧妙地工作的一种解决方案是利用这些图像具有固定大小的事实,并相应地缩进文本。
考虑如下方法:
using System.Drawing;
const string MENU_TEXT_INDENT = " ";
private void MenuItemWithImage_Paint(Object sender, PaintEventArgs e) {
ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
if (!menuItem.Text.StartsWith(MENU_TEXT_INDENT)) {
menuItem.Text = menuItem.Text.Insert(0, MENU_TEXT_INDENT);
}
Image img = menuItem.Image;
e.Graphics.DrawImage(img, new Point(0, 0));
menuItem.Refresh(); // May be needed to reflect changes - try without though!
}
如果然后将此事件处理程序附加到Paint
每个菜单项的事件,并以这种方式呈现图像,这应该可以工作。(您可能需要更多或更少的空间 - 我自己没有测试过)