|
-
Jul 2nd, 2011, 01:13 PM
#1
Thread Starter
Lively Member
Transparent DC
Hello, hope somebody can help me...
I want to create a VB6 UserControl, which has a Transparency property. I do copy the rectangle underneath the UC into a backbuffer DC. Draw my controls into that backbuffer and move the content to the UCs DC via BitBlt.
This works fine until Aero comes into the game! - In this case the UCs parent form is black. This results in a black background on my UC, which features a DIBSection.
I did already introduce a transparent color (because text is also black), which I can remove via GDI+ and ColorMap, when blitting to the destination DC. This works also fine, until I use the DrawThemeTextEx API, which is drawing an alpha blended glow effect. This effect changes my transparent color a little, so that I am not able any more to remove it from my back buffer.
I did try to use a 32bit bitmap for my back buffer, but here I was not able to draw controls via the DrawThemeBackground API (but maybe I did something wrong - am am very new to this kind of programming).
Has somebody any idea, how I can solve my problem?
Maybe a 32bit DC, which can be used like a normal DC, created with the CreateCompatibleDC API?
-
Jul 2nd, 2011, 04:52 PM
#2
Re: Transparent DC
If your user control does not need to act as a container you could set Windowless = True, ClipBehavior = None, AutoRedraw = False, and do drawing in UserControl_Paint. This gives you full Transparency with no need to copy what is behind the control to a buffer. Your Transparency Property sets a boolean variable such as m_bTranspaent.
To draw opaque use FillRect, DrawEdge, and DrawText.
To draw transparent use DrawEdge and DrawThemedText or DrawText.
To enable events you need to set HitResult = vbHitResultHit (if UserControl is Enabled) in UserControl_HitTest.
There are other things to solve such as MouseEnter and MouseLeave events.
Search for "Windowless" in vbForums for more info.
Last edited by DrUnicode; Jul 2nd, 2011 at 04:55 PM.
-
Jul 3rd, 2011, 02:14 AM
#3
Thread Starter
Lively Member
Re: Transparent DC
Thank you for your answer DrUnicode!
Is a windowless control a light weight control?
I thought, that in light weight controls, the drawing happens in the controls containers DC. In this case, it is not possible to change the Z order of the controls anymore.
What is the exact effect of following properties?
Windowless = True
ClipBehavior = None
AutoRedraw = False
If windowless is true, the control shouldn't be a real window itself, it has no hWnd property and is therefore problematic for APIs. Is this correct?
If AutoRedraw is true, there should be a back buffer handling by the control itself, which redraws the control after moving it back into a visible region on the screen. Correct?
I don't have an idea for ClipBehavoir. - For what is this for?
I made some tests with these settings and I always had to change the BackStyle property to Transparent, to get transparency. But I did also get this transparency, if I did change the BackStyle property only (without the other properties you mentioned).
I would really prefer a windowed control where I do have to copy the DC content from behind the control. The only thing what I need is a possibility to draw with DrawThemeBackground into a DC, which features an alpha channel, so that transparent parts stay really transparent.
My goal is, to take this DC and mulitply it with a transparency value, defined by the user, so that I can draw it semitransparent onto the destination DC.
Right now, I have to use some color for the background (because in the case of aero, there is only black behind the control), which I can strip before painting to the destination DC. This works fine until this back color gets changed by the drawing APIs (glow effect from DrawThemeTextEx for instance).
Do you think, there is a way?
-
Jul 3rd, 2011, 03:05 AM
#4
Re: Transparent DC
In no particular order:
1. Windowless is a lightweight control
2. Autoredraw must be False and ClipBehavior = None for a windowless control.
3. No hWnd available so no Zorder.
4. vbLabel doesn't have hWnd either so behavior of Windowless is essentially the same as vbLabel.
5. You can use Gdiplus to render images with transparency.
6. I have Label/Option/Check/Button controls that are Windowless and was able to work around lack of
hWnd. They all use DrawThemeBackground.
-
Jul 3rd, 2011, 06:43 AM
#5
Thread Starter
Lively Member
Re: Transparent DC
I have some questions to your answers DrUnicode:
1. Windowless is a lightweight control
Ok, makes sense.
2. Autoredraw must be False and ClipBehavior = None for a windowless control.
Ok, I made some research on ClipBehavoir: together with MaskPicture and MaskColor it defines, where it is possible to draw to in the UserControl. It also seems having to do something with HitTesting (which only makes sense, if there are several layers of transparent controls, which are windowed - so it must be possible somehow, don't you think?).
3. No hWnd available so no Zorder.
Yes, makes sense too.
4. vbLabel doesn't have hWnd either so behavior of Windowless is essentially the same as vbLabel.
Yes, I do hate the Label for its behavoir sometimes.
5. You can use Gdiplus to render images with transparency.
Yes, I did this already - but I was not able to draw on images with alpha channel with the Theme-APIs so far... 
But this would be my dream. Is this possible somehow?
6. I have Label/Option/Check/Button controls that are Windowless and was able to work around lack of hWnd. They all use DrawThemeBackground.
Ok, cool. Where do you draw to? Into the controls DC or to the controls container? Is there something to consider regarding MaskPicture and MaskColor?
What about containers - you mentioned above, that it is not possible to make them transparent?
-
Jul 3rd, 2011, 11:32 AM
#6
Re: Transparent DC
MaskPicture and MaskColor are not used with Windowless.
You draw to UserControl.hDc which is only available during UserControl_Paint. This hDc is actually the containers hDc but clipped. You will get an error if you try to draw to UserControl.hDc outside the Paint event.
See http://www.vbforums.com/showpost.php...42&postcount=2
ControlContainer must be False for Windowless controls.
I have never tried to render Theme-APIs with partial transparency. If you copied the UserControl.hdc to a temporary hDc and render Theme-API onto that, could you not then use GDI+ to copy this back to UserControl.hDc with different level of transparency?
Last edited by DrUnicode; Jul 3rd, 2011 at 12:02 PM.
-
Jul 3rd, 2011, 12:49 PM
#7
Re: Transparent DC
Sounds like your problem is that alpha blending is changing expected back color. That's alpha blending at work. Strongly suggest you do not try to render something alpha blended on a DC then go back and try to make some color transparent. Alpha blending in its nature modifies colors so that the forecolor is blended to the backcolor. Themes are all about alpha blending.
I see two immediate options:
1. As already mentioned, make a windowless UC as discussed earlier.
2. Continue with your current idea, but slightly modified.
a. Cache stuff behind the uc to a backbuffer
b. Create another backbuffer used for composing, same size as uc
c. When comes time to update uc....
-- Copy uc backbuffer to composing backbuffer (bitblt)
-- Call your theme APIs and draw controls onto that composing buffer
-- Transfer composing buffer to your uc dc (bitblt)
-- You will not be using color mapping now
Edited: Note that Option 1 is a true transparent control. Whenever whatever is behind the control changes, VB will ask the uc to repaint. The downside is that the control is windowless which has restrictions. Option 2 is a fake transparent control. If something behind the control changes, you will not easily know. Some uc authors I've seen force their users to provide a background to the uc while others try your method. In either case, Option 2 is not self-updating.
If you want to see the potential power of windowless, transparent controls, take a look at my Alpha Image Control, linked in my signature below.
Last edited by LaVolpe; Jul 3rd, 2011 at 12:57 PM.
-
Jul 3rd, 2011, 04:19 PM
#8
Thread Starter
Lively Member
Re: Transparent DC
Hello LaVolpe,
this sounds like option 1 is the only possible choice for me...
Option 2 is the exact way I am going right now (except, that I am reading the content behind my control on every update instead of saving it in a backbuffer). It works fine - until Aero and semitransparency comes into the game:
On Aero forms, the stuff behind the uc is black - this black doesn't matter, because on the form it becomes Aero glass again.
But for semitransparency I have to use GDI+ and a alpha channeled bitmap. This bitmap will be painted with the final control (including the black) and gets multiplied with a transparancy level value. The result will be blitted onto the destination DC. For some reason the black parts stay visible in this case. Therefore I do strip the black from the bitmap - but I can do this only for the black parts, which were not changed by some alpha parts from the theme APIs.
PS: actually I do not use black as backcolor, since this color is mostly used for text. But I did use this color in my description above, to simplify the whole thing.
The downside is that the control is windowless which has restrictions.
- I see here mainly uncomfortable bahavoir in the visual editor: controls can get "lost" behind other windowed controls.
- It is not possible to manipulate the controls with APIs, which require a hWnd
+ Besides the true transparency there might be also advantages in resource usage (no window) and performance (does not require to read the content behind the control)
What PROs and CONs else are you aware of?
Option 2 is a fake transparent control. If something behind the control changes, you will not easily know.
Yes, the user has to refresh the control on every paint event of its container.
Some uc authors I've seen force their users to provide a background to the uc
Instead of reading the content behind the control? - This is very uncomfortable!
If you want to see the potential power of windowless, transparent controls, take a look at my Alpha Image Control, linked in my signature below.
Is there a way to run the examples without having to place the AlphaImgControls again? I did unzip the archives and added the AlphaImgControl project to the example projects.
Thanks, Peter
-
Jul 3rd, 2011, 04:34 PM
#9
Re: Transparent DC
How exactly are you copying the contents behind the usercontrol on each refresh?
Regarding the Alpha Image Control. Huh? If you copy both the control & the samples zips in that thread, simply unzip each in separate folders but make those folders siblings, same parent folder. This is explained at bottom of 1st post in that thread.
-
Jul 4th, 2011, 12:36 PM
#10
Thread Starter
Lively Member
Re: Transparent DC
 Originally Posted by LaVolpe
How exactly are you copying the contents behind the usercontrol on each refresh?
First I calculate the controls position relative to its container or parent.
Then I take the container/parents DC and BitBlt calculated rectangle to my control.
Regarding the Alpha Image Control. Huh? If you copy both the control & the samples zips in that thread, simply unzip each in separate folders but make those folders siblings, same parent folder. This is explained at bottom of 1st post in that thread.
This is what I did - and I am getting following error:
Error while loading. More Information in
'F:\Downloads\_VB\LaVolpe\Samples\frmAnimation.log'
Log:
Code:
Zeile 48: Klasse LaVolpeAlphaImg.AlphaImgCtl des Steuerelements AlphaImgCtl1 war keine geladene Steuerelementklasse.
Zeile 65: Klasse LaVolpeAlphaImg.AlphaImgCtl des Steuerelements AlphaImgCtl2 war keine geladene Steuerelementklasse.
Zeile 86: Klasse LaVolpeAlphaImg.AlphaImgCtl des Steuerelements AlphaImgCtl3 war keine geladene Steuerelementklasse.
Line ??: Class LaVolpeAlphaImg.AlphaImgCtl of the control AlphaImgCtl? was no no loaded control class.
What I am doing wrong?!?
-
Jul 4th, 2011, 02:00 PM
#11
Re: Transparent DC
 Originally Posted by NeedHelp!
First I calculate the controls position relative to its container or parent.
Then I take the container/parents DC and BitBlt calculated rectangle to my control.
Using BitBlt shouldn't get you the "stuff" behind the control. You can verify this easily enough: Place an image control with an image behind your uc. You shouldn't be able to get the image in your backbuffer. If I'm wrong, let me know. Curious.
 Originally Posted by NeedHelp!
Line ??: Class LaVolpeAlphaImg.AlphaImgCtl of the control AlphaImgCtl? was no no loaded control class.
What I am doing wrong?!? 
1. Open the alpha image control project first
2. Select menu: File | Add Project
3. Navigate to & select a sample project
4. After sample added to your project explorer window (top right treeview), right click on it and choose: Set as Start up
5. Now press Ctrl+F5 (run)
-
Jul 4th, 2011, 02:32 PM
#12
Thread Starter
Lively Member
Re: Transparent DC
Hi LaVolpe!
 Originally Posted by LaVolpe
Using BitBlt shouldn't get you the "stuff" behind the control. You can verify this easily enough: Place an image control with an image behind your uc. You shouldn't be able to get the image in your backbuffer. If I'm wrong, let me know. Curious.
No, you are right. I do not cover this case, since it is not very likely, that this happens.
It would be possible to check, which other controls on the same parent touch/collide with the control, check their Z order and get the interesting parts like I am doing it with the container. - But this is not really worth the effort and should also not speed up the whole thing.
Anyway, I am really thinking to go the windowless way. But I like to be aware of all downsides, before I am doing this. - I have a further control in mind, where I want to use the SetParent-API, to place other controls on my control. But here I need a window handle. It might be possible to use the container hWnd in this case and move the controls to the right position afterwards - but this will cause bad flickering, don't you think?
1. Open the alpha image control project first
2. Select menu: File | Add Project
3. Navigate to & select a sample project
4. After sample added to your project explorer window (top right treeview), right click on it and choose: Set as Start up
5. Now press Ctrl+F5 (run)
I got it. Thanks!
-
Jul 4th, 2011, 02:40 PM
#13
Re: Transparent DC
Regarding downsides of windowless:
1. If OCX not placed in VB or Access, the other language IDEs may not support windowless, so control becomes windowed & transparency logic is gone.
2. Windowless controls cannot contain windowed children.
3. Windowless controls cannot be moved to another container outside of its form
4. Mouse Enter/Exit events, if desired, not easily done because can't use typical logic without hWnd
5. Obviously, since windowless has no hWnd, cannot manipulate the control via APIs that require hWnds
6. If windowless has the HasDC property false, the UserControl.hDC is zero everywhere except during the Paint event. All updating should be done from the Paint event. Calling UserControl.Refresh will activate that event.
-
Jul 5th, 2011, 05:08 PM
#14
Thread Starter
Lively Member
Re: Transparent DC
Thank you LaVolpe for this summary!
There are some big downsides - I have to think about it...
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
|