John Demetriou John Demetriou - 14 days ago 6
C# Question

How to add Back and Fore Color on ContextMenu

I am Showing a

ContextMenu
whenever the user right clicks on a specific location in a
DataGridView
.
I want the items of that
ContextMenu
to have a back color and fore color depending on their content.

How can I do this since
ContextMenu
has no back color or Fore color property?
I tried looking up
ContextMenuStrip
but this has to be connected to a
ToolStripButton
which I do not have and do not want.

Answer

In order to change the back color of a MenuItem you need to specify a draw item handler and set owner-draw to true for each item. Also for the color to actually take some space you need to implement a MeasureMenuItem handler. So for example

                color.MenuItems.Add(new MenuItem("#123456", menuHandler));
                color.MenuItems.Add(new MenuItem("Green", menuHandler));
                color.MenuItems.Add(new MenuItem("Red", menuHandler));
                foreach (MenuItem item in color.MenuItems)
                {
                    item.OwnerDraw = true;
                    item.DrawItem += item_DrawItem;
                    item.MeasureItem += MeasureMenuItem;
                }

The above codes hooks up the items and their handlers.

void item_DrawItem(object sender, DrawItemEventArgs e)
        {
            MenuItem cmb = sender as MenuItem;
            string color = SystemColors.Window.ToString();
            if (e.Index > -1)
            {
                color = cmb.Text;
            }
            if (checkHtmlColor(color))
            {

                e.DrawBackground();
                e.Graphics.FillRectangle(new SolidBrush(ColorTranslator.FromHtml(color)), e.Bounds);

                e.Graphics.DrawString(color, new Font("Lucida Sans", 10), new SolidBrush(ColorTranslator.FromHtml(color)), e.Bounds);

            }
        }

The above code takes the MenuItem contents, converts it to a color, creates a rectangle for that color and draws it.

   void MeasureMenuItem(object sender, MeasureItemEventArgs e)
        {
            MenuItem m = (MenuItem)sender;
            Font font = new Font(Font.FontFamily, Font.Size, Font.Style);
            SizeF sze = e.Graphics.MeasureString(m.Text, font);
            e.ItemHeight = (int)sze.Height;
            e.ItemWidth = (int)sze.Width;
        }

And lastly the above few lines simply measure the area the MenuItem should take before drawing (basically measures the space of it's string content) so the draw_item handler knows how much space to take up

Comments