如何在 C# 和 WinForms 中将窗口居中显示?

155

我需要一种方法将当前窗口居中显示在屏幕上。

例如,如果用户按下一个按钮,我希望窗口能够自动居中在屏幕上。

我知道可以使用“startposition”属性来实现居中显示,但我无法找到方法使其在应用程序启动后也能生效。

那么如何将窗体居中显示在屏幕上呢?


1
你使用的是Win Forms吗? - Andrew Orsich
9
不要使用 Form.CenterToScreen 方法。有关详细信息,请参见此帖子。 - Artemix
1
在窗体类的构造函数中使用CenterToScreen()方法。 - webMac
1
尝试使用以下代码:StartPosition = FormStartPosition.CenterScreen; 或者 this.CenterToScreen(); - AliNajafZadeh
13个回答

230

8
在具有两个显示器的系统上,窗体将居中于当前光标所在的显示器上。因此,该窗体可能会突然跳转到另一个显示器上。请参见此处的帖子。 - Artemix
8
你所提及的文档确实写着“不要直接从你的代码中调用它”,但没有说明为什么。 - Stephen Turner
5
文档确实建议使用窗体的StartPosition属性来将其居中。这对我起作用了。 - John Kroetch
1
这个可以用,我只需要实例化它:this.CenterToScreen(); - Laki Politis
1
我也想知道为什么文档上说“不要直接从您的代码中调用此函数。” - Pete
1
如果将此代码行放置在以下代码行之后,它将无法正常工作:this.Location = Screen.AllScreens[0].WorkingArea.Location; - TK-421

189
  1. 使用 属性 窗口

    选择表单 → 转到属性窗口 → 选择 "起始位置" → 选择任何您想要的地方。

    "

  2. 编程方式

    Form form1 = new Form(); form1.StartPosition = FormStartPosition.CenterScreen; form1.ShowDialog();

    注意: 不要直接从代码中调用 Form.CenterToScreen()。请阅读这里


这并没有回答问题,因为它只是在启动时将表单居中,而不是在按下按钮时。 - Ola Ström

46
一个单独的行:
this.Location = new Point((Screen.PrimaryScreen.WorkingArea.Width - this.Width) / 2,
                          (Screen.PrimaryScreen.WorkingArea.Height - this.Height) / 2);

这展示了一种良好的方式手动获取“x”或“y”的中心。我需要“屏幕中心”,但仅适用于“y”坐标。 - atconway
12
为什么要用Screen.PrimaryScreen?如果窗体在“SecondaryScreen”上会怎样?你应该在这里使用Screen screen = Screen.FromControl(this); - Artemix
我使用这种原始技术只是因为它适用于.NET Compact Framework 3.5,并且这也解释了为什么我不使用Screen.FromControl(this)而保持使用PrimaryScreen。(我正在开发一款受硬件限制的应用程序) :-) - Yeo
如果您只使用一个屏幕,那么该方法是可以的。但是,如果您有多个显示器并在左侧显示器上单击快捷方式,则不希望它在右侧打开。StartPosition属性可以为您处理这个问题。 - Trevor_G
这并非【每个显示器的 DPI 感知】。 - vt.

37

在 Windows Forms 中:

this.StartPosition = FormStartPosition.CenterScreen;
在WPF中:
this.WindowStartupLocation = WindowStartupLocation.CenterScreen;

那就是你需要做的全部...


最佳解决方案。我不想设置位置,而是希望在回到表单时将其重置。这很完美。 - KangarooRIOT

26

如果你想在运行时居中你的窗口,请使用以下代码,并将其复制到你的应用程序中:

protected void ReallyCenterToScreen()
{
  Screen screen = Screen.FromControl(this);

  Rectangle workingArea = screen.WorkingArea;
  this.Location = new Point() {
    X = Math.Max(workingArea.X, workingArea.X + (workingArea.Width - this.Width) / 2),
    Y = Math.Max(workingArea.Y, workingArea.Y + (workingArea.Height - this.Height) / 2)};
}

最后调用上面的方法使其工作:

ReallyCenterToScreen();

这是最好的方法,因为即使在运行this.Location = Screen.AllScreens[0].WorkingArea.Location;之前,它也能正常工作。其他答案在使用多个屏幕时移动应用程序时不起作用。 - TK-421
这在我的电脑上使用3个显示器可以正常工作。 - ThePeter

9

居中运行时的表单



1. 将下列属性设置为Form:
   -> StartPosition : CenterScreen
   -> WindowState: Normal

这将使表单在运行时居中,但如果表单大小超出预期,请执行第二步。

2. 在InitializeComponent();之后添加自定义大小。

public Form1()
{
    InitializeComponent();
    this.Size = new Size(800, 600);
}

7
请使用以下内容:
this.CenterToScreen();  // This will take care of the current form

1
"-100. 不要直接从代码中调用CenterToScreen()方法。相反,将StartPosition属性设置为CenterScreen。" - A876

6
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace centrewindow
{
    public partial class Form1 : Form
    {
        public struct RECT
        {
            public int Left;        // x position of upper-left corner
            public int Top;         // y position of upper-left corner
            public int Right;       // x position of lower-right corner
            public int Bottom;      // y position of lower-right corner
        }

        [DllImport("user32.dll")]
        public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);

        [DllImport("user32.dll")]
        public static extern bool GetWindowRect(HandleRef hwnd, out RECT lpRect);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            CentreWindow(Handle, GetMonitorDimensions());
        }

        private void CentreWindow(IntPtr handle, Size monitorDimensions)
        {
            RECT rect;
            GetWindowRect(new HandleRef(this, handle), out rect);

            var x1Pos = monitorDimensions.Width/2 - (rect.Right - rect.Left)/2;
            var x2Pos = rect.Right - rect.Left;
            var y1Pos = monitorDimensions.Height/2 - (rect.Bottom - rect.Top)/2;
            var y2Pos = rect.Bottom - rect.Top;

            SetWindowPos(handle, 0, x1Pos, y1Pos, x2Pos, y2Pos, 0);
        }

        private Size GetMonitorDimensions()
        {
            return SystemInformation.PrimaryMonitorSize;
        }
    }
}

居中任何您可以获得句柄的窗口。

4

这可能与问题不完全相关,但也许可以帮助某些人。

对于我来说,居中屏幕的方法都不起作用。原因是我在动态向表单添加控件。从技术上讲,当它居中时,它是正确的,基于添加控件之前的表单。

所以这是我的解决方案。(应该适用于两种情况)

int x = Screen.PrimaryScreen.Bounds.Width - this.PreferredSize.Width;
int y = Screen.PrimaryScreen.Bounds.Height - this.PreferredSize.Height;

this.Location = new Point(x / 2, y / 2);

你会注意到我使用的是"PreferredSize"而不仅仅是使用高度/宽度。首选大小将保存添加控件后表单的值,而高度/宽度则不会。
希望这能帮助到某个人。
干杯!

3

实际样例

private void barButtonItem1_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
    AccountAddForm f = new AccountAddForm();
    f.StartPosition = FormStartPosition.CenterScreen;
    f.Show();            
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接