Results 1 to 11 of 11

Thread: [RESOLVED] Invalidating Inherited Controls When Parent Form Is Resized Or Moved

  1. #1

    Thread Starter
    Master Of Orion ForumAccount's Avatar
    Join Date
    Jan 2009
    Location
    Canada
    Posts
    2,802

    Resolved [RESOLVED] Invalidating Inherited Controls When Parent Form Is Resized Or Moved

    Pretending I have a class that inherits off Control, how would I handle the parent form's Resize and Move events within the control? I have a painting glitch that happens when the form is resized or moved. Right now in the form I just have:

    vb.net Code:
    1. Private Sub frmMain_ResizeMove(ByVal sender As Object, ByVal e As System.EventArgs) _
    2. Handles Me.Resize, Me.Move
    3.     Me.Refresh()
    4. End Sub

    But this can't be the proper way to do it, considering Refresh() invalidates all children (will be slow and flashing if the form has lots of controls). I want to basically do the above code inside the control.

    Edit:

    This is the glitch after a resize of the parent form:

    And this is what the button is supposed to look like:


    Also, I experience this issue if something like a message box is dragged over top of it. How can I remedy these issues by forcing a repaint?
    Last edited by ForumAccount; Jul 19th, 2009 at 02:53 AM.

  2. #2
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Invalidating Inherited Controls When Parent Form Is Resized Or Moved

    Try calling the Invalidate method of the control.

    You may also want to use Double Buffering. You can do that using the SetStyle method in the control's constructor. I believe you need to set at least 3, maybe 4 styles, called something like 'AllPaintingInWmPaint', 'UserPaint', 'ResizeRedraw' and 'DoubleBuffer'. That last one does not show up in intellisense, but it should exist anyway.
    Not sure if that helps with your current issue, but it might.

  3. #3

    Thread Starter
    Master Of Orion ForumAccount's Avatar
    Join Date
    Jan 2009
    Location
    Canada
    Posts
    2,802

    Re: Invalidating Inherited Controls When Parent Form Is Resized Or Moved

    Ah Nick, how did I know the guy that's always playing around with painting would reply? I may have explained a bit poorly though, I am trying to call Me.Invalidate() inside my custom control when it's parent form (host form) is Moved or Resized. I just can't seem to figure out how... I can't seem to find anywhere I can place an event handler.

  4. #4
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Invalidating Inherited Controls When Parent Form Is Resized Or Moved

    Ah... In that case, I don't really know. I don't even think you need to do that. I started with a custom drawn control yesterday actually, and it has none of the suggestions I gave above (yet), but it works just fine. There are no glitches when moving/resizing the form.

    However, when I add the Me.Refresh code in the move/resize handler, it DOES glitch!

    Try removing the Refresh call and see if it still glitches.

  5. #5

    Thread Starter
    Master Of Orion ForumAccount's Avatar
    Join Date
    Jan 2009
    Location
    Canada
    Posts
    2,802

    Re: Invalidating Inherited Controls When Parent Form Is Resized Or Moved

    Removing the Refresh call makes it glitch for me... weird you don't experience it. The Move issue actually might be more focused on my dual monitors and when I drag it across it sometimes glitches. Try this on your control to see if it glitches. Resize the form over top of the control and then resize back (Anchor it on Top, Left). Or, anchor your control to Bottom, Right. Then while resizing your form, move your control under another control. Same thing...

  6. #6
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Invalidating Inherited Controls When Parent Form Is Resized Or Moved

    I have dual monitors to. There is no glitching whatsoever when I drag it across.

    There is no glitching when I resize the form smaller than the control, and then back again.

    There is a very slight amount of glitching when I resize the form so that the control moves underneath other controls. The glitching is only near the other control's border, and is restored almost immediately.

    Using the SetStyles in the constructor solved the last glitch too. Now, it does not glitch at all.
    Code:
            Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
            Me.SetStyle(ControlStyles.ResizeRedraw, True)
            Me.SetStyle(ControlStyles.UserPaint, True)
            Me.SetStyle(ControlStyles.DoubleBuffer, True)

    Could you post your painting code? Or the whole control perhaps? I won't be online for a few hours after this post so I'll have a look this afternoon.



    EDIT
    In the meantime, you may want to take a look at my expandable groupbox control and compare it with yours. I do a bit of custom drawing there too.

  7. #7

    Thread Starter
    Master Of Orion ForumAccount's Avatar
    Join Date
    Jan 2009
    Location
    Canada
    Posts
    2,802

    Re: Invalidating Inherited Controls When Parent Form Is Resized Or Moved

    Hey Nick, I took a look at your code and managed to duplicate my problem by adding a little painting code. There is something up with LinearGradientBrushes that is unexplained.

    vb.net Code:
    1. Private Sub pnlContainer_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
    2.         Using borderPen As New Pen(Me.BorderColor, 1)
    3.             If e.ClipRectangle.Width > 0 AndAlso e.ClipRectangle.Height > 0 Then 'Added
    4.                 Using linearBrush As New Drawing2D.LinearGradientBrush(e.ClipRectangle, Color.White, Color.LightBlue, Drawing2D.LinearGradientMode.Vertical) 'Added
    5.                     e.Graphics.FillRectangle(linearBrush, e.ClipRectangle) 'Added
    6.                 End Using 'Added
    7.             End If 'Added
    8.             e.Graphics.DrawLine(borderPen, 2, 0, 2, Me.Height - 4)
    9.             e.Graphics.DrawLine(borderPen, Me.Width - 2, 0, Me.Width - 2, Me.Height - 4)
    10.  
    11.             e.Graphics.DrawLine(borderPen, 4, Me.Height - 1, Me.Width - 4, Me.Height - 1)
    12.  
    13.             e.Graphics.DrawLine(borderPen, 3, Me.Height - 2, 4, Me.Height - 2)
    14.             e.Graphics.DrawLine(borderPen, 2, Me.Height - 3, 3, Me.Height - 3)
    15.  
    16.             e.Graphics.DrawLine(borderPen, Me.Width - 4, Me.Height - 2, Me.Width - 3, Me.Height - 2)
    17.             e.Graphics.DrawLine(borderPen, Me.Width - 3, Me.Height - 3, Me.Width - 2, Me.Height - 3)
    18.         End Using
    19.     End Sub

    I added those 5 lines to paint a linear faded rectangle and it does the same thing I am experiencing. Try the resizing over top of the control with it. If I just use a brush from the Brushes class this glitch doesn't happen...

    Nice control by the way, I still need to learn how to make custom designers and now I can reference yours.

  8. #8
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Invalidating Inherited Controls When Parent Form Is Resized Or Moved

    Ok, I get the glitch now too. I find it odd that it doesn't happen on the other control I tested it on, which used LinearGradientBrushes too. I can't see anything I'm doing differently.

    I can only think of one method, that basically does what you say: invalidate the control when the parent form is moved or resized. To do that, you can get a reference to the form in the InitLayout override, and use AddHandler to add an event handler to the Resize and Move events.
    vb.net Code:
    1. Private frm As Form = Nothing
    2.     Protected Overrides Sub InitLayout()
    3.         MyBase.InitLayout()
    4.  
    5.         frm = Me.FindForm
    6.         If frm IsNot Nothing Then
    7.             AddHandler frm.Resize, AddressOf ParentFormMoveResize
    8.             AddHandler frm.Move, AddressOf ParentFormMoveResize
    9.         End If
    10.     End Sub
    11.  
    12.     Private Sub ParentFormMoveResize(ByVal sender As Object, ByVal e As EventArgs)
    13.         Me.Invalidate()
    14.     End Sub

    It does work, although there's a tiny amount of flickering near the borders. Note that I am not sure if this has any side effects, it's just something I tried out in 5 seconds and appears to work

    I am pretty sure there must be a better way though, I think 'real' controls must be painted in some way or another too, I can't imagine them all using this method...

  9. #9

    Thread Starter
    Master Of Orion ForumAccount's Avatar
    Join Date
    Jan 2009
    Location
    Canada
    Posts
    2,802

    Re: Invalidating Inherited Controls When Parent Form Is Resized Or Moved

    That is still much cleaner then having the parent form handle it, so thank you! You are probably right, there must be a better way to do this. Unfortunately there are two other glitches I was hoping you might have some insight on. The first is if a form is shown over top of the control, such as a MessageBox, it will glitch. The second isn't too bad, when in design mode if you drag your mouse to select the control it will glitch until you release the mouse. Any thoughts?

    Thanks for all the help!

  10. #10
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Invalidating Inherited Controls When Parent Form Is Resized Or Moved

    I think I found the problem. I only occurs when you use the ClipRectangle. If you simply declare a new rectangle [0, 0, Me.Width, Me.Height] it works! Perhaps the ClipRectangle is 'clipped' (:P) when the control is not fully visible or something? I'll have to read up on the ClipRectangle property.

    There's something interesting here
    Geometry of the Drawing Region

    The ClientRectangle property of a control specifies the rectangular region available to the control on the user's screen, while the ClipRectangle property of PaintEventArgs specifies the area that is actually painted. (Remember that painting is done in the Paint event method that takes a PaintEventArgs instance as its argument). A control might need to paint only a portion of its available area, as is the case when a small section of the control's display changes. In those situations, a control developer must compute the actual rectangle to draw in and pass that to Invalidate. The overloaded versions of Invalidate that take a Rectangle or Region as an argument use that argument to generate the ClipRectangle property of PaintEventArgs.
    Seems that the ClipRectangle should not be used when the control is partially invisible. Instead, you should use the ClientRectangle (of the Control, not paint event args), which is basically the same as manually specifying x,y,w,h.


    So I guess what's happening is that the part of the control outside of the form is not included in the ClipRectangle and hence is not painted. When you move that part back into view, it still has the 'old background', until it is repainted again.

    I am confident that using ClientRectangle will solve both your other problems too, although I didn't test it.

  11. #11

    Thread Starter
    Master Of Orion ForumAccount's Avatar
    Join Date
    Jan 2009
    Location
    Canada
    Posts
    2,802

    Re: Invalidating Inherited Controls When Parent Form Is Resized Or Moved

    Wow! I'm so glad you figured that out. Damn you ClipRectangle... This solves everything, thanks Nick!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width