tags:

views:

669

answers:

3

My Windows Forms application has a MenuStrip and some of the menu items (ToolStripMenuItem) have an icon (setting the ToolStripMenuItem.Image property).

When the RenderMode property of the MenuStrip is set to ToolStripRenderMode.System, the checkmark doesn't display when the Checked or CheckOnClick property is true and the menu item has an icon.

It does display when i switch the MenuStrip.RenderMode property to ToolStripRenderMode.Professional or ToolStripRenderMode.RenderManagerMode.

Unfortunately, this is a problem because my app requires:

  1. A ProgressBar in marquee mode, so Application.EnableVisualStyles() is required to get this to work.
  2. The app requires a "flat" visual style, which i accomplished by leaving out the call to Application.EnableVisualStyles() and leaving the default ToolStripRenderMode.RenderManagerMode on the MenuStrip. But then i can't get my marquee ProgressBar!
  3. Setting the RenderMode to ToolStripRenderMode.System solves the look and feel requirement, but takes away the ability to have checked menu items w/icons.

Is there any way to satisfy all my requirements? Am i missing something? Thanks for looking.

A: 

Wow, i stumped SO! Now i know i must be working on some serious code.

Anyway, the answer is: implement your own ToolStripRenderer by creating a class that inherits from ToolStripSystemRenderer.

Override the methods that draw the items with your own code. Here's what i was looking for specifically that draws the checked item. It draws a check if there's no image for the ToolStripMenuItem.

protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e)
{
    base.OnRenderItemCheck(e);
    if (e.Item.Selected)
    {
        Rectangle rect = new Rectangle(3, 1, 20, 20);
        Rectangle rect2 = new Rectangle(4, 2, 18, 18);
        SolidBrush b = new SolidBrush(Color.FromArgb(49, 106, 197));
        SolidBrush b2 = new SolidBrush(Color.Orange);

        e.Graphics.FillRectangle(b, rect);
        e.Graphics.FillRectangle(b2, rect2);
        e.Graphics.DrawImage(e.Image, new Point(5, 3));
    }
    else
    {
        Rectangle rect = new Rectangle(3, 1, 20, 20);
        Rectangle rect2 = new Rectangle(4, 2, 18, 18);
        SolidBrush b = new SolidBrush(Color.FromArgb(49, 106, 197));
        SolidBrush b2 = new SolidBrush(Color.Orange);

        e.Graphics.FillRectangle(b, rect);
        e.Graphics.FillRectangle(b2, rect2);
        e.Graphics.DrawImage(e.Image, new Point(5, 3));
    }
}
Matt
A: 

I don't see any difference in your else block?

A: 

I did also come across a simpler alternative:

You can simply put your menu items into a ContextMenuStrip and then assign it to the DropDown property of the DropDownButton.

Hope this helps anyone out there who doesn't fancy overriding the Paint method.

Andy Blackman