1

I am tampering with ToolStrip modifications as of now and is trying to make the submenu also transparent like the MenuStrip. I can't manage to make the submenu's property to be like the menu itself.

How do I do that?

Here's my code for the modifications:

    public class ArrowRenderer : ToolStripProfessionalRenderer
    {
        public ArrowRenderer() : base(new LeftMenuColorTable())
        {

        }
        protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
        {
            var tsMenuItem = e.Item as ToolStripMenuItem;
            if (tsMenuItem != null)
                e.TextColor = Color.White;
            base.OnRenderItemText(e);
        }

        protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
        {
            var tsMenuItem = e.Item as ToolStripMenuItem;
            if (tsMenuItem != null)
                e.ArrowColor = Color.White;
            base.OnRenderArrow(e);
        }
        protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
        {
            var tsMenuItem = e.Item as ToolStripMenuItem;
            if (tsMenuItem != null)
                e.Item.BackColor = Color.Black;
            base.OnRenderMenuItemBackground(e);
        }
    }
    public class LeftMenuColorTable : ProfessionalColorTable
    { 
        public override Color MenuItemSelected
        {
            // when the menu is selected
            get { return ColorTranslator.FromHtml("#494f52");  }
        }

        public override Color ToolStripBorder
        {
            get { return ColorTranslator.FromHtml("#FFFFFF"); }
        }
        public override Color ToolStripDropDownBackground
        {
            get { return Color.White; }
        }
    }

    internal void SetTrayMenu()
    {
        if (m_menu != null)
            if (notifyIcon.ContextMenuStrip != null)
                notifyIcon.ContextMenuStrip.Refresh();

        m_menu = new ContextMenuStrip();
        m_menu.Renderer = new ArrowRenderer();
        m_menu.AllowTransparency = true;
        m_menu.Opacity = 0.8;

        m_menu.BackColor = Color.Black;
}

enter image description here

TerribleDog
  • 1,237
  • 1
  • 8
  • 31

1 Answers1

2

Because the ToolStripDropDownMenu that hosts/lists the sub items or DropDownItems is not the same object that the ContextMenuStrip inherits. Hence you need to apply the same settings for each sub menu or DropDown.

The SetTrayMenu() should do:

internal void SetTrayMenu()
{
    if (m_menu != null && notifyIcon.ContextMenuStrip != null)
        //Why?
        notifyIcon.ContextMenuStrip.Refresh();
    else
    {
        m_menu = new ContextMenuStrip
        {
            Renderer = new ArrowRenderer(),
            AllowTransparency = true,
            Opacity = 0.8,
        };

        foreach (var dd in m_menu.Items.OfType<ToolStripMenuItem>()
            .Where(x => x.HasDropDown))
        {
            var ddm = dd.DropDown as ToolStripDropDownMenu;

            if (ddm != null)
            {
                ddm.AllowTransparency = true;
                ddm.Opacity = 0.8;
            }
        }

        m_menu.BackColor = Color.Black;
    }
}

Before

SOQ61911652A

After

SOQ61911652

Note: Opacity = 0.5 here.

  • 1
    Thank you for the answer. But how do I change the border color of the sub-menus? – TerribleDog May 21 '20 at 08:19
  • 1
    @TerribleDog Most welcome buddy. To you need to override the `MenuBorder` as well in the `LeftMenuColorTable` class. e.g. `public override Color MenuBorder => ColorTranslator.FromHtml("#FFFFFF");` –  May 21 '20 at 08:36
  • 1
    @TerribleDog No it will change. just set another color like `Color.Red` to see. As for the `ToolStripSeparator`, yes it ignores the back color. You need to derive a new class from it and override the `OnPaint` method instead. Check [this](https://stackoverflow.com/a/31093769/10216583) out. Also you can derive a new class from `ToolStripMenuItem` to draw something better. I've published something like [this](https://github.com/q8soft/WinFrmSkins.NYX/blob/master/src/NYX/NYXToolStripSeparator.vb) in this context. Its VB.NET though. I believe you can manage that :) –  May 21 '20 at 09:28
  • Yes, thank you for it, I had overlapping codes that prevented the change but there is one more question, https://imgur.com/a/ZhPU2gj How do I remove the border on the left side? – TerribleDog May 21 '20 at 09:34
  • 1
    @TerribleDog This requires overriding the `OnRenderToolStripBorder` method in the `ArrowRenderer` class to check which type of `e.ToolStrip` and draw the `e.AffectedBounds` accordingly. e.g. `if (e.ToolStrip is ContextMenuStrip) { //draw the border }; else if (e.ToolStrip is ToolStripDropDownMenu) { }; else base.OnRenderToolStripBorder(e);` and forget overriding the `MenuBorder` property as I mentioned above. You might need to reduce both the width and height of `e.AffectedBounds` rectangle by 1. –  May 21 '20 at 09:52
  • 1
    I did this using ImageMarginGradientBegin. Thanks so much – TerribleDog May 21 '20 at 10:02
  • 1
    @TerribleDog Welcome bud. Anytime. –  May 21 '20 at 10:13