4

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

问题是这些文章在我的问题的范围内,但我不能像我看到的那样使用它们(除非我让我的解决方案变得非常复杂)。虽然这篇文章谈到了在他们完全关闭应用程序时恢复表单,但这并不是我想要完成的任务。

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

在上述情况下,是否有任何简单的方法可以将其保留在监视器 2 上,还是我必须深入研究复杂的库?

4

4 回答 4

1

If I were you I would consider your problem to be a simple extension of those linked questions, the only change being that your application isn't being closed - only the window is (so you don't need to persist this information to disk, just keep it in memory).

The reason being that users can (and eventually one of them probably will) change display configuration (number of displays, display positions etc...) while your application is running (e.g. a laptop user unplugging an external screen), and so if you don't take this into account you will end up positioning your windows off screen where they can't be accessed by the user.

于 2012-07-23T15:02:25.600 回答
1

尝试这个...

(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;
            }
        }
    }
}
于 2012-07-23T22:40:02.767 回答
0

按照原始帖子评论中的 Hans Passant 说明,正确设置值可以解决问题。我现在在我的 Forms OnLoad 事件中这样做:

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

首先是位置,然后是状态。正如贾斯汀在他的回答中指出的那样,这不是一个完美的解决方案,因为用户可以更改他的设置,然后如果用户更改他的设置,表单可能会出现在屏幕外。但是,在我的具体情况下,这不是问题。

于 2012-07-24T06:23:31.687 回答
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;
                }
            }
    }
于 2015-08-07T13:20:16.263 回答