1

I'm trying to draw a semi-transparent background and then opaque elements on top of it.

How come I can't do something like this?

protected override void OnPaint(PaintEventArgs pe)
{
    base.OnPaint(pe);

    this.Opacity = 0.5;
    pe.Graphics.FillRectangle(trans_black_brush, square_rect_big);
    this.Opacity = 1;
    pe.Graphics.FillRectangle(solid_red_brush, square_rect);
}

I'd appreciate if someone with better understanding of Form drawing could tell me why this doesn't work :)

Update: The solution has 3 forms: 1) Main (program, buttons etc) 2) Semi-transparent background (screen size, using opacity) 3) Transparent background but solid brushes on top.

In Form2's constructor, I have this:

Foreground = new FormForeground(this);

and in Form3's constructor I have this:

private Form_FormBackground m_Parent;

public FormForeground(FormBackground parent)
{
InitializeComponent();
FormBackground m_Parent = parent;
...
}

Whenever the mouse is clicked and used to draw with in form 3, I update the parent's rectangle like so:

private void _UpdateParent()
{
    m_Parent.s_DrawArea = m_DrawArea;
    m_Parent.Invalidate();
}

The parent, form 2 then does its OnPaint() where it draws the marked area.

It does work, however the drawing does lag a bit compared to drawing directly in form3 (which does not produce the desired results because the drawn area needs to be transparent across the forms).

Alx
  • 651
  • 1
  • 9
  • 26
  • If you need transparency then winforms really isn't what you want to be using, its graphics processing (gdi+) always struggles with some parts of doing it since its whole transparency handling is kind of a hack – Sayse Feb 05 '16 at 07:41
  • 1
    _its whole transparency handling is kind of a hack_ That is putting it mildly. The official word on it is: The transparency is __faked__ by copying the control's parent's background; this means among other restrictions: No overlapping is allowed and any dynamics is rather hard.. – TaW Feb 05 '16 at 07:54

1 Answers1

2

This doesn't work because Opacity is a Property of the Form and will always make the whole form and all its content have the current Value. It is perfect for fading a form in or out, though..

You can't achieve what you want with only one form.

Instead you will need two sychronized forms.

One can be somewhat opaque and will let the desktop shine through; the other must be transparent by making use of the TransparencyKey property and you can draw onto it..

To synchronize the two forms code the Move and the ResizeEnd events.

For a first setup use code like this:

A dummy form to create the semi-transparent look:

Form form0 = new Form() { Opacity = 0.33f , BackColor = Color.Black};

In the Form1's Load event:

TransparencyKey = Color.FromArgb(255, 147, 151, 162);
BackColor = TransparencyKey;
DoubleBuffered = true;

form0.Enabled = false;
form0.BringToFront();
form0.Show();
form0.Size = Size;
form0.Location = Location;
BringToFront();

And in the Move and the ResizeEnd events maybe code like this:

private void Form1_Move(object sender, EventArgs e)
{
    form0.Size = Size;
    form0.Location = Location;
}

private void Form1_ResizeEnd(object sender, EventArgs e)
{
    form0.Size = Size;
    form0.Location = Location;
}

You also may want to study this post that also shows a way to sandwich two forms.

Note that I picked a rather random color instead of the more common named color Fuchsia or any named colors. This is because I

  • Don't want to accidentally use it in the drawing, thius breaking making wrong spots transparent, but also
  • Don't want to make the form transparent for mouse actions, aka 'click-through'. This happens when using Fuchsia (and possibly some other colors) for some weird legacy reasons..
Community
  • 1
  • 1
TaW
  • 53,122
  • 8
  • 69
  • 111
  • Thank you, TaW. I've set up 3 forms. The First one is the main program. The second is the background (with opacity) and the third is the foreground you draw on. Form 1 and 2 works great, the problem is form 3 which refuses to work with transparency. I can't set BackColor to Color.Transparent. If I set the transparencykey and backcolor to the same, I am unable to move the mouse around and draw (since the form isnt there anymore, kind of, invisible) – Alx Feb 05 '16 at 07:54
  • Which backcolor did you choose? Fuchsia perchance? This is the only one to avoid as it makes the form 'click-through'... – TaW Feb 05 '16 at 07:56
  • Thank you for asking that question.. I've tried different colors so far (not the one you mentioned) and now I randomly tried CadetBlue and it works! Colors I tried before were standards, black, white, red, pink, lime.. I wonder why the colors have different effects.. – Alx Feb 05 '16 at 07:58
  • One thing I tried to achieve is making the selection transparent through both forms, so I set the same transparency key and the selected rectangle is filled with the same color. the drawn box doesnt bleed through the foreground. Which I'd like to do so that whatever is selected becomes 100% transparent through both forms. Is there any way to do this? How can I get the selection box rectangle in form3 to form 2 so that I could draw it there instead? – Alx Feb 05 '16 at 08:29
  • Hm, I guess I don't fully understand. But what you can always do, as all forms have the same size, is to pick up the coordinates from the top but do the drawing on a lower form. I hope you do the drawing in a correct (ie persistent) way btw. Check by mimimizing&maximizong the form! How are those forms stacked now? main - semi-transparent - transparent ? Onto which do you want the drawing to go? – TaW Feb 05 '16 at 08:58
  • Yeah, Main(form 1) -> Semi-trans background(2) -> transparent foreground(3). What I have done is that the mouse's clicking state and coordinates of the drawing is put into a rectangle which is updated into form2 from form3 by having a reference of the class. Then form 2 draws the rectangle in OnPaint which is invoked from form3, whenver the mouse moves in the drawing state. It lags a bit more than drawing directly in form 3, but.. not sure how it can get better – Alx Feb 05 '16 at 11:42
  • Not sure why it should lag but it sound ok. do the forms have doublebuffering=true? – TaW Feb 05 '16 at 12:10
  • Yes, they all have doublebuffering. I get the feeling that the data isnt updated fast enough, even though I call for an update in the form's MouseMove method. The update method immediately sets the new rectangle for the parent and then calls parent's Invalidate() – Alx Feb 05 '16 at 12:59
  • Yeah, well, mousemove happens real fast; maybe too fast?? one trick is to measure the distance and only process every n pixels with n>2 or 3.. – TaW Feb 05 '16 at 20:51