表单位置和大小行为

c45*_*1u5 6 .net c# forms location winforms

我想将表单放置在屏幕的左上角。

我已经尝试过this.Location = new Point(0,0),但窗口位于 (7,0) - 窗口顶部位于屏幕顶部,但左侧距离屏幕边缘 7 个像素。我创建了新的 WinForms 应用程序进行测试,并仅添加了以下代码:

private void Form1_Load(object sender, EventArgs e)
{
    Point p = new Point(0, 0);

    WindowState = FormWindowState.Maximized;
    Debug.WriteLine("\nMaximized");
    Debug.WriteLine("Location: " + Location);
    Debug.WriteLine("Size: " + Size);
    Debug.WriteLine("PointToScreen(0,0): " + PointToScreen(p));

    WindowState = FormWindowState.Normal;
    Location = p;            
    Debug.WriteLine("\nNormal");
    Debug.WriteLine("Location: " + Location);
    Debug.WriteLine("Size: " + Size);
    Debug.WriteLine("PointToScreen(0,0): " + PointToScreen(p));

    Debug.Write("\nScreen.PrimaryScreen.WorkingArea: ");
    Debug.WriteLine(Screen.PrimaryScreen.WorkingArea);
}
Run Code Online (Sandbox Code Playgroud)

输出是:

Maximized  
Location: {X=-8,Y=-8}  
Size: {Width=1936, Height=1056}
PointToScreen(0,0): {X=0,Y=23}

Normal
Location: {X=0,Y=0}
Size: {Width=300, Height=300}
PointToScreen(0,0): {X=8,Y=31}

Screen.PrimaryScreen.WorkingArea: {X=0,Y=0,Width=1920,Height=1040}
Run Code Online (Sandbox Code Playgroud)

为什么Location = new Point(0,0)位置不在 (0,0) 上形成?这是由于我的系统上的某些原因造成的吗?我有Win10和VS2015。任务栏在底部,我的桌面左侧没有任何东西。为了将其定位在 (0,0) 上,我实际上必须将其定位在 (-7,0) 上。此外,报告的最大化表单宽度比屏幕宽度大 16 像素。我知道由于窗口边缘、标题栏等原因,客户区域大小和表单大小之间存在差异,但事实并非如此。当表单最大化时,没有左右边缘(客户区宽度 = 桌面宽度),但表单宽度为 +16px。表格 4 条边各有 +8px,但 Y 位置还可以。为什么 Y 位置可以,而 X 位置不行?

c45*_*1u5 5

感谢Uwe Keim和他自己对问题的回答,我创建了计算偏移量并正确设置表单位置的函数,无论 Windows 版本如何(即边框大小):MoveForm

    void MoveForm(Point p)   // Move form to point 'p'
    {
        this.WindowState = FormWindowState.Normal;
        this.Location = new Point(0, 0);
        Rectangle rec = WindowHelper.GetWindowRectangle(this.Handle);
        p.Offset(-rec.Location.X, -rec.Location.Y);
        this.Location = p;
    }
Run Code Online (Sandbox Code Playgroud)

MoveForm函数使用Uwe Keim帖子WindowHelper的类:

public static class WindowHelper
{
    // https://code.google.com/p/zscreen/source/browse/trunk/ZScreenLib/Global/GraphicsCore.cs?r=1349

    /// <summary>
    /// Get real window size, no matter whether Win XP, Win Vista, 7 or 8.
    /// </summary>
    public static Rectangle GetWindowRectangle(IntPtr handle)
    {
        if (Environment.OSVersion.Version.Major < 6)
        {
            return GetWindowRect(handle);
        }
        else
        {
            Rectangle rectangle;
            return DWMWA_EXTENDED_FRAME_BOUNDS(handle, out rectangle) ? rectangle : GetWindowRect(handle);
        }
    }

    [DllImport(@"dwmapi.dll")]
    private static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out Rect pvAttribute, int cbAttribute);

    private enum Dwmwindowattribute
    {
        DwmwaExtendedFrameBounds = 9
    }

    [Serializable, StructLayout(LayoutKind.Sequential)]
    private struct Rect
    {
        // ReSharper disable MemberCanBePrivate.Local
        // ReSharper disable FieldCanBeMadeReadOnly.Local
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
        // ReSharper restore FieldCanBeMadeReadOnly.Local
        // ReSharper restore MemberCanBePrivate.Local

        public Rectangle ToRectangle()
        {
            return Rectangle.FromLTRB(Left, Top, Right, Bottom);
        }
    }

    private static bool DWMWA_EXTENDED_FRAME_BOUNDS(IntPtr handle, out Rectangle rectangle)
    {
        Rect rect;
        var result = DwmGetWindowAttribute(handle, (int)Dwmwindowattribute.DwmwaExtendedFrameBounds,
            out rect, Marshal.SizeOf(typeof(Rect)));
        rectangle = rect.ToRectangle();
        return result >= 0;
    }

    [DllImport(@"user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool GetWindowRect(IntPtr hWnd, out Rect lpRect);

    private static Rectangle GetWindowRect(IntPtr handle)
    {
        Rect rect;
        GetWindowRect(handle, out rect);
        return rect.ToRectangle();
    }
}
Run Code Online (Sandbox Code Playgroud)


MSL*_*MSL 0

我解决了这个问题。

刚刚设置

this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;

并测试结果。对我来说是这样的:

Maximized
Location: {X=0,Y=0}
Size: {Width=1280, Height=800}
PointToScreen(0,0): {X=0,Y=0}

Normal
Location: {X=0,Y=0}
Size: {Width=477, Height=321}
PointToScreen(0,0): {X=0,Y=0}
Run Code Online (Sandbox Code Playgroud)

一切都与边界有关。

看这个