Alpha blended, Double buffered non-client areas. How? Please help!

G

Guest

Hi,

I am deriving from Panel and I paint the client and non-client area of the
panel myself. I am drawing a bitmap in both the client and non-client area.
The bitmap has an alpha channel so the edges are neatly anti-aliased. I am
using the WM_NC* messages to distinquish between the client and non-client
area. I set the ControlStyles to both OptimizedDoubleBuffered and
SupportTransparentBackColor and set the BackColor to a transparent color.

All of this works fine, except for the fact that the non-client area does
not use double buffering or transparency. It seems that the control styles
are used for the client area only?

I have read Bob Powell's faq on Windows Forms and he also has a section on
transparent forms. However, if you set the WS_EX_TRANSPARENT style, you will
never be able to use double buffering, since Bob's technique will invalidate
the parent's window, causing flickering. Microsoft's approach for copying the
parent's background into an offscreen surface, and then copying your own
graphics over it sounds like the only possible way to deal with double
buffered transparent controls.

The frustrating thing is that .NET has everything in place with the
background painting. I've checked reflector and OnPaintBackground indeed
paints a piece of the parent control into the graphics object, when
SupportTransparentBackColor is set and the backcolor alpha is not opaque.
Great, but it seems that OnPaintBackground only paints the client area and
not the non-client area...

Did I miss something? Bottom line is: does anybody know how to handle double
buffered, transparent, alpha blended non-client area's? I'm counting on you,
Bob :).

Regards,
Jelle van der Beek
 
M

Mick Doherty

Non Client graphics drawing is not implemented at all in Visual Studio. You
will have to DoubleBuffer manually.

Draw the Parent Background to an offscreen bitmap, draw the control
Background to the offscreen bitmap and then draw the offscreen bitmap to
your non client area. It is best to use BitBlt via Interop to draw the
offscreen bitmap to your non client area, as when the forms opacity is not
set at default the clipregion is not correctly defined in GDI+ and the right
and bottom edge of your non client area will be clipped out and filled with
a null brush.
 
G

Guest

Ok, this was my bet too. I didn't know how to paint the parent background in
my graphics object, but I've found ButtonRenderer.DrawParentBackground in
..NET 2.0. This sounds like something that would most definitely be placed in
a more common class or even the control class, but still, it is very useful.

However, my quest continues: since I'd like to do my own doublebuffering, I
am using the BufferedGraphics object from .NET 2.0. It works fine, except for
the clipping part. My main graphics object that is retrieved from the Window
DC has a GDI+ clipping region set, which excludes the client area. From that
graphics object, I create a BufferedGraphics object. In the bufferedgraphics
object, I also exclude the client area from the region. Painting into the
doublebuffer is indeed clipped, but whenever Render is called, the entire
rectangle (incl client area) is also blitted to the screen.

My question: Are these the same clipping problems as you were describing?
BufferedGraphics uses Bitblt! Or am I missing something?


I could do my own doublebuffering with Bitmaps of course, but I'd prefer to
use .NET technology.

Regards,
Jelle van der Beek
 
M

Mick Doherty

I haven't looked too much at the VS2005 Graphics classes, so I suppose there
could be a completely .net aproach to your problem, but I very much doubt
it.

In VS2003 I did spend a fair amount of time playing with the Non client area
of controls, but not really too much on forms. What I found was that you can
draw directly to the Graphics object created from a WindowDC and it would
draw perfectly. If you then placed that same control onto a form with the
WS_EX_LAYERED style bit set (i.e. if you set the forms opacity), only a
rectangle the size of the clientarea would be drawn to the Window which
means that if you have a 3 pixel nonclient edge around your control, then
you would see that your controls nonclient edge is missing the rightmost 6
pixels and the bottommost 6 pixels. If instead you draw to an offscreen
bitmap and then use BitBlt via Interop to draw to the WindowDC then not only
does it draw the entire window, but it actually draws faster.

I usually call InvokePaintBackground() and InvokePaint(), passing the parent
as the control parameter, to simulate transparency and I expect that
ButtonRenderer.DrawParentBackground will do something similar.

In VB it would be something like (where bmGraphics is the offscreen bitmap
graphics object):

\\\
Dim TranslateRect As Rectangle = New Rectangle(Me.Location, Me.Size)
Dim pe As New PaintEventArgs(bmGraphics, TranslateRect)
bmGraphics.TranslateTransform(-Me.Left, -Me.Top)
Me.InvokePaintBackground(Me.Parent, pe)
Me.InvokePaint(Me.Parent, pe)
bmGraphics.ResetTransform()
///

Your offscreen bitmap now contains the relevant portion of your controls
container graphics and you just need to draw your control to it. You'll also
need to PInvoke SelectClipRgn() to exclude the client area from your
WindowDC and BitBlt the offscreen bitmap to the WindowDC.

As I mentioned above, these are the steps necessary to perform the task in
VS2003 and the new and improved graphics classes in VS2005 may be able to
give you a completely .net solution rather than you having to PInvoke old
Win32 routines.
 
G

Guest

Thanks for your help, Mick.

I've got all of it up and running now. I have filed the clipping issue with
BufferedGraphics.Render as a bug. If I set the clipping region of the DC
using plain GDI, it all works fine. BufferedGraphics.Render uses BitBlt, and
I assume that BitBlt does not use GDI+ regions that are set in the Graphics
object.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top