C# ToolStripProfessionalRender, event OnRenderItemText applied only on the first item

246 Views Asked by At

I'm drawing a custom toolstrip using ToolStripProfessionalRender and editing the OnRenderItemText event as follows:

protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
{
    e.Item.ForeColor = Clr.White;
    e.Item.TextAlign = ContentAlignment.MiddleLeft;
    e.Item.Alignment = ToolStripItemAlignment.Left;
    base.OnRenderItemText(e);
    if (e.Item.GetType() == typeof(ToolStripDropDownButton))
    {
        ToolStripDropDownButton tsmi = (ToolStripDropDownButton)e.Item;
        if (tsmi.HasDropDownItems && tsmi.OwnerItem == null)
        {
            Rectangle bounds = tsmi.Bounds;
            bounds.X = bounds.Right - 25;
            bounds.Width = 25;
            bounds.Y = 10;

            // Draw the corner
            Graphics G = e.Graphics;
            SolidBrush brushw = new SolidBrush(Color.FromArgb(70,70,70));
            Point[] points =
            {
                new Point(bounds.Right - 3, bounds.Height - 11), // point top right
                new Point(bounds.Right - 3, bounds.Bottom - 14), // point bottom right
                new Point(bounds.Right - 10, bounds.Bottom - 14) // point bottom left

            };
            G.FillPolygon(brushw, points);
        }
    }
}

and basically the output i'm trying to obtain is the following: enter image description here

So drawing a little triangle on the bottom right corner when i got a ToolStripDropDownButton. The problem is that the little triangle is drawn only first item.

To end up the question i draw this toolstrip dynamically using a function that adds a dropdownbutton at each call.

ToolStripDropDownButton m_Item = new ToolStripDropDownButton(text, image);
                        m_Item.ImageAlign = ContentAlignment.MiddleCenter;
                        m_Item.ImageScaling = ToolStripItemImageScaling.None;
                        m_Item.Name = name;
                        m_Item.ForeColor = Color.White;
                        m_Item.BackColor = Color.FromArgb(95, 95, 95);
                        m_Item.Padding = new Padding(5);
                        m_Item.ShowDropDownArrow = false;
                        m_Item.Paint += new PaintEventHandler(this.PaintButtonBorder);
                        if (tabPage != null)
                            m_Item.Click += (sender, e) => AddClickTab(sender, e, tabPage);
                        ((ToolStripDropDownMenu)m_Item.DropDown).ShowImageMargin = false;
                        ((ToolStripDropDownMenu)m_Item.DropDown).ShowCheckMargin = false;
                        ((ToolStripDropDownMenu)m_Item.DropDown).Cursor = Cursors.Hand;
                        toolStrip1.Items.Add(m_Item);

                        if (SubItems != null)
                        {
                            for(int i = 0; i < SubItems.Length; i++)
                            {
                                object[] subitem = (object[])SubItems[i];
                                FnAddToolStripMenuItem(
                                    subitem[0].ToString(),
                                    subitem[1].ToString(),
                                    (Bitmap)subitem[2],
                                    m_Item,
                                    (TabPage)subitem[3]
                                    );
                            }
                        }

Am i missing some "new" maybe?

1

There are 1 best solutions below

1
dr.null On BEST ANSWER

Override the OnRenderItemText method only to draw the text part as it says, and/or to set the default properties used when rendering the text. To change the look and the shape of the arrows of the dropdown items, override the OnRenderArrow method.

Example

using System.Drawing;
using System.Drawing.Drawing2D;

protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
{
    // Optional: to be the default color of the arrows.
    e.ArrowColor = Color.FromArgb(70, 70, 70);

    if (e.Item is ToolStripDropDownButton item && item.OwnerItem == null)
    {
        var g = e.Graphics;
        var r = new Rectangle(item.Bounds.Width - 10, item.Bounds.Height - 10, 8, 8);

        g.SmoothingMode = SmoothingMode.AntiAlias;
        g.PixelOffsetMode = PixelOffsetMode.Half;

        using (var br = new SolidBrush(e.ArrowColor))
            g.FillPolygon(br, new[]
            {
                new Point(r.Left, r.Bottom),
                new Point(r.Right, r.Top),
                new Point(r.Right, r.Bottom)
            });

        g.SmoothingMode = SmoothingMode.None;
        g.PixelOffsetMode = PixelOffsetMode.Default;
    }
    else
        base.OnRenderArrow(e);
}

protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
{
    e.Item.ForeColor = Color.White;
    e.Item.TextAlign = ContentAlignment.MiddleLeft;
    e.Item.Alignment = ToolStripItemAlignment.Left;
    base.OnRenderItemText(e);
}

Make sure to enable the ShowDropDownArrow property of the dropdown buttons. So comment this m_Item.ShowDropDownArrow = false;.

If you are also interested to change the color according to the current state of the dropdown button (Selected, Pressed), then you can do for example:

using (var br = new SolidBrush(item.Selected 
    ? Color.FromArgb(150, 150, 150) : item.Pressed 
    ? Color.FromArgb(100, 100, 100) :
      Color.FromArgb(70, 70, 70)))
    //...