Pselus Posted December 29, 2005 Author Posted December 29, 2005 I'll try out the things you mentioned today. Sorry about not replying yesterday...I was out sick. The reasson I'm using that bitmap to draw was because I was attempting to double buffer the control. The normal windows double buffering wasn't working well enough so I had to do it on my own. As for the amount of this control in my program...well if you look at the images I put above, every single time you see a rounded edge...it's this control. Quote
Pselus Posted December 29, 2005 Author Posted December 29, 2005 also, what I meant by "not drawing all of the controls" is that some of my controls don't draw INSIDE the curves now. Specifically my tabcontrol which uses this panel. It now draws outside the curves just fine (which fixes the origional problem), but doesn't draw inside anymore. I also have a label control that is just this panel with a label inside of it (so I can have curved labels) and it does the same thing. Draws outside the curves now, but what's inside doesn't draw right. I'll try to get a screenshot or 2. Quote
Pselus Posted December 29, 2005 Author Posted December 29, 2005 I apologize now if these images are too huge...don't have any graphics programs at work except for MS Paint. Pay attention to what's inside the main white panel. Using the Region stuff you talked about (I took out the double buffering and it is much faster) it now paints outside the curves...but doesn't paint INSIDE. http://www.livethislife.net/images/ForWork/nodrawinside.png Now the odd thing is that as soon as I click the search link, which raises an event...it paints what's inside like this (remember, the ONLY thing I've done at this point is type "smith" and clicked "Search"...this screenshot was taken while processing for Search was going on): http://www.livethislife.net/images/ForWork/aftersearch.png and here is one more example of things not painting. The red borders were added in Paint. If you look at the big one you are seeing a windows panel inside of my custom panel. Inside the windows panel are 2 windows listboxes (along with some labels and things). Those listboxes aren't fully painting even though I have no code to override their paint events. If you look at the smaller red borders you will see another issue. Those are my custom panel with a windows label and a windows checkbox inside. The labels seem to be painting just fine, but the checkboxes aren't painting their background to match the parents background...which is why you see the white square outside the checkbox. Cags I can't thank you enough for the help you've given me already...this Region thing is DEFINATLY heading in the right direction...I've got faster loading and no flicker...now I just need to figure out these painting issues. http://www.livethislife.net/images/ForWork/inworkflow.png Quote
Cags Posted December 29, 2005 Posted December 29, 2005 In your OnPaint method how are you drawing the Background of the control are you calling e.Graphics.Clear(this.BackColor); or are you drawing a region/ rectangle? Quote Anybody looking for a graduate programmer (Midlands, England)?
Pselus Posted December 29, 2005 Author Posted December 29, 2005 In your OnPaint method how are you drawing the Background of the control are you calling e.Graphics.Clear(this.BackColor); or are you drawing a region/ rectangle? apparently neither. But the problem with using e.Graphics.Clear(this.Backcolor) is that the backcolor is Color.Transparent and windows transparency doesn't work right unless you don't override OnPaintBackground. Quote
Cags Posted December 29, 2005 Posted December 29, 2005 Ok you've confused me now. How are you drawing the actually main body colour of the control? Quote Anybody looking for a graduate programmer (Midlands, England)?
Pselus Posted December 29, 2005 Author Posted December 29, 2005 I was using Fillpath because the background is a gradient and Fillpath allows the use of a gradient brush whereas e.Graphics.Clear(Me.BackColor) just uses 1 color. *edit* right now this is my paint method: graphPath = Me.GetPath() If Me.ClientRectangle.Width = 0 Then rect.Width += 1 End If If Me.ClientRectangle.Height = 0 Then rect.Height += 1 End If If Me._GradientMode = LinearGradientMode.None Then filler = New System.Drawing.Drawing2D.LinearGradientBrush(rect, Me._BackColour1, Me._BackColour1, System.Drawing.Drawing2D.LinearGradientMode.Vertical) Else filler = New System.Drawing.Drawing2D.LinearGradientBrush(rect, Me._BackColour1, Me._BackColour2, CType(Me._GradientMode, System.Drawing.Drawing2D.LinearGradientMode)) End If e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias e.Graphics.FillPath(filler, graphPath) Me.Region = New Region(graphPath) OnPaintBackground is overridden and is blank. Quote
Cags Posted December 29, 2005 Posted December 29, 2005 It will help your program run fast if you call get Path only when you resize / create the control rather than when every time you paint. Todo this create a method called CalcLayout, and add the path calculation to it something like this... (my vb isn't that good) Public graphPath As New System.Drawing.Drawing2D.GraphicsPath Private Sub CalcLayout() graphPath = Me.GetPath() If Me.ClientRectangle.Width = 0 Then rect.Width += 1 End If If Me.ClientRectangle.Height = 0 Then rect.Height += 1 End If Me.Region = graphPath Invalidate() End Sub Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs) MyBase.OnPaint(e) If Me._GradientMode = LinearGradientMode.None Then filler = New System.Drawing.Drawing2D.LinearGradientBrush(rect, Me._BackColour1, Me._BackColour1, System.Drawing.Drawing2D.LinearGradientMode.Vertical) Else filler = New System.Drawing.Drawing2D.LinearGradientBrush(rect, Me._BackColour1, Me._BackColour2, CType(Me._GradientMode, System.Drawing.Drawing2D.LinearGradientMode)) End If e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias e.Graphics.FillPath(filler, graphPath) End Sub Protected Overrides Sub OnResize(ByVal e As EventArgs) MyBase.OnResize(e) CalcLayout() End Sub Quote Anybody looking for a graduate programmer (Midlands, England)?
Pselus Posted December 29, 2005 Author Posted December 29, 2005 you sir, are very nearly my hero. :) what you just posted works 99% perfectly...the only problem is that the gradient background doesn't draw all the way across now. example: http://www.livethislife.net/images/ForWork/wackyfun.png I'm going to look into it more, but was hoping you knew why that was happening. I did however navigate through the app and apart from the gradient and a few other issues I'm sure I can solve...this worked perfect. You english folks always seem to help me out so much. If I'm ever in england, you'll get a round a drinks on me. :) Quote
Cags Posted December 29, 2005 Posted December 29, 2005 Try changing e.Graphics.FillPath(filler, graphPath) to e.Graphics.FillRegion(filler, this.Region); Quote Anybody looking for a graduate programmer (Midlands, England)?
Pselus Posted December 29, 2005 Author Posted December 29, 2005 nope. Still shows the gradient wrong. I'm betting that somewhere the "rect" object isn't being treated the same. I basically took what you posted and commented out everything I had. So I'll go back and look at what's done to rect in my code. Quote
Cags Posted December 29, 2005 Posted December 29, 2005 ahh i think its because the rectangle you pass in to the linear brush should be relative to the control not the form so it should be new Rectangle(0, 0, this.Width, this.Height) Quote Anybody looking for a graduate programmer (Midlands, England)?
Pselus Posted December 29, 2005 Author Posted December 29, 2005 got it. Origionally rect was declared = Me.ClientRectangle. Forgot that part this time around. so...possibly 1 last question. Earlier you mentioned getting the border into the Region by adding 1 or 2 pixels all around. Should I do that in the graphPath or somewhere else? Quote
Cags Posted December 29, 2005 Posted December 29, 2005 The way i've been getting a border on my test control is like this, note you will have to modify the GetPath method slightly to accept a Rectangle. With the method I'm using I'm not entirely sure the border is the right thickness but you can tweak the size of the rectangle you pass in untill this is correct. private sub CalcLayout() _BorderPath = GetPath(new Rectangle(1, 1, this.Bounds.Width, this.Bounds.Height)) Me.Region = new Region(GetPath(this.Bounds)) Invalidate(); end sub then in the OnPaint method you call DrawPath(myPen, _BorderPath); EDIT: You also nead to remember that you will have to call CalcLayout whenever the border thickness is changed, and Invalidate whenever its colour is changed etc. Quote Anybody looking for a graduate programmer (Midlands, England)?
Pselus Posted December 29, 2005 Author Posted December 29, 2005 I'm not exactly following what you do with the rectangle that you pass into your GetPath method. are you just using it in place of the Method level "rect" that is declared in my GetPath method (do you still have that code? I thought I posted it a couple pages back). Quote
Pselus Posted December 29, 2005 Author Posted December 29, 2005 I believe I may just be a dolt. This whole "flicker" thing has drained my will to program. I just went and got the origional border drawing code and pasted it in...it works fine. silly me. :) Thank you so very much for all your help Cags. Quote
Pselus Posted December 29, 2005 Author Posted December 29, 2005 ah, the joy of all this crap is really getting to me. :) I have one last question (I hope). still having a bit of trouble with drawing the border. The problem isn't that it's not drawing the border...I think the problem is that the region isn't quite right. The border draws for the top and the left sides, and the bottom right corner shows up almost...but the right border and bottom border don't show. this is what it should look like: http://www.livethislife.net/images/ForWork/should.png and this is what it does: http://www.livethislife.net/images/ForWork/does.png see the difference in the borders? Quote
Cags Posted December 29, 2005 Posted December 29, 2005 It depends on how you look at it as to whether the problem is the border or the region. The fact is you are using the same calculation to work out both, which means the border is drawn the same size as the region however it is drawn slightly further down and across. You need to essentially work out the path of the border and the path for the region seperately which is what the code I posted before did (It certainly wasn't perfect code, but it did make some alteration to the border). At this moment in time I'm not entirely sure of the exact code that is required to make the border the correct size, but you definately have to work out the values seperately. I'll have a proper look at it tomorrow when I'm completely sober. I might eventually post the code for the test control I've been doing incase anybody else is trying to achieve the same effect. Quote Anybody looking for a graduate programmer (Midlands, England)?
Cags Posted January 7, 2006 Posted January 7, 2006 (edited) For anybody interested in doing this here is an example control that allows the user to specify a custom border, gradient background and select which corners of a control are rounded. Its the first time I've made a control with designtime support so there may be a few bugs, so if you find one please let me know (for reference sake as i'm not actually using the control for anything). The code is C# however I'm trying to pickup the VB syntax so I'm currently working on a conversion. If anyone is interested in that then just post here and let me know.RoundedPanel_cs.zip Edited January 7, 2006 by PlausiblyDamp Quote Anybody looking for a graduate programmer (Midlands, England)?
Pselus Posted January 9, 2006 Author Posted January 9, 2006 Cags, I'll check this out. Any VB syntax you need to know (and can't find) post up...I'll help in any way I can. Can't thank you enough for all the help you provided man. Quote
Pselus Posted January 9, 2006 Author Posted January 9, 2006 also, Cags...don't know if yours has this problem...but I noticed with mine that when you set the backcolor to Transparent in design time, it doesn't paint anything in the background and you end up with black or whatever is behind your app...it's not a real problem for me...just thought I'd point it out in case someone else does have a problem with it. Quote
Cags Posted January 9, 2006 Posted January 9, 2006 I have a vb version that works at runtime, however an error is encountered when using the control at designtime that prevents it from drawing. Basically instead of drawing correctly a nullreferenceexception is displayed, citing a line in the paint method. The variable it claims is null is Me.Region which seems very odd. What exactly causes this error I don't know but as this was only a learning task I'm not too worried about it. Quote Anybody looking for a graduate programmer (Midlands, England)?
WASTHEBEST Posted September 14, 2006 Posted September 14, 2006 Solved the problem of endless flickering of transparent controls when the form first loads or is maximized. Couldn't find a solution anywhere on the NET after a strenuous search, so to give back for the countless times I have been helped by the online community, I'm sharing it here: It appears that sometimes when a transparent control paints itself, for some reason the display area of transparent controls in the lower z-order and the parent are invalidated, and an endless loop of WM_PAINT messages occurs. Override the WndProc function of the control. When the function receives the WM_PAINT message, call base.WndProc(ref m) and then call the ValidateRect Windows API as necessary, like so: [Yeah, I know example is in C#. Started programming with VB6; I don't care where the solution comes from.] [DllImport("user32", CharSet = CharSet.Auto, EntryPoint = "ValidateRect")] public extern static Boolean ValidateRectangle( IntPtr handle, // handle to window IntPtr nullPointer); //type changed from ref RECT private const Int32 WM_PAINT = 0x00f; protected override void WndProc(ref Message m) { if(m.Msg == WM_PAINT) { base.WndProc(ref m); ValidateRectangle(this.Parent.Handle, IntPtr.Zero); foreach(Control control in this.Parent.Controls) { Int32 i3 = this.Parent.Controls.IndexOf(this); Int32 i4 = this.Parent.Controls.IndexOf(control); if(control is TransparentControlD) { if(i4 > i3) { continue; } } ValidateRectangle(control.Handle, IntPtr.Zero); } } else { base.WndProc(ref m); } } Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.