The Overrider
The Overrider

Reputation: 93

Custom Paint in ToolStripTextBox

i have a problem about custom Paint method in class that inherit from ToolStripTextBox. I need to draw an icon before ToolStripTextBox in ContextMenuStrip.

FIRST ATTEMPT:

 ContextMenuStrip CXstrip = new ContextMenuStrip();
 CXstrip.ImageList = [My defined list];
 var groupMenu = new ToolStripTextBox();
 groupMenu.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
 groupMenu.ImageIndex = 1;

Failed :( Only textBox will Appear.

SECOND ATTEMPT:

    public class ToolStripSpringTextBox : ToolStripTextBox {
      protected override void OnPaint(PaintEventArgs e) {
         e.Graphics.DrawLine(Pens.Red, 0, 0, 50, 10);
      }
   }

Paint is called, but he draw always standard textbox without my line (same of First Attempt)

My question is why i cannot draw manually? Why first (Logic) way to do this doesn't work like ToolStripMenuItem for example?

enter image description here Thanks.

Upvotes: 2

Views: 626

Answers (1)

dr.null
dr.null

Reputation: 4660

As a direct answer to your question, the ToolStripTextBox doesn't have in its inheritance tree the ToolStripMenuItem so you can't deal with it in the exact same way.

To assign images to items like ToolStripTextBox, ToolStripComboBox, and ToolStripDropDownItem:

  1. Override the hidden Image property and reverse the attributes to make it visible and accessible again. You will find it in the Properties window to assign an image. Or through the code.

  2. Override the OnParentChanged method to subscribe to the parent's Paint event. The type of the parent of both ContextMenuStrip and a MenuStrip drop down is ToolStripDropDownMenu.

  3. Define the rectangle of the image and draw it.

using System.ComponentModel;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Drawing;

[DesignerCategory("ToolStrip"),
ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.All)]
public class ToolStripSpringTextBox : ToolStripTextBox
{
    public ToolStripSpringTextBox() : base() { }

    /// <summary>
    /// The image that will be displayed on the item.
    /// </summary>
    [Browsable(true),
        EditorBrowsable(EditorBrowsableState.Always),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
        Category("Appearance"),
        Description("The image associated with the object.")]
    public override Image Image { get => base.Image; set => base.Image = value; }

    protected override void OnParentChanged(ToolStrip oldParent, ToolStrip newParent)
    {
        base.OnParentChanged(oldParent, newParent);

        if (newParent != null && newParent is ToolStripDropDownMenu)
        {
            newParent.Paint -= new PaintEventHandler(OnParentPaint);
            newParent.Paint += new PaintEventHandler(OnParentPaint);
        }

        if (oldParent != null)
            oldParent.Paint -= new PaintEventHandler(OnParentPaint);
    }

    private void OnParentPaint(object sender, PaintEventArgs e)
    {
        if (Image is null || 
            (sender is ContextMenuStrip cmnu &&
            !cmnu.ShowImageMargin && !cmnu.ShowCheckMargin))
            return;

        var sz = Image.Size;
        var r = new Rectangle((Bounds.X - sz.Width - 7) / 2,
            (Bounds.Height - sz.Height) / 2 + Bounds.Y, sz.Width, sz.Height);

        if (RightToLeft == RightToLeft.Yes)
            r.X = Bounds.Right + r.Width - ContentRectangle.X;

        e.Graphics.DrawImage(Image, r);
    }
}

MenuStrip MenuStrip2

Upvotes: 2

Related Questions