Solved

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

Posted on 2008-06-23
1
2,792 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

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
The viewer will learn how to use and create new code templates in NetBeans IDE 8.0 for Windows.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…

808 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