Link to home
Start Free TrialLog in
Avatar of LastUntakenName
LastUntakenName

asked on

Artifact created with LinearGradientBrush and FillRectangle

I am trying to create a symmetric gradient background for a panel - or any other paintable object. The following code works for the most part. However, as I change the form size, occasionally a line of the other-end color appears in the middle. This artifact appears consistently at the same form heights. The actual artifact is part of the bitmap. I know because I saved the bitmap several times, all coinciding with the form's artifact or lack thereof. Any help would be appreciated.

The form simply has a panel (panel1) docked to the right.
private void GradientFill(Control paintedObject, Color firstColor, Color secondColor, LinearGradientMode linearGradientMode, bool symmetric) {
            int width = paintedObject.Width;
            int height = paintedObject.Height;
            Bitmap bmp = new Bitmap(width, height);
            Graphics g = Graphics.FromImage(bmp);
            if (symmetric) {
                int widthHalf = width / 2;
                int heightHalf = height / 2;
                Rectangle firstBrushRectangle;
                Rectangle firstFillRectangle;
                Rectangle secondBrushRectangle;
                Rectangle secondFillRectangle;
                if (linearGradientMode == LinearGradientMode.Vertical) {
                    firstBrushRectangle = new Rectangle(0, 0, width, heightHalf);
                    firstFillRectangle = new Rectangle(0, 0, width, heightHalf);
                    secondBrushRectangle = new Rectangle(0, heightHalf, width, height - heightHalf);
                    secondFillRectangle = new Rectangle(0, heightHalf, width, height - heightHalf);
                } else {
                    firstBrushRectangle = new Rectangle(0, 0, widthHalf, height);
                    firstFillRectangle = new Rectangle(0, 0, widthHalf, height);
                    secondBrushRectangle = new Rectangle(widthHalf, 0, width - widthHalf, height);
                    secondFillRectangle = new Rectangle(widthHalf, 0, width - widthHalf, height);
                }
                LinearGradientBrush firstGradientBrush = new LinearGradientBrush(firstBrushRectangle, firstColor, secondColor, linearGradientMode);
                LinearGradientBrush secondGradientBrush = new LinearGradientBrush(secondBrushRectangle, secondColor, firstColor, linearGradientMode);
                g.FillRectangle(firstGradientBrush, firstFillRectangle);
                g.FillRectangle(secondGradientBrush, secondFillRectangle);
            } else {
                Rectangle baseRectangle = new Rectangle(0, 0, width, height);
                LinearGradientBrush gradientBrush = new LinearGradientBrush(baseRectangle, firstColor, secondColor, linearGradientMode);
                g.FillRectangle(gradientBrush, baseRectangle);
            }
            paintedObject.BackgroundImage = bmp;
        }
 
        private void panel1_Resize(object sender, EventArgs e) {
            GradientFill((Control)sender, Color.BlueViolet, Color.LimeGreen, LinearGradientMode.Vertical, true);
            textBox1.Text = panel1.Height.ToString();
        }

Open in new window

Avatar of rachitkohli
rachitkohli
Flag of India image

Try following suggestion :
Create the Bitmap only once, may be on the form load or somewhere else.
Keep the painting job done in Paint Event. Could be of Form Paint event.
And use the graphics object from the paint event argument. i.e. e.graphics
Avatar of LastUntakenName
LastUntakenName

ASKER

Thank you rachitkohli.

I tried creating the bitmap only once. It didn't work; the width and height are read-only properties, and they must change as the form's width or height change. I tried putting the job in the paint event, but that just added flicker. The use of the paint event argument, e, did not help either.

I chose to run the method only during a resize, because all I want to do is change the background image at that time. Since I am setting it to an independent bitmap, there should be no need to create the bitmap with the paint event argument.

The problem is with the bitmap creation. I ran this method (modified to return a bitmap) on a picturebox with its width/height controlled by a numericupdown control. The problem still occurred.

I have discovered that the problem lies within the second rectangle. I temporarily disabled each rectangle, one at a time. The problem occurs only with the second one. I shifted the rectangle up, which did not make any difference.
If you wish to modify the Image dimensions on form resize, than instead of creating the image on every resize, as i said earlier create it only once. On Form_Paint
e.Graphics.DrawImage(bitMapObject, 0,0,Width, Height)

In form properties you have a property called DoubleBuffer, make it TRUE. This may avoid flickering.
I can't create the bitmap only once. The width and height properties are read-only. Perhaps I am missing something?

The DoubleBuffer setting did not eliminate the flickering.

Regardless, the bitmap still is not being created correctly.
The problem is in the second rectangle.

It is probably easier to analyze the problem by running the code. The form just needs a right-docked panel.
ASKER CERTIFIED SOLUTION
Avatar of LastUntakenName
LastUntakenName

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial