C#: How to make a form remember its Bounds and WindowState (Taking dual monitor setups into account)

前端 未结 4 835
说谎
说谎 2020-12-15 10:51

I have made a class which a form can inherit from and it handles form Location, Size and State. And it works nicely. Except for one thing:

When you maximize the app

相关标签:
4条回答
  • 2020-12-15 11:28

    There are a few issues with the above solution.

    On multiple screens as well as if the restore screen is smaller.

    It should use Contains(...), rather than IntersectsWith as the control part of the form might otherwise be outside the screen-area.

    I will suggest something along these lines

    bool TestBounds(Rectangle R) {
        if (MdiParent == null) return Screen.AllScreens.Any(ø => ø.Bounds.Contains(R)); // If we don't have an MdiParent, make sure we are entirely on a screen
        var c = MdiParent.Controls.OfType<MdiClient>().FirstOrDefault(); // If we do, make sure we are visible within the MdiClient area
        return (c != null && c.ClientRectangle.Contains(R));
    }
    

    and used like this. (Note that I let Windows handle it if the saved values does not work)

    bool BoundsOK=TestBounds(myBounds);
    if (!BoundsOK) {
        myBounds.Location = new Point(8,8); // then try (8,8) , to at least keep the size, if other monitor not currently present, or current is lesser
        BoundsOK = TestBounds(myBounds);
    }
    if (BoundsOK) { //Only change if acceptable, otherwise let Windows handle it
        StartPosition = FormStartPosition.Manual;
        Bounds = myBounds;
        WindowState = Enum.IsDefined(typeof(FormWindowState), myWindowState) ? (FormWindowState)myWindowState : FormWindowState.Normal;
    }
    
    0 讨论(0)
  • 2020-12-15 11:32

    I found a solution to your problem by writing a little functio, that tests, if a poitn is on a connected screen. The main idea came from http://msdn.microsoft.com/en-us/library/system.windows.forms.screen(VS.80).aspx but some modifications were needed.

    public static bool ThisPointIsOnOneOfTheConnectedScreens(Point thePoint)
        {
            bool FoundAScreenThatContainsThePoint = false;
    
            for(int i = 0; i < Screen.AllScreens.Length; i++)
            {
                if(Screen.AllScreens[i].Bounds.Contains(thePoint))
                    FoundAScreenThatContainsThePoint = true;
            }
            return FoundAScreenThatContainsThePoint;
        }
    
    0 讨论(0)
  • 2020-12-15 11:50

    There's no built in way to do this - you'll have to write the logic yourself. One reason for this is that you have to decide how to handle the case where the monitor that the window was last shown on is no longer available. This can be quite common with laptops and projectors, for example. The Screen class has some useful functionality to help with this, although it can be difficult to uniquely and consistently identify a display.

    0 讨论(0)
  • 2020-12-15 11:51

    Try to spawn your main form in its saved location in restored (non-maximized) state, THEN maximize it if the last state was maximized.

    As Stu said, be careful about removed monitors in this case. Since the saved location may contain off-screen coordinates (even negative ones), you may effectively end up with and invisible (off-screen, actually) window. I think checking for desktop bounds before loading previous state should prevent this.

    0 讨论(0)
提交回复
热议问题