So having looked this up for a while now, I have read probably twenty different implementations but have not yet seen a solid, control-based, framework based general solution to implementing truly transparent controls that works.
This possibly oversimplified approach doesn't do anything at all and creates a routine (InvalidateEx) that never gets used: http://bytes.com/topic/c-sharp/answers/248836-need-make-user-control-transparent
This seems to be hinting at what the previous answer was getting at: http://www.bobpowell.net/transcontrols.htm
however uses a timer tick to execute the InvalidateEx method.
This appears to be abandoning multi-layered controls and handles all drawing on a single layered panel, while glossing over how the label object appears to be implementing its own transparency: http://www.codeproject.com/Articles/25048/How-to-Use-Transparent-Images-and-Labels-in-Window
This is a completely non-framework based method: http://www.codeproject.com/Articles/30135/General-solution-for-transparent-controls
The accepted solution in this answer simply does not work for me: Transparent Control on Transparent control?
The control I get is a generic solid colour (white) with the transparent image drawn over it.
So, I start on my own implementation.
I'd rather not rely on bottom-up GDI drawing, i.e. perform all drawing in the parent-most form, I'd rather not do pre-rendering to transparent bitmaps, I'd rather not inherit from something other than Forms.Control that is performing some clever tricks of its own to short-cut transparency. I really want to get to the bottom of how to draw on a control surface with complete transparency support. Evidently the label control for instance has a full implementation inside itself, how does it work?
Logically, a transparent control cannot rely on simple 1-bit clip regions and needs to stay mostly complete. Multi-layering of controls needs to be handled correctly, i.e. correct drawing order etc. without causing infinite loops.
The first and most common recommendation is this:
SetStyle(ControlStyles.SupportsTransparentBackColor, True)
Me.BackColor = Color.Transparent
where the first line I understand is synonymous with
Protected Overrides ReadOnly Property CreateParams As System.Windows.Forms.CreateParams
Get
Dim result As System.Windows.Forms.CreateParams = MyBase.CreateParams
result.ExStyle = result.ExStyle Or WindowsMessages.WS_EX_TRANSPARENT
Return result
End Get
End Property
Which has very different behaviours depending on which class is being inherited. In the case of Forms.Control, OnPaintBackground chooses to clear the clip rectangle with the parent control's background colour. Not too clever.
Overriding and removing the base OnPaintBackground call causes the control to stay 'dirty' having never overwritten what came below it. Clearing using a transparent colour (optimistic approach) yields a field of black transparent pixels and causes the control to appear completely black.
Logically this makes sense, underlying controls in a bid for efficiency do not redraw the area they anticipate this control with draw over. That area of the form then never gets updated and stays whatever came before the form existed. The painting of a transparent colour onto this is a little confusing, since it implies that the graphics buffer does not even contain the underlying pixels but actual nothings that are replaced with black transparent somethings to make the control appear black.
The first challenge appears to be handling when the control itself redraws, getting all underlying controls to redraw themselves in that region (without automatically invalidating the control itself to start a stack overflow), then painting itself over the underlying and up-to-date pixels. I haven't found a way to do this yet. The closest I have come is through digging around the .net code and finding the ButtonRenderer.DrawParentBackground method. This largely seems to work, though a quick test showed that z order of overlapping components was still not handled correctly, with underlying controls drawing over the top of this control.
The second challenge then is to have the control properly redraw itself when an underlying control changes. By disconnecting the automatic invalidation in challenge one, it makes it difficult to notify the control to invalidate itself and not invalidate its parents.
If someone has solved this problem completely, please provide the code, if not, please provide some experience in how I might handle one or several of the problem's parts.
Many thanks.
Edit:
It appears the assumed detail about WS_EX_TRANSPARENT as per WS_EX_TRANSPARENT - What does it actually do?
Research Update: ButtonRenderer.DrawParentBackground is actually just used by Control itself, only if Application.EnableVisualStyles() is used and simply forces the background draw of the parent. It appears to be a synonym of
InvokePaintBackground(Parent, e.Graphics)
Which will reproduce all background drawn details of the parent control.