【问题标题】:Closing and opening a Form on the same monitor on dual monitor setups在双显示器设置的同一显示器上关闭和打开表单
【发布时间】:2012-07-21 17:56:15
【问题描述】:

我一直在四处寻找,发现这两篇文章:

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

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

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

【问题讨论】:

  • 据我所见,这两个示例都存储了 form 关闭时的窗口位置,而不是应用程序。
  • 注意分配属性的顺序。 首先设置Location,然后设置WindowState。反过来做就错了。
  • @HansPassant 你是对的。这只是以正确的顺序设置值的问题。非常感谢。

标签: c# winforms


【解决方案1】:

我创建了一个扩展方法,无论您是关闭应用程序还是仅关闭当前窗口都可以使用。我在 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;
                }
            }
    }

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      试试这个...

      (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;
                  }
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-01-10
          相关资源
          最近更新 更多