Link to home
Start Free TrialLog in
Avatar of carpbyte
carpbyte

asked on

Gradient bitmaps and the paint event

I have a form with the background image set to a gradient image. On the form is docked a splitcontainer with all of the appropriate backcolor properties set to color.transparent

Problem is that if I resize or change the orientation of the split, it appears as if the paint event fires numerous times. It also doesn't repaint the actual gradient region, but rather flashes multiple times in the main graident color.

So my question is, is there a way to foce or control the paint event so that any resizing, repainting, etc, appears seemless.

i've tried double buffering, suspend layout, setting the visible property, etc, to no avail - always flashes.

Note - if the form's back color is just set to a solid backcolor (no backimage) then refreshing/painting is pretty smotth. It's oly whne the background cointains an image that multiple redraws seem to rake place.

???

Thanks.
Avatar of 5thcav
5thcav
Flag of United States of America image

set a boolen when resizing to true and when the mouse up event fires then repaint
also when mouse down on the resizing set the background to stretch

hay,, just put your controls on a picturebox and the gradient will simple stretch..

i see that you posted a while ago,, i was searching to apply a gradient to a bmp ,,

maybe you can still use the help?
Avatar of carpbyte
carpbyte

ASKER

Thanks, but still no luck.

Same issue - whatever the control's backcolor is set to is what flashes.

A boolean won't work because there is NO code in the actual paint event - it's whatever the default "painting" that .NET uses is what seems to be causing the problem.

Carp

try this,,,,

Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.ResizeRedraw Or ControlStyles.UserPaint Or ControlStyles.OptimizedDoubleBuffer, True) : Me.UpdateStyles()


maybe set color.transparent to white during the drag?
Nope, same thing, flash of default backcolor.

I am having some luck with the following though, but it's been awhile so I've kind of forgotten what I was initially trying to do...need to redefine the problem...

Thanks for the comments.

Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)

    If Me.BackgroundImage Is Nothing Then
      If Not (Parent.BackgroundImage Is Nothing) Then
        e.Graphics.DrawImage(Parent.BackgroundImage, _
          New Rectangle(0, 0, Me.Width, Me.Height), _
          Me.Left, Me.Top, Me.Width, Me.Height, GraphicsUnit.Pixel)
      Else
        e.Graphics.FillRectangle(New SolidBrush(Parent.BackColor), _
        New Rectangle(0, 0, Me.Width, Me.Height))
      End If
    End If

    Dim attributes As New ImageAttributes

    Dim matrixElements As Single()() = { _
      New Single() {1.0F, 0.0F, 0.0F, 0.0F, 0.0F}, _
      New Single() {0.0F, 1.0F, 0.0F, 0.0F, 0.0F}, _
      New Single() {0.0F, 0.0F, 1.0F, 0.0F, 0.0F}, _
      New Single() {0.0F, 0.0F, 0.0F, CSng(_opacity), 0.0F}, _
      New Single() {0.0F, 0.0F, 0.0F, 0.0F, 1.0F}}

    Dim matrix As ColorMatrix
    matrix = New ColorMatrix(matrixElements)
    attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap)

    Dim bitmap As Bitmap = New Bitmap(Me.Width, Me.Height, PixelFormat.Format24bppRgb)
    Dim g As Graphics = Graphics.FromImage(bitmap)
    Dim brush As Brush = New SolidBrush(Me.BackColor)
    g.FillRectangle(brush, New RectangleF(0, 0, Me.Width, Me.Height))
    brush.Dispose()
    e.Graphics.DrawImage(bitmap, _
      New Rectangle(0, 0, Me.Width, Me.Height), _
      0, 0, Me.Width, Me.Height, GraphicsUnit.Pixel, attributes)

  End Sub
    just make a bmp from the code below and set the background to the image?
     set the picturebox or panel? background to stretch.

its going to flash if its in the onpaint event, maybe put your code into a timer event or resize event.

does painting during the onpaint event cause the onpaint event to fire? when you think of it this way
it sure shounds like i know what im doing! LOL

   Dim r As Rectangle
        Dim b As LinearGradientBrush
        r = New Rectangle(0, 0, Me.Width, Me.Height)
        b = New LinearGradientBrush(r, Color.Blue, Color.LightBlue, LinearGradientMode.Vertical)
        e.Graphics.FillRectangle(b, r)
picturebox image, not background
OK I Made a simple test app to show what the issue is without using a bitmap. The issue is the same.

I'm also bumping up the points because I really need to figure this out in VB.net

If you try the following, the Picture box will show the parent form's backcolor and NOT the gradient (which is what I want..)

Any help would be appreciated. I have a feeling I somehow need to grab the painted region from memory and work some API magic to get thsi to work.

Thanks.

Create a Form and set it's back color to Red

In the Load Event:

        Dim pic As New PictureBox
        pic.BackColor = Color.Transparent 'want the gradient to show through
        pic.BorderStyle = BorderStyle.FixedSingle
        Me.Controls.Add(pic)
In the Paint Event:

        Dim gr As Graphics = Me.CreateGraphics
        Dim brSize As Rectangle = New Rectangle(0, 0, Me.Width, Me.Height)
        Dim clrs() As String = {"255", "0", "0", "255"}
        Dim clr As Color = Color.FromArgb(clrs(0), clrs(1), clrs(2), clrs(3))
        Dim lgBrush As New LinearGradientBrush(brSize, clr, Color.Black, LinearGradientMode.Vertical)
        Dim br As Brush = lgBrush

        gr.FillRectangle(br, 0, 0, Me.Width, Me.Height) ' Fill the entire Control/Form
        br.Dispose()
        lgBrush.Dispose()
        gr.Dispose()

this works for me?

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
       
        Dim pic As New PictureBox
        pic.BackColor = Color.Transparent
        pic.BorderStyle = BorderStyle.FixedSingle
        Me.Controls.Add(pic)
        pic.Dock = DockStyle.Fill
        pic.BackgroundImageLayout = ImageLayout.Stretch
        Dim bmp As Bitmap
        bmp = New Bitmap(Width, Height, Imaging.PixelFormat.Format24bppRgb)
        Dim gr As Graphics = Graphics.FromImage(bmp)
        Dim brSize As Rectangle = New Rectangle(0, 0, 800, 600)
        Dim clrs() As String = {"255", "0", "0", "255"}
        Dim clr As Color = Color.FromArgb(clrs(0), clrs(1), clrs(2), clrs(3))
        Dim lgBrush As New Drawing2D.LinearGradientBrush(brSize, clr, Color.Black, Drawing2D.LinearGradientMode.Vertical)
        Dim br As Brush = lgBrush
        gr.FillRectangle(br, 0, 0, 800, 600)
        pic.BackgroundImage = bmp

        Dim pic1 As New PictureBox
        pic1.BackColor = Color.Transparent
        pic1.BorderStyle = BorderStyle.FixedSingle
        Me.Controls.Add(pic1)
        pic1.BringToFront()
        br.Dispose()
        lgBrush.Dispose()
        gr.Dispose()
    End Sub
Not for me.

I get a grey rectangle in the upper left corner, NOT a transparent picture control displaying the gradient underneath.

?
shows red for me? did you set

did you set the forms backcolor to red.

this would have to be the case if you see gray. thats the only place it can come from..
That's not what I'm looking for, that's the problem.

Whatever the BackColor is of the Form ISwhat's showing through - I don't want that, I want the GRADIENT that was created in the form's paint event to show through, NOT the back color.

Same problem if the form has a background image - the iumage won't show through, only the back color.

I think it's a bug...
ASKER CERTIFIED SOLUTION
Avatar of 5thcav
5thcav
Flag of United States of America image

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