0

I have a custom control that I'm using as a rubber band which paints a blue border and a semi-transparent middle. I'm handling the mouse down / move events to resize the panel. Everything seems to work fine when the mouse move event is called, it all draws as I'd expect, but when the mouse stops moving, certain custom controls below the semi-transparency are redrawing themselves on top. Playing around with the z-order doesn't do anything.

Here is the transparent panel:

        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT
                return cp;
            }
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            pe.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(128, 101, 135, 196)), this.ClientRectangle);
            pe.Graphics.DrawRectangle(Pens.DarkBlue,
              pe.ClipRectangle.Left,
              pe.ClipRectangle.Top,
              this.Width - 1,
              this.Height - 1);
        }

        protected override void OnPaintBackground(PaintEventArgs pevent)
        {
            //do not allow the background to be painted 
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
        }
TimCodes.NET
  • 4,601
  • 1
  • 25
  • 36
  • Did your control derived from Panel class? – Anton Semenov Mar 02 '11 at 15:48
  • What happens is that controls that get invalidated underneath paint over the transparent control (without the transparent control getting an invalidate). What you want to achieve this way will be very hard. We went all-over-board in one of our projects and completely redirected rendering of WinForms controls by modifying the calls to the API at runtime. But this is hard and takes a lot of time. If you have the possibility, you might want to consider WPF for this use-case. Or make a part of UI WPF and host this within WinForms. – Dennis Smit Mar 03 '11 at 00:18
  • Another option: Make your rubberband selection a real window and make this transparent using form.Opacity. – Dennis Smit Mar 03 '11 at 00:21
  • What about hooking the paint event of other controls and doing a `rubberBand.Invalidate()` ? Thanks for the help Dennis – TimCodes.NET Mar 03 '11 at 08:41

1 Answers1

0

So, it turns out this is a pretty difficult problem with the semi-transparency (even if Microsoft have done it in Explorer etc). In the end I hacked up a solution where the middle is now totally transparent, and the rubber band is just a border.

The border still draws underneath certain controls, so for each control, we add a statement in their Paint event that calls ruberBand.Invalidate() if the rubberBand is visible. Hey presto, a hacked together rubber band that draws itself above controls.

IMO this is still better than using DrawReversibleRectangle, because you can use it inside panels for autoscrolling at the edge, and on top of that it doesn't flicker.

Community
  • 1
  • 1
TimCodes.NET
  • 4,601
  • 1
  • 25
  • 36