如何将图像放置在ToolStripMenuItem(或类似控件)的文本旁边?

4
我知道可以像下图中“关闭所有文档”选项那样将图像添加到ToolStripMenuItem

Menu with some ToolStripMenuItems

但是,我想要实现的是这样的效果:

enter image description here

也就是将图像放置在项目文本的一侧,但不重叠检查空间。我搜索了一些资源,但找不到可以实现这一目标的 Winforms 控件。您能给我指点吗?还是说我必须自己实现它?谢谢。

编辑:感谢大家的回答!周末后我会接受一个。


我看不到任何选项。也许我错了。但你可以很容易地实现它。那不应该很难。 - Sriram Sakthivel
可能需要一个自定义渲染器。 - terrybozzio
4个回答

4

您需要使用一些自定义绘制。有几种实现方式,但我想介绍一下使用自定义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();

enter image description here


3

你无法在设计器中完成此操作,但你可以将父级DropDown属性转换为ToolStripDownDownMenu项,以访问Show属性并显示额外的边距:

public Form1() {
  InitializeComponent();
  ((ToolStripDropDownMenu)FileMenuItem.DropDown).ShowCheckMargin = true;
  ((ToolStripDropDownMenu)FileMenuItem.DropDown).ShowImageMargin = true;
}

结果:

在此输入图片描述

(注:该段内容为HTML代码,已保留标签并进行翻译)

我接受了这个答案,因为我可以在不写太多代码的情况下得到接近我想要的结果。 - elnigno

1
您可以使用paint事件在控件的任何位置绘制任何内容。例如 -
void myToolStripMenuItem1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawImage(Image.FromFile("open_icon.jpg"), 0, 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事件,则应该可以正常工作。(您可能需要更多或更少的空格-我自己没有测试过)

这篇与编程有关的内容需要翻译成中文。由于需要使用某些固定宽度字体,否则文字排版可能会出现问题,请只返回已翻译的文本内容。 - King King

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接