使用多个监视器还原窗口大小/位置 [英] Restoring Window Size/Position With Multiple Monitors

查看:80
本文介绍了使用多个监视器还原窗口大小/位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

许多关于恢复WinForm位置和大小的帖子。

Many posts around about restoring a WinForm position and size.

示例:

  • www.stackoverflow.com/questions/92540/save-and-restore-form-position-and-size
  • www.codeproject.com/KB/dialog/restoreposition.aspx?fid=1249382&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2595746

但是我还没有找到可以在多台监视器上执行此操作的代码。

But I have yet to find code to do this with multiple monitors.

也就是说,如果我用监视器2上的窗口关闭.NET Winform应用程序,则需要它将窗口的大小,位置和状态保存为应用程序设置,以便稍后在我重新启动应用程序时可以将其还原到监视器2。就像上面的代码项目示例一样,如果它包括一些完整性检查,那就好了,就像保存的位置大部分在屏幕外一样,它可以修复它。或者,如果保存的位置位于不再存在的显示器上(例如,现在我的笔记本电脑本身就没有第二台显示器),那么它将正确地移动到显示器1。

That is, if I close my .NET Winform app with the window on monitor 2, I want it to save the windows size, location, and state to the application settings, so it could later restore to monitor 2 when I restart the app. It would be nice if, like in the codeproject example above, it includes some sanity checks, as in if the saved location is mostly off-screen it "fixes" it. Or if the saved location is on a monitor that is no longer there (e.g. my laptop is now by itself without my second monitor) then it correctly moves it to monitor 1.

有任何想法吗?

我的环境:C#、. NET 3.5或更低版本,VS2008

My environment: C#, .NET 3.5 or below, VS2008

推荐答案

VVS提供的答案很有帮助!不过,我发现了两个小问题,因此我将这些修订版本重新发布到他的大部分代码中:

The answer provided by VVS was a great help! I found two minor issues with it though, so I am reposting the bulk of his code with these revisions:

(1)应用程序第一次运行时,该表单以正常状态打开,但其大小使其仅显示为标题栏。我在构造函数中添加了一个条件来解决此问题。

(1) The very first time the application runs, the form is opened in a Normal state but is sized such that it appears as just a title bar. I added a conditional in the constructor to fix this.

(2)如果在最小化或最大化时关闭了应用程序,则OnClosing中的代码无法记住窗口的尺寸处于正常状态。 (我现在已注释掉的三行代码似乎是合理的,但由于某些原因无法正常工作。)幸运的是,我之前已经解决了这个问题,并将该代码包含在代码的新区域中。跟踪窗口状态,而不是等待关闭。

(2) If the application is closed while minimized or maximized the code in OnClosing fails to remember the dimensions of the window in its Normal state. (The 3 lines of code--which I have now commented out--seems reasonable but for some reason just does not work.) Fortunately I had previously solved this problem and have included that code in a new region at the end of the code to track window state as it happens rather than wait for closing.

有了这两个修复程序,我已经测试了:

With these two fixes in place, I have tested:

A。在正常状态下关闭-恢复为相同的大小/位置和状态

A. closing in normal state--restores to same size/position and state

B。在最小化状态下关闭-恢复到具有最后一个正常大小/位置的正常状态

B. closing in minimized state--restores to normal state with last normal size/position

C。在最大化状态下关闭-恢复到最大化状态,并在以后调整为正常状态时记住其最后的大小/位置。

C. closing in maximized state--restores to maximized state and remembers its last size/position when one later adjusts to normal state.

D。在监视器2上关闭-恢复到监视器2。

D. closing on monitor 2--restores to monitor 2.

E。在监视器2上关闭然后断开监视器2的连接,将其恢复到监视器1上的相同位置

E. closing on monitor 2 then disconnecting monitor 2--restores to same position on monitor 1

David:您的代码使我几乎毫不费力地达到了D点和E点您是否为我的问题提供了解决方案,您是否在完整的程序中提供了解决方案,所以我将其粘贴到Visual Studio的几秒钟内就可以启动并运行。

David: your code allowed me to achieve points D and E almost effortlessly--not only did you provide a solution for my question, you provided it in a complete program so I had it up and running almost within seconds of pasting it into Visual Studio. So a big thank you for that!

public partial class MainForm : Form
{
    bool windowInitialized;

    public MainForm()
    {
        InitializeComponent();

        // this is the default
        this.WindowState = FormWindowState.Normal;
        this.StartPosition = FormStartPosition.WindowsDefaultBounds;

        // check if the saved bounds are nonzero and visible on any screen
        if (Settings.Default.WindowPosition != Rectangle.Empty &&
            IsVisibleOnAnyScreen(Settings.Default.WindowPosition))
        {
            // first set the bounds
            this.StartPosition = FormStartPosition.Manual;
            this.DesktopBounds = Settings.Default.WindowPosition;

            // afterwards set the window state to the saved value (which could be Maximized)
            this.WindowState = Settings.Default.WindowState;
        }
        else
        {
            // this resets the upper left corner of the window to windows standards
            this.StartPosition = FormStartPosition.WindowsDefaultLocation;

            // we can still apply the saved size
            // msorens: added gatekeeper, otherwise first time appears as just a title bar!
            if (Settings.Default.WindowPosition != Rectangle.Empty)
            {
                this.Size = Settings.Default.WindowPosition.Size;
            }
        }
        windowInitialized = true;
    }

    private bool IsVisibleOnAnyScreen(Rectangle rect)
    {
        foreach (Screen screen in Screen.AllScreens)
        {
            if (screen.WorkingArea.IntersectsWith(rect))
            {
                return true;
            }
        }

        return false;
    }

    protected override void OnClosed(EventArgs e)
    {
        base.OnClosed(e);

        // only save the WindowState if Normal or Maximized
        switch (this.WindowState)
        {
            case FormWindowState.Normal:
            case FormWindowState.Maximized:
                Settings.Default.WindowState = this.WindowState;
                break;

            default:
                Settings.Default.WindowState = FormWindowState.Normal;
                break;
        }

        # region msorens: this code does *not* handle minimized/maximized window.

        // reset window state to normal to get the correct bounds
        // also make the form invisible to prevent distracting the user
        //this.Visible = false;
        //this.WindowState = FormWindowState.Normal;
        //Settings.Default.WindowPosition = this.DesktopBounds;

        # endregion

        Settings.Default.Save();
    }

    # region window size/position
    // msorens: Added region to handle closing when window is minimized or maximized.

    protected override void OnResize(EventArgs e)
    {
        base.OnResize(e);
        TrackWindowState();
    }

    protected override void OnMove(EventArgs e)
    {
        base.OnMove(e);
        TrackWindowState();
    }

    // On a move or resize in Normal state, record the new values as they occur.
    // This solves the problem of closing the app when minimized or maximized.
    private void TrackWindowState()
    {
        // Don't record the window setup, otherwise we lose the persistent values!
        if (!windowInitialized) { return; }

        if (WindowState == FormWindowState.Normal)
        {
            Settings.Default.WindowPosition = this.DesktopBounds;
        }
    }

    # endregion window size/position
}

这篇关于使用多个监视器还原窗口大小/位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆