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 位置不行?
感谢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)
我解决了这个问题。
刚刚设置
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)
一切都与边界有关。
归档时间: |
|
查看次数: |
3065 次 |
最近记录: |