|
-
Jul 19th, 2009, 02:24 AM
#1
[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:
Private Sub frmMain_ResizeMove(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles Me.Resize, Me.Move Me.Refresh() 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.
-
Jul 19th, 2009, 03:51 AM
#2
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.
-
Jul 19th, 2009, 03:58 AM
#3
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.
-
Jul 19th, 2009, 04:07 AM
#4
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.
-
Jul 19th, 2009, 04:14 AM
#5
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...
-
Jul 19th, 2009, 04:22 AM
#6
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.
Last edited by NickThissen; Jul 19th, 2009 at 04:28 AM.
-
Jul 19th, 2009, 01:33 PM
#7
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:
Private Sub pnlContainer_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint Using borderPen As New Pen(Me.BorderColor, 1) If e.ClipRectangle.Width > 0 AndAlso e.ClipRectangle.Height > 0 Then 'Added Using linearBrush As New Drawing2D.LinearGradientBrush(e.ClipRectangle, Color.White, Color.LightBlue, Drawing2D.LinearGradientMode.Vertical) 'Added e.Graphics.FillRectangle(linearBrush, e.ClipRectangle) 'Added End Using 'Added End If 'Added e.Graphics.DrawLine(borderPen, 2, 0, 2, Me.Height - 4) e.Graphics.DrawLine(borderPen, Me.Width - 2, 0, Me.Width - 2, Me.Height - 4) e.Graphics.DrawLine(borderPen, 4, Me.Height - 1, Me.Width - 4, Me.Height - 1) e.Graphics.DrawLine(borderPen, 3, Me.Height - 2, 4, Me.Height - 2) e.Graphics.DrawLine(borderPen, 2, Me.Height - 3, 3, Me.Height - 3) e.Graphics.DrawLine(borderPen, Me.Width - 4, Me.Height - 2, Me.Width - 3, Me.Height - 2) e.Graphics.DrawLine(borderPen, Me.Width - 3, Me.Height - 3, Me.Width - 2, Me.Height - 3) End Using 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.
-
Jul 19th, 2009, 02:13 PM
#8
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:
Private frm As Form = Nothing Protected Overrides Sub InitLayout() MyBase.InitLayout() frm = Me.FindForm If frm IsNot Nothing Then AddHandler frm.Resize, AddressOf ParentFormMoveResize AddHandler frm.Move, AddressOf ParentFormMoveResize End If End Sub Private Sub ParentFormMoveResize(ByVal sender As Object, ByVal e As EventArgs) Me.Invalidate() 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...
-
Jul 19th, 2009, 02:26 PM
#9
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!
-
Jul 19th, 2009, 02:28 PM
#10
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.
Last edited by NickThissen; Jul 19th, 2009 at 02:35 PM.
-
Jul 19th, 2009, 02:44 PM
#11
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|