在双显示器设置的同一台显示器上关闭并打开表格

时间:2012-07-23 13:30:06

标签: c# winforms

我一直在环顾四周,发现了这两篇文章:

问题是这些文章在我的问题的球场,但我不能使用它,因为我看到它(除非我让我的解决方案真的很复杂)。虽然文章谈到在完全关闭应用程序时恢复表单,但这并不是我想要完成的。

我正在做的是在同一个正在运行的应用程序中关闭并打开相同的表单。当发生这种情况时,我希望它具有与我关闭时相同的确切位置,状态和大小。这很简单,因为我可以从表单对象中保存位置,状态和大小,将其丢弃并将旧值应用于我的新表单。这样可行,但如果我在监视器2上有一个最大化窗口,并且关闭/打开功能运行,它将在监视器1上打开最大化的窗体。

在上面的案例中,有没有简单的方法将它保存在监视器2上,或者我是否需要深入了解复杂的库?

4 个答案:

答案 0 :(得分:1)

如果我是你,我会认为你的问题是这些链接问题的简单扩展,唯一的变化是你的应用程序没有被关闭 - 只有窗口是(所以你不需要保留这些信息到磁盘,只需将其保存在内存中。)

原因是用户可以(并且最终其中一个可能会)更改显示配置(显示器数量,显示位置等...)在您的应用程序运行时(例如笔记本电脑用户)拔掉外部屏幕),所以如果你不考虑这一点,你最终会把你的窗户放在屏幕上,用户无法访问它们。

答案 1 :(得分:0)

试试这个......

(Form2是您要定位的表单。根据需要进行修改。)

using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form2 : Form
    {
        static System.Drawing.Point _location = new Point();
        static System.Drawing.Size _size;
        static FormWindowState _state;

        public Form2()
        {
            InitializeComponent();

            this.Load += new EventHandler( Form2_Load );
            this.FormClosing += new FormClosingEventHandler( Form2_FormClosing );
        }

        void Form2_Load( object sender, EventArgs e )
        {
            // Restore the Form's position.
            //
            // Handle possibility that our previous screen location is no longer valid for
            // the current display environment (i.e., multiple->single display system).
            //

            Point location = _location;

            if ( location == new Point( 0, 0 ) || !IsScreenLocationValid( location ) )
            {
                if ( null != this.Parent )
                    this.StartPosition = FormStartPosition.CenterParent;
                else
                    this.StartPosition = FormStartPosition.CenterScreen;
            }
            else
            {
                this.Location = location;

                // Ensure that the Form's size is not smaller than its minimum allowed.
                //

                Size size = _size;

                size.Width = System.Math.Max( size.Width, this.MinimumSize.Width );
                size.Height = System.Math.Max( size.Height, this.MinimumSize.Height );

                this.Size = size;
            }

            // Only restore the Form's window state if it is not minimized.
            // (If we restore it as minimized, the user won't see it).
            //
            if ( _state == FormWindowState.Normal || _state == FormWindowState.Maximized )
            {
                this.WindowState = _state;
            }
        }

        /// <summary>
        /// Determines if the given screen location is valid for the current display system.
        /// </summary>
        /// <param name="location">A Point object describing the location</param>
        /// <returns>True if the location is valid; otherwise, false</returns>
        static bool IsScreenLocationValid( Point location )
        {
            Rectangle screenBounds = System.Windows.Forms.Screen.GetBounds( location );

            return screenBounds.Contains( location );
        }

        void Form2_FormClosing( object sender, FormClosingEventArgs e )
        {
            _state = this.WindowState;

            if ( _state == FormWindowState.Normal )
            {
                _location = this.Location;
                _size = this.Size;
            }
            else
            {
                _location = this.RestoreBounds.Location;
                _size = this.RestoreBounds.Size;
            }
        }
    }
}

答案 2 :(得分:0)

在原帖中的评论中遵循Hans Passant说明,并正确设置值解决了问题。我现在在Forms OnLoad事件中喜欢这个:

if(UseGivenpositioningValues)
{
    Location = OverrideLocation;
    if (OverrideWindowState == FormWindowState.Normal)
        Size = OverrideSize;
    WindowState = OverrideWindowState;
    UseGivenpositioningValues = false;
}

位置优先,然后是州。 Justin在他的回答中指出,这不是一个完美的解决方案,因为用户可以更改他的设置,然后如果用户更改其设置,则表单可能会出现在屏幕外。但是在我的具体情况下,这不是问题。

答案 3 :(得分:0)

我创建了一个扩展方法,无论您是关闭应用还是仅关闭当前窗口,它都会起作用。我在form_load事件上调用RestoreLastLocation,在form_closing事件上调用SaveLastLocation。这是旧代码,所以如果它有点粗糙,我道歉。

    public static void SaveLastLocation(this Form form, string UniqueName)
    {
        FormWindowState CurState = form.WindowState;
        if (CurState == FormWindowState.Minimized)
            CurState = FormWindowState.Normal;

        form.WindowState = FormWindowState.Normal;

        if (Properties.Settings.Default.WindowSettings == null)
            Properties.Settings.Default.WindowSettings = new System.Collections.Specialized.StringCollection();

        if(Properties.Settings.Default.WindowSettings.Count > 0)
            foreach (string S in Properties.Settings.Default.WindowSettings)
                if (S.Split('|').First().ToLower() == UniqueName.ToLower())
                {
                    Properties.Settings.Default.WindowSettings.Remove(S);
                    break;
                }

        Properties.Settings.Default.WindowSettings.Add(string.Format("{0}|{1}|{2}|{3}|{4}|{5}",
            UniqueName, form.Top.ToString(), form.Left.ToString(), form.Height.ToString(), form.Width.ToString(), form.WindowState.ToString()));

        Properties.Settings.Default.Save();
    }

    public static void RestoreLastLocation(this Form form, string UniqueName)
    {
        if (Properties.Settings.Default.WindowSettings != null && Properties.Settings.Default.WindowSettings.Count > 0)
            foreach (string S in Properties.Settings.Default.WindowSettings)
            {
                string[] Parts = S.Split('|');
                if (Parts[0].ToLower() == UniqueName.ToLower())
                {
                    form.Top = int.Parse(Parts[1]);
                    form.Left = int.Parse(Parts[2]);
                    form.Height = int.Parse(Parts[3]);
                    form.Width = int.Parse(Parts[4]);
                    form.WindowState = (FormWindowState)Enum.Parse(typeof(FormWindowState), Parts[5]);
                    break;
                }
            }
    }