arcoant

Hi, everyone!
I'd really like to hear (or read ;)) some help on solving my problem.

I want to create a custom user control. I'd probably derive it from Control class, I want to draw everything on the control by myself (it's actually not going to be really complicated). The problem is that I want to draw some kind of a shadow that drops onto the background of this control. Obviously, it has to be translucent. And I would maybe make some other parts of the control translucent.

So I tried to draw the shadow using brush colored as Color.FromArgb(100, Color.Gray), for example. I do my drawing in overridden OnPaint method. This did NOT work. I started to look for the solution on the web. Everything I found was one method of creating such a behavior - override OnPaintBackground (leaving it empty), override CreateParams property (changing ExStyle), create function that invalidates parent control and then draw. This works, but blinks a lot, because I move it with mouse. If I set Double Buffering it stops being translucent. I actually had many troubles with this, so i may be forgetting anything else...

Could anyone help me Is it really so hard (or even impossible) to make a translucent control


Re: Windows Forms General User control with some parts drawn translucent

Mick Doherty

So long as you don't want true Transparency (i.e. controls underneath the control show through) then it is certainly possible.

You simply need to tell the controls Parent to draw the relevant part of itself to the control surface in the OnPaintBackground method.

Here's a simple VB.net example of code added to a class which Inherits Control

  Public Sub New()
    MyBase.New()
    Me.DoubleBuffered = True
    'The following line allows a translucent backcolor to be set
    Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
  End Sub

  Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)

    'Simulate Transparency
    Dim g As System.Drawing.Drawing2D.GraphicsContainer = pevent.Graphics.BeginContainer()
    Dim translateRect As Rectangle = Me.Bounds
    pevent.Graphics.TranslateTransform(-Me.Left, -Me.Top)
    Dim pe As PaintEventArgs = New PaintEventArgs(pevent.Graphics, translateRect)
    Me.InvokePaintBackground(Me.Parent, pe)
    Me.InvokePaint(Me.Parent, pe)
    pevent.Graphics.ResetTransform()
    pevent.Graphics.EndContainer(g)
    pe.Dispose()

    'Draw your background and edges here
    pevent.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
    Dim paintBrush As New SolidBrush(Me.BackColor)
    Dim fillPath As New Drawing2D.GraphicsPath()
    Dim r As Rectangle = Me.ClientRectangle
    r.Inflate(-12, -12)
    fillPath.AddEllipse(r)
    pevent.Graphics.FillPath(paintBrush, fillPath)
    fillPath.AddEllipse(Me.ClientRectangle)
    paintBrush.Color = Color.FromArgb(180, Color.Gray)
    pevent.Graphics.FillPath(paintBrush, fillPath)
    paintBrush.Dispose()
    fillPath.Dispose()

  End Sub




Re: Windows Forms General User control with some parts drawn translucent

arcoant

Thanks a lot for help! Well, I translated the code into C#, pasted it to my class...

It works, but it doesn't work as it should. It repaint only parent of a control, and this is not enough. See, the control is a form's child, but the form has another (and may have more) child (e.g. some picture) which happens to be between my control and the form...

PS. Could you please explain why did you call TranslateTransform(...) and was it done using GraphicsContainer (i didn't quite get the purpose of this class in MSDN)




Re: Windows Forms General User control with some parts drawn translucent

Mick Doherty

VB is my preferred language, but I would have posted C# code had you specified C# or posted the message in a C# group.

It seems that what you want is true transparency, which is not really supported in dotnet.

You will find examples which show how to set the WS_EX_TRANSPARENT style in a control, and it seems that you have already seen some. Although this would appear to be exactly what you want, you will face many problems using this approach and may never actually get it working. I've tried several times and never had results which I found to be acceptable.

TranslateTransform() is used to offset the DestinationRectangle which the parent Paints to (you don't want to paint the Parent Rectangle from Point(0,0) to your Control).

GraphicsContainer is used to limit the painting to the controls Graphics object. Under certain conditions a Control will paint itself to transparent child controls, this is most apparent when using TranslateTransform() on the Graphics object.

Why do you want to place a control on top of other controls, and have them visible





Re: Windows Forms General User control with some parts drawn translucent

arcoant

WS_EX_TRANSPARENT: yes, that's what I saw and tried to use. It works as I wish it to work except one thing - awful blinking (when no double buffering, if I turn double buffering on - it stops being transparent).

I just wanted to make a control (mostly to see if I can do it to use it in practice in future) which would have some "cool" transparency/translucency :). I thought it would be easy to create a control with a shadow, or, for instance, a control with half-transparent rectangle in it. But it seems it wouldn't be that easy...

Thanks for help, and do you know how do they draw these controls with shadows E.g. hints in XP, pretty hints in Office2007 Or do they just manually calculate amount of color in every point of the "shadow"





Re: Windows Forms General User control with some parts drawn translucent

arcoant

Mick Doherty wrote:

VB is my preferred language, but I would have posted C# code had you specified C# or posted the message in a C# group.

And don't worry about that :) I didn't have any trouble with translation...





Re: Windows Forms General User control with some parts drawn translucent

Mick Doherty

arcoant wrote:

I just wanted to make a control (mostly to see if I can do it to use it in practice in future) which would have some "cool" transparency/translucency :). I thought it would be easy to create a control with a shadow, or, for instance, a control with half-transparent rectangle in it. But it seems it wouldn't be that easy...

It wouldn't be easy, but I wouldn't say impossible. You would have to manually doublebuffer and, I suspect, use GDI rather than GDI+.

arcoant wrote:

Thanks for help, and do you know how do they draw these controls with shadows E.g. hints in XP, pretty hints in Office2007 Or do they just manually calculate amount of color in every point of the "shadow"

I don't know what controls you're referring to here. I don't recall having seen translucent controls sitting in front of other controls in the Office 2007 trial which I tested.





Re: Windows Forms General User control with some parts drawn translucent

efbiaiinzinz

Now then, there exists such thing as SetStyle function.
Just call it with the right parameters that show up to you when you're using Visual Studio 2005 ;)
Here's an example:
SetStyle( ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.SupportsTransparentBackColor, true );
First three need to be used together so that the control is drawn using double buffering, no background is erased so that the painting is done without any flickering.

The last option sets the Control so that it can be transparent using background color that has alpha set to less than 255 or when using backgroundimage that has transparency.

Thats all there is to it, call that SetStyle at the first line of the control's constructor and you're all set.
No need to override background painting in your case too, just set background to totally transparent color and all should work as needed.

But remember one thing, the transparency thing works nicely only as long as the control is located in a control that is the type of System.Windows.Forms.Control (or the form itself).





Re: Windows Forms General User control with some parts drawn translucent

arcoant

2 Mick Doherty: As for Office 2007, I meant hints with translucent shadow which falls "as a shadow should fall", but every XP hint has such a shadow... You can see it if you want to see it :)

2
efbiaiinzinz: Thank you for that tip. The funniest thing is that I think I tried that even before I posted here... Heh, maybe I used it with smth else...




Re: Windows Forms General User control with some parts drawn translucent

Mick Doherty

arcoant wrote:
2 Mick Doherty: As for Office 2007, I meant hints with translucent shadow which falls "as a shadow should fall", but every XP hint has such a shadow... You can see it if you want to see it :)

I don't have Office 2007 installed anymore (I loved it, but I don't use it often enough to justify an upgrade at the moment), but I suspect that you are talking about popup windows (like enhanced Tooltips). These are basicly just PerPixelAlpha forms, and you will find examples on codeproject. The drawback to these controls is that you must draw all child controls on them yourself as they swallow up standard Paint messages and do not draw child controls.

You can set the CS_DROPSHADOW ClassStyle flag in CreateParams, which will give you a shadow in XP.

SetStyle(OptimizedDoubleBuffer | UserPaint | AllPaintingInWmPaint); is the same as this.DoubleBuffered = true;

This form of doublebuffering will not work with WS_EX_TRANSPARENT.

If you want the entire background of the control to be transparent to it's parent then there is no need to override OnPaintBackground(), but if you want a specified region to be painted with a set BackColor whilst leaving the rest transparent to the parent, then you first need to simulate the transparency yourself as in the example I gave.





Re: Windows Forms General User control with some parts drawn translucent

arcoant

Thanks for the answer.