Question Load form on all of the screens

Valakik

Member
Joined
Nov 8, 2020
Messages
12
Programming Experience
Beginner
Hello
Long time ago I mentioned that I am making parental control app nowadays and I stuck with one thing.
I am trying to cover the screen with transparent black form so the kids can't use their laptop when the time is up.

Before I had this code in load form event:

C#:
 Bitmap bmp = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);
            using (Graphics G = Graphics.FromImage(bmp))
            {
                G.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
                G.CopyFromScreen(this.PointToScreen(new Point(0, 0)), new Point(0, 0), this.ClientRectangle.Size);
                double percent = 0.60;
                Color darken = Color.FromArgb((int)(255 * percent), Color.Black);
                using (Brush brsh = new SolidBrush(darken))
                {
                    G.FillRectangle(brsh, this.ClientRectangle);
                }

            }

            // put the darkened screenshot into a Panel and bring it to the front:
            using (Panel p = new Panel())
            {
                p.Location = new Point(0, 0);
                p.Size = this.ClientRectangle.Size;
                p.BackgroundImage = bmp;
                this.Controls.Add(p);
                p.BringToFront();

                // display your dialog somehow:
                TimeEndedForm timended = new TimeEndedForm();
                timended.Show();
            }

After is like this:

C#:
 Bitmap bmp = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);
            using (Graphics G = Graphics.FromImage(bmp))
            {
                G.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
                G.CopyFromScreen(this.PointToScreen(new Point(0, 0)), new Point(0, 0), this.ClientRectangle.Size);
                double percent = 0.60;
                Color darken = Color.FromArgb((int)(255 * percent), Color.Black);
                using (Brush brsh = new SolidBrush(darken))
                {
                    G.FillRectangle(brsh, this.ClientRectangle);
                }

            }

            // put the darkened screenshot into a Panel and bring it to the front:
            using (Panel p = new Panel())
            {
                int height = 0;
                int width = 0;
                foreach (Screen screen in Screen.AllScreens)
                {
                    //take smallest height
                    height = (screen.Bounds.Height <= height) ? screen.Bounds.Height : height;
                    width += screen.Bounds.Width;
                }

                p.Location = new Point(0, 0);
                this.Size = new Size(width, height);
                // p.Size = this.ClientRectangle.Size;
                p.Size = new Size(width, height);
                p.BackgroundImage = bmp;
                this.Controls.Add(p);
                p.BringToFront();

                // display your dialog somehow:
                TimeEndedForm timended = new TimeEndedForm();
                timended.Show();
            }

Both method don't help me that the transparent black form will be showed on all of the screens (if there are more than 1 screen, laptop screen and a separate screen).
The form just shows on the primary screen.

How can I do that on both screen will be showed?

Note: The TimeEndedForm is just for to able request more time if I am not at home so the kids can do things if they need something to do. Behind the TimeEndedForm appears the black transparent form/panel.

Thank you in advance all of the answers.
 
Solution
Alright.
I am satisfied what I got after playing around with the GetDesktopBoundse function whole week:

C#:
private static Rectangle GetDesktopBoundse(Form main)
            {
                Rectangle result = new Rectangle();
            for (int i = 0; i < Screen.AllScreens.Length; i++)
                {
                Screen screen = Screen.AllScreens[i];
                result = Rectangle.Union(result, screen.Bounds);
            }

            main.Top = result.Top;
            main.Left = result.Left;
            main.Width = result.Width;
            main.Height = result.Height;
            return result;
        }

I hope for other people will work this too if someone wants to make similar app.

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,921
Location
Sydney, Australia
Programming Experience
10+
C#:
Dim allBounds = Screen.AllScreens.Select(Function(s) s.Bounds).ToArray()
Dim minX = allBounds.Min(Function(s) s.X)
Dim minY = allBounds.Min(Function(s) s.Y)
Dim maxX = allBounds.Max(Function(s) s.X)
Dim maxY = allBounds.Max(Function(s) s.Y)
I'll leave it to you to figure out how to use that information.
 

Valakik

Member
Joined
Nov 8, 2020
Messages
12
Programming Experience
Beginner
1607860073855.png


If I put in label to see the size then it is correct. I have 1920x1080 screen settings on both screens but the form doesn't want to maximize to both screens, just staying on the primary screen.
I changed to this my code for now:

C#:
private void Background_Load(object sender, EventArgs e)
        {
            Rectangle desktopRect = GetDesktopBoundse();

            Bitmap bmp = new Bitmap(desktopRect.Width, desktopRect.Height);
            using (Graphics G = Graphics.FromImage(bmp))
            {
                G.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
                G.CopyFromScreen(this.PointToScreen(new Point(0, 0)), new Point(0, 0), desktopRect.Size);
                double percent = 0.60;
                Color darken = Color.FromArgb((int)(255 * percent), Color.Black);
                using (Brush brsh = new SolidBrush(darken))
                {
                        G.FillRectangle(brsh, desktopRect);
                }

            }
            

            // put the darkened screenshot into a Panel and bring it to the front:
            using (Panel p = new Panel())
            {
                 TopLevel = true;
                Size = new Size(desktopRect.Width, desktopRect.Height);
                p.Location = desktopRect.Location;
                //p.Size = this.ClientRectangle.Size;
                p.Size = desktopRect.Size;
                p.BackgroundImage = bmp;
                this.Controls.Add(p);
                p.BringToFront();

                // display your dialog somehow:
                TimeEndedForm timended = new TimeEndedForm();
                timended.TopMost = true;
                timended.Show();
            }
        }

        private static Rectangle GetDesktopBoundse()
            {
                Rectangle result = new Rectangle();
            for (int i = 0; i < Screen.AllScreens.Length; i++)
                {
                Screen screen = Screen.AllScreens[i];
                result = Rectangle.Union(result, screen.Bounds);
            }
                return result;
        }

I changed start position in the form properties to Manual and windowstate to Normal.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
3,386
Location
Chesapeake, VA
Programming Experience
10+
If you want a form for each screen, you'll need to put a form on each screen. (Time to learn about modeless dialog boxes.) The reason for this is that you should not try to maximize across multiple screens because there is no guarantees that the screens are symmetrically placed, have the same dot pitch, and do not have gaps. Imagine a user with one screen in landscape, and their second screen in portrait mode. There will be a missing rectangular chunk somewhere unless the height of one monitor is the width of the other monitor.
 

Valakik

Member
Joined
Nov 8, 2020
Messages
12
Programming Experience
Beginner
Alright.
I am satisfied what I got after playing around with the GetDesktopBoundse function whole week:

C#:
private static Rectangle GetDesktopBoundse(Form main)
            {
                Rectangle result = new Rectangle();
            for (int i = 0; i < Screen.AllScreens.Length; i++)
                {
                Screen screen = Screen.AllScreens[i];
                result = Rectangle.Union(result, screen.Bounds);
            }

            main.Top = result.Top;
            main.Left = result.Left;
            main.Width = result.Width;
            main.Height = result.Height;
            return result;
        }

I hope for other people will work this too if someone wants to make similar app.
 
Solution

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,921
Location
Sydney, Australia
Programming Experience
10+
You should not be setting those four properties separately. As you already have a Rectangle, you should simply set the Bounds property. If you had individual values then you'd call SetBounds.
 

Valakik

Member
Joined
Nov 8, 2020
Messages
12
Programming Experience
Beginner
Oh ok. Thank you.
For now how it is, works fine but if it will not work as should when I will put the app to the kids laptop then I will do as you recommended. Thanks. :)
 
Top Bottom