Draw Transparent Rectangle WITHOUT OnPaintBackground

Pselus

Active member
Joined
Dec 21, 2005
Messages
29
Right, so...long story short, I have a panel with curved corners. I need the portion of the panel outside the curve to be transparent. La-dee-da, thats easy as pie...done did it.
Problem: Due to the amount of graphical processing in the app (and the use of this panel ALL over the place), when the application raises an event or resizes there is alot of "flickering". I traced the issue down to the fact that the application is redrawing the background and for a split second it is showing through all the controls (on each of the panels in the application...so it causes alot of visual nastiness).
Now, the true problem arises in that, when I override OnPaintBackground...this flickering stops flat out...but I cant get the outside corners to draw transparent.
Ive tried alot of different things and come to the conclusion that you CANNOT use transparency if you Override OnPaintBackground (and do nothing in it). I pray that I am wrong about that conclusion and was hoping someone here would konw a way that I can.

for reference sake my panel is based off this example.

Here is a shot of the panel before overriding OnPaintBackground:
[Broken External Image]:http://www.livethislife.net/images/ForWork/panelbefore.gif

and here is a shot after overriding OnPaintBackground:
[Broken External Image]:http://www.livethislife.net/images/ForWork/panelafter.gif


So...anyone know of a way for me to draw a transparent rectangle as the background without actually drawing the background?

To further complicate matters...I need to do this over gradients.
 
guess no one wants to touch this one with a 10 foot pole eh?

let me try to make it easier.

How could I write a procedure to do Transparency just like Color.Transparent would do in VB.Net.
Thats the gist of it...I need to write what M$ already wrote because theirs only works if OnPaintBackground isnt overridden.
 
sadly no...that does allow me to make the corners transparent without calling MyBase.OnPaintBackground...but it raises a whole host of other issues like not fully drawing the controls until events are raised...though Im sure that this is my code interfering with what works from that example...but I cant for the life of me figure out why.
:(
 
Its going to be incredibly hard to be any more helpfull without seeing more code as there are many variables that may be causing you trouble, are you calling the main draw code from the paint event or from other events (which cause changes). Are you drawing directly to screen or to some kind of memory buffer?

On a side note I assume you havent accidently caused a loop by calling InvalidateEx from the OnPaint Event?
 
well...its gonna be pretty tough to show all the relevant code because 1) its huge and 2) its code for my company and I cant show much of it (I always hate that rule).

Mainly, I think one of my problems with that example is that our program uses this panel for other controls.
See, this is a panel that was built for this company by a different programmer who no longer works here...he did it solely for the purpose of creating rounded edges in a panel. Then, when they asked for buttons with rounded edges and labels with rounded edges and tab-controls with rounded edges he (stupidly in my opinion) used this panel to create them. For the label, he created a control with this panel and a windows label inside of it. This means that on any given form I have lots of instances of this panel, all of which are trying to be transparent and I end up with controls not completely drawing for some reason...
From what I understand this whole WS_EX_Transparent thing just tells the control to wait to draw after its children and parents...but what happens when a control with this setting is a child of another control with this setting?
 
Maybe Im missing the point here, but that surely doesnt help at all, and is infact quite likely to be the method Pselus is using. The links you provide basically talk about drawing a rounded rectangle. Pselus control already does that. The problem is its being drawn onto a square control and what Pselus wants is the areas its not being drawn on to show whatever is behind the control.
 
but will this get over the issue of the form redrawing when events are raised?
Ive come up with PLENTY of ways to get around the Transparency thing, but so far none of them have solved that particular problem...
now that I think about it...Im not sure I even mentioned that problem here...hmmm....

ah, yes, I did:
I traced the issue down to the fact that the application is redrawing the background and for a split second it is showing through all the controls

so yeah, overriding OnPaintBackground stops this flickering...but then the transparency problem comes up.

I will look into the links you posted...I hope they help me.
 
Cags said:
Maybe Im missing the point here, but that surely doesnt help at all, and is infact quite likely to be the method Pselus is using. The links you provide basically talk about drawing a rounded rectangle. Pselus control already does that. The problem is its being drawn onto a square control and what Pselus wants is the areas its not being drawn on to show whatever is behind the control.

YES!
exactly.
:P

my current thing Im looking into is trying to basically "capture" a rectangle on the parent at certain coordinates (specifically, where the corner is outside the curve) and draw that onto the control to mimic transparency....but I have no clue how to actually GET that rectangle from the parent that I need.
 
Im sure the method I outlined is probably your best solution, but I cant really say for sure untill ive tested it as a designtime control (which i dont know how todo) so ill have a look into that and get back to you.
 
umm....could I somehow use Regions for that purpose?
I have never worked with them before so Im not sure.
 
Im pretty sure that your method is the overall best solution as well...however, there are so many other things dependant upon it now that I dont think its the FASTEST way.
My boss has already said that we will take the time to go back and rewrite the controls later...so all I need to find now is a quick fix...when I redesign them I will most definatly use your method.
 
Try using Control.SuspendLayout() and ResumeLayout() when redrawing...without the need to override OnPaintBackground.

Also...is the username/password rectangle a user control? What is the need for the panel?
 
So, are you considering setting a region for the panel? Basically, taking a GraphicsPath, adding a RoundedRectangle identical to yours (but starting at 0,0), turning the GraphicsPath into a Region object and then setting the Panel region to the Region that you just created?
 
weve already tried the SuspendLayout, ResumeLayout route.
the Login is just a form, it happens to have one of these panels on it.
I can show you what it looks like with the control working properly...I have highlighted in green all the places just in one screen of the app that use this panel (ignore the red background...its me trying to test things):
[Broken External Image]:http://www.livethislife.net/images/ForWork/system.png

then this is what it looks like with OnPaintBackground overridden (the places that dont work are highlighted green, the places that do are blue):
[Broken External Image]:http://www.livethislife.net/images/ForWork/system2.png

honestly, for the life of me I cant figure out why some of those things work fine when others dont...

I must say...I used to hate doing bugs...now I just hate doing Graphics bugs when the graphics were designed by an incompetant programmer...I cant tell you how many places just have arbitrary Color.Transparent assignments...
 
literally the difference in those 2 pictures is when I go into this control and comment out (or uncomment) the single line: Mybase.OnPaintBackground.
doing that one thing in 1 control causes that much change in the application.
 
and now I have to go home for the weekend...everyone have a great Christmas and I hope I can solve this on Monday.
:)
 
Setting the Region setting seems to be the best solution, I just gave it a quick test. Create a region using a graphics path (if your not already doing that), if you are just set this.Region = new Region(myGraphicsPath), you will need to make this calculation everytime you resize the control etc but it should work fine.
 
ok, I only partially get what youre saying there Cags.
you are saying that I should set the controls region using a graphics path..I understand that part...but what exactly should this graphics path consist of? If I make the graphicspath based on the rounded edges, is it going to still need MyBase.OnPaintBackground to paint the transparent corners? If so, well...thats the whole issue...painting the background normally is the origional problem because it creates alot of flickering.
 
Back
Top