none
How can i color the last item in a ContextMenu once without re drawing it over again with the mouse cursor ? RRS feed

  • Question

  • This is a working method and events that color the last item in a ContextMenu in red:

    private void dataGridView1_MouseClick(object sender, MouseEventArgs e)
            {
                if (e.Button == MouseButtons.Right)
                {
                    ContextMenu m = new ContextMenu();
    
                    m.MenuItems.Add(new MenuItem("Cut"));
                    m.MenuItems.Add(new MenuItem("Copy"));
                    m.MenuItems.Add(new MenuItem("Paste"));
    
                    int currentMouseOverRow = dataGridView1.HitTest(e.X, e.Y).RowIndex;
    
                    if (currentMouseOverRow >= 0)
                    {
                        
                        m.MenuItems.Add(new MenuItem(string.Format("Row number {0}", currentMouseOverRow.ToString())));
                        m.MenuItems[m.MenuItems.Count - 1].OwnerDraw = true;
                        m.MenuItems[m.MenuItems.Count - 1].DrawItem += Cm_DrawItem;
                        m.MenuItems[m.MenuItems.Count - 1].MeasureItem += MeasureMenuItem;
                    }
    
                    m.Show(dataGridView1, new Point(e.X, e.Y));
    
                }
            }

    And the Cm_DrawItem event:

    void Cm_DrawItem(object sender, DrawItemEventArgs e)
            {
                var item = (MenuItem)sender;
                var g = e.Graphics;
                var font = new Font("Arial", 10, FontStyle.Italic);
                var brush = new SolidBrush(System.Drawing.Color.Red);
                g.DrawString(item.Text, font, brush, e.Bounds.X, e.Bounds.Y);
            }


    And the MeasureMenuItem event:

    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;
            }

    It's drawing the text in Red for example: Row  number 9

    So the line: Row number 9 is in Red.

    Thep roblem is that if/when i move the mouse cursor over this last item in the contextmenu it will keep drawing it over and over again in Red. How can i avoid it from happen ?

    I tried to use TextRenderer.DrawTex like this:

    void Cm_DrawItem(object sender, DrawItemEventArgs e)
            {
                var item = (MenuItem)sender;
                var g = e.Graphics;
                var font = new Font("Arial", 10, FontStyle.Italic);
                var brush = new SolidBrush(System.Drawing.Color.Red);
                g.DrawString(item.Text, font, brush, e.Bounds.X, e.Bounds.Y);
                TextRenderer.DrawText(g, item.Text, this.Font,
                    new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height)
                    , System.Drawing.Color.Red, System.Drawing.Color.Red);
            }

    But it didn't help.

    How can i avoid from moving the mouse cursor over the last item in the contextmenu and it will keep drawing it ?

    This is an image of how the colored item look like in the first time:

    And this is how it look like after moving the mouse cursor over this item over and over again:


    Saturday, June 7, 2014 9:24 PM

Answers

  • You have to call e.DrawBackground(); at the beginning of the Cm_DrawItem method.

    Create a custom menu item derive from MenuItem and set the back color to SystemColor.Control

    public class CustomMenuItem : MenuItem
    {
        public CustomMenuItem(string text) : base(text)
        {
            
        }
    
        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            base.OnDrawItem(new DrawItemEventArgs(e.Graphics, e.Font, e.Bounds, e.Index, e.State, e.ForeColor, SystemColors.Control));
        }
    }
    

    Add CustomMenuItem to MenuItems collection

    private void dataGridView1_MouseClick(object sender, MouseEventArgs e)
    {
        ...
    
            if (currentMouseOverRow >= 0)
            {
                m.MenuItems.Add(new CustomMenuItem(string.Format("Row number {0}", currentMouseOverRow)));
        ...
            }
    

    You'd better dispose the font and the brush, or use the static Brushes.Red property.

    void Cm_DrawItem(object sender, DrawItemEventArgs e)
    {
        e.DrawBackground();
        var item = (MenuItem)sender;
        var g = e.Graphics;
        var font = new Font("Arial", 10, FontStyle.Italic);
        var brush = Brushes.Red;
        g.DrawString(item.Text, font, brush, e.Bounds.X, e.Bounds.Y);
        font.Dispose();
    }
    

    Best regards

    • Marked as answer by Chocolade1972 Tuesday, June 10, 2014 6:24 PM
    Tuesday, June 10, 2014 4:30 PM
    Moderator

All replies

  • Hi Chocolade1972,

    Do you mean the red color is deeper than before which means it is drawing over and over again?

    We need to know which event caused your issue so please insert breakpoints to check some details. For example, you can use breakpoints to see which event is loop when you move your mouse to the last item in a ContextMenu.

    Regards,



    Barry Wang
    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Tuesday, June 10, 2014 6:42 AM
    Moderator
  • Barry Hi,

    Yes you right it's getting deeper Red since it keep drawing it over and over again.

    I found that each time i make right click on the same cell/item it keep register again to the draw and measure events. And since it register it over and over again when i make right click mouse on same cell/item it will enter the events will draw it again just like in the first time.

    same thing when i move the mouse over it. I can't use breakpoint when i move the mouse over it since the menu when i make right click is gone when i use a break point. 

    I don't have any mouse move event but for some reason when i move just move the mouse over the menu the contextmenu it keep register the events and enter the events and redraw over it and make it deeper.

    I need some how to check that it was registered once for the current menu item:

    m.MenuItems[m.MenuItems.Count - 1]

    And current e.X and e.Y maybe so it wont register again on this places.

    The main problem is that it keep register the events when i move the mouse over the last item or make another right click on same place e.X e.Y 


    Tuesday, June 10, 2014 12:59 PM
  • You have to call e.DrawBackground(); at the beginning of the Cm_DrawItem method.

    Create a custom menu item derive from MenuItem and set the back color to SystemColor.Control

    public class CustomMenuItem : MenuItem
    {
        public CustomMenuItem(string text) : base(text)
        {
            
        }
    
        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            base.OnDrawItem(new DrawItemEventArgs(e.Graphics, e.Font, e.Bounds, e.Index, e.State, e.ForeColor, SystemColors.Control));
        }
    }
    

    Add CustomMenuItem to MenuItems collection

    private void dataGridView1_MouseClick(object sender, MouseEventArgs e)
    {
        ...
    
            if (currentMouseOverRow >= 0)
            {
                m.MenuItems.Add(new CustomMenuItem(string.Format("Row number {0}", currentMouseOverRow)));
        ...
            }
    

    You'd better dispose the font and the brush, or use the static Brushes.Red property.

    void Cm_DrawItem(object sender, DrawItemEventArgs e)
    {
        e.DrawBackground();
        var item = (MenuItem)sender;
        var g = e.Graphics;
        var font = new Font("Arial", 10, FontStyle.Italic);
        var brush = Brushes.Red;
        g.DrawString(item.Text, font, brush, e.Bounds.X, e.Bounds.Y);
        font.Dispose();
    }
    

    Best regards

    • Marked as answer by Chocolade1972 Tuesday, June 10, 2014 6:24 PM
    Tuesday, June 10, 2014 4:30 PM
    Moderator