views:

37

answers:

2

My form has a group box which contains two overlapping rectangles. The form's other controls are two sets of four numeric up down controls to set the rectangles' colors. (nudF1,2,3 and 4 set the rectangle that's in front, and nudB1,2,3 and 4 set the rectangle that's behind.) Everything works fine, except that the rectangles do not display the colors set in the numeric up downs when the form first loads. The numeric up down controls' ChangeValue events all call the ShowColors() method. The form's Load event calls the csColorsForm_Load() method. Any suggestions?

namespace csColors
{
    public partial class csColorsForm : Form
    {
        public csColorsForm()
        {
            InitializeComponent();
        }

        private void csColorsForm_Load(object sender, EventArgs e)
        {
            this.BackColor = System.Drawing.Color.DarkBlue;
            SetColors(sender, e);
        }

        private void SetColors(object sender, EventArgs e)
        {
            Control control = (Control)sender;
            String ctrlName = control.Name;
            Graphics objGraphics;
            Rectangle rect1, rect2;
            int colorBack, colorFore;
            objGraphics = this.grpColor.CreateGraphics();
            // If calling control is not a forecolor control, paint backcolor rectangle
            if (ctrlName.Substring(0,4)!="nudF")
            {
                colorBack = int.Parse(SetColorsB("nudB"), NumberStyles.HexNumber);
                SolidBrush BrushB = new SolidBrush(Color.FromArgb(colorBack));
                rect1 = new Rectangle(this.grpColor.Left, this.grpColor.Top,
                    this.grpColor.Width, this.grpColor.Height);
                objGraphics.FillRectangle(BrushB, rect1);
            }
            // Always paint forecolor rectangle
            colorFore = int.Parse(SetColorsB("nudF"), NumberStyles.HexNumber);
            SolidBrush BrushF = new SolidBrush(Color.FromArgb(colorFore));
            rect2 = new Rectangle(this.grpColor.Left, this.grpColor.Top,
                this.grpColor.Width, this.grpColor.Height);
            objGraphics.FillRectangle(BrushF, rect2);
            objGraphics.Dispose();
        }

        private string SetColorsB(string nam)
        {
            string txt="";
            for (int n = 1; n <= 4; ++n)
            {
                var ud = Controls[nam + n] as NumericUpDown;
                int hex = (int)ud.Value;
                txt += hex.ToString("X2");
            }
            return txt;
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

    }
}
+2  A: 

I suspect that painting in the Load event is a little premature. Try painting in the Paint event.

Or:

Could you just use a couple of Panel controls, and set their background colors?

Richard Ev
Thanks for your reply. Using the Paint event instead of the Load event doesn't help.
Jimmy
+1  A: 

A group box, like any control, will paint itself when Windows sends it the WM_PAINT message. You can indeed use Control.CreateGraphics() to draw yourself, bypassing the normal paint logic. But that's not going to last and will randomly disappear when Windows decides that the control needs to repaint itself again. Which is obvious when you minimize the form and restore it. Less obvious on Vista and Win7 with Aero enabled, repaints are not necessary when your form is overlapped by another window. But it will be quite obvious on XP or with Aero disabled.

You cannot make this work reliably, you have to use the Paint event. Not your form's, the group box controls'. Call its Invalidate() method to force it to repaint when the color changes.

Hans Passant
Hans, you da man! Putting This.Invalidate() in the groupbox's paint method didn't work for me. However, calling SetColors() in the groupbox's paint method did the trick. Many thanks.
Jimmy