Solved

Opacity of a Child Form has OnPaintBackGround issue - Parent painting last!

Posted on 2008-06-23
1
2,771 Views
Last Modified: 2013-12-16
I am creating a "Sheet" which overlays a WinForm and provides a MessageBox like functionality...actually, it's much more interactive...but rather than come up in another window...it comes up inside the WinForm that invokes it...

An important part of the "Sheet" functionality is that it also provides a translucent (Opacity = 50%) covering of the first (Parent) form which provides two key functions:

1.  To "effectively" disable the Parent WinForm's controls by overlaying the "Sheet" form on top of the WinForm.
2.  The Opacity set to 50% gives a visual clue to the user that the controls underneath the "Sheet" are disabled.

Important Notes:
1.  The Sheet cannot use the stock Opacity property...because in order to add this Form (Sheet) to the Parent WinForm, you have to first disable it as a TopLevel Form.

     Sheet.TopLevel = false;

2.  You cannot do Controls.Add to the Sheet Form without setting TopLevel = false;

3.  Microsoft, in their GUI wisdom, decided to disable the Opacity property of all Forms with TopLevel = false;

So my real goal right now is to create child form which can have an Opacity property AND handles window invalidations properly.

I have achieved that goal to some extent by making the child form transparent and then overriding the OnPaintBackGround method and filling the background using an Alpha channel.  

Here is the code which is based on:

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2363164&SiteID=1

       protected override CreateParams CreateParams

        {

            get

            {

                CreateParams cp = base.CreateParams;

                cp.ExStyle |= 0x00000020;//WS_EX_TRANSPARENT

                return cp;

            }

        }

 

        private int opacity;
        public int Opacity

        {
            get { return opacity; }

            set {

                opacity = value;

                this.InvalidateEx();

            }

        }

 
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            Color bk = Color.FromArgb(Opacity, this.BackColor);

            e.Graphics.FillRectangle(new SolidBrush(bk), e.ClipRectangle);
        }

        protected void InvalidateEx()
        {

            if (Parent == null)

                return;

            Rectangle rc = new Rectangle(this.Location, this.Size);

            Parent.Invalidate(rc, true);

        }


This actually works great on the first draw...my problem occurs whenever a portion of the Sheet and WinForm Parent are invalidated by another window.  

The problem is that the Sheet gets the OnPaintBackGround event BEFORE the Parent and any other controls on the Parent WinForm.  

PROBLEM: What that means is that the Parent form is drawn last which effectively hides my "Sheet".


I am confused why the child control (Sheet) is handling his OnPaintBackGround before it's parent...this seems very wrong...I know this is the case because I put Debug.Print statements in both the Parent and the child (Sheet)'s OnPaintBackGround methods to see who get's called first.  Further, I tried to make my Sheet WinForm be at the top of the Zorder in two ways:

            parentForm.Controls.Add(this);
       
            parentForm.Controls.SetChildIndex(this, 0);  <-- make sure he is at the top of the Zorder
            sheet.TopMost = true; <-- force him to be TopMost


NOTE:  The OnPaintBackGround is called in the correct order upon the first showing of the WinForm (Parent, other controls lower in the zorder, then the Sheet Form).  The problem only seems to happen when a region is invalidated...


I would be happy to post the project somewhere for you guys to play with and see if you can figure it out...


Any ideas?
0
Comment
Question by:clintcarter1999
1 Comment
 

Accepted Solution

by:
clintcarter1999 earned 0 total points
ID: 21847034
ok, i figured out a solution...

Rather than override OnPaintBackGround...I decided to override OnPaint (which paints the foreground).
This gaurantee's that the Parent will draw his background before I draw my foreground which gives me what i want.

Works great.  

No need to answer this one guys.  Sorry...
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

After several hours of googling I could not gather any information on this topic. There are several ways of controlling the USB port connected to any storage device. The best example of that is by changing the registry value of "HKEY_LOCAL_MACHINE\S…
For a while now I'v been searching for a circular progress control, much like the one you get when first starting your Silverlight application. I found a couple that were written in WPF and there were a few written in Silverlight, but all appeared o…
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now