我如何计算WPF中的非客户端窗口大小?

WPF的SystemParameters类公开了大量的系统度量标准。 在我的电脑上,我注意到一个普通的窗口有一个30像素高的标题和一个8像素宽的边框。 这是在启用了Aero主题的Windows 7上:

非客户区域 - 航空

但是, SystemParameters返回以下值:

 SystemParameters.BorderWidth = 5 SystemParameters.CaptionHeight = 21 

在这里我禁用了Aero主题:

非客户区 - 经典

现在, SystemParameters返回以下值:

 SystemParameters.BorderWidth = 1 SystemParameters.CaptionHeight = 18 

如何通过使用SystemParameters来计算实际观察值?

对于可调整大小的窗口,您需要使用一组不同的参数来计算大小:

 var titleHeight = SystemParameters.WindowCaptionHeight + SystemParameters.ResizeFrameHorizontalBorderHeight; var verticalBorderWidth = SystemParameters.ResizeFrameVerticalBorderWidth; 

当您修改主题时,这些大小将会改变。

我非常肯定, GetSystemMetrics函数 ( SystemParameters类在内部调用适当的参数) 正在为系统返回正确的值,只是在Aero主题被禁用的情况下返回正确的值。 通过打开航空,你会得到更强大的边界和更高的窗口标题,所有的多汁的图形善良的名字。

如果你想获得这些窗口元素的正确大小,不管用户当前的主题是什么(记住,你可以运行Windows Vista及更高版本的经典主题,Aero基本主题,或完整的Aero主题,所有这些都是有不同大小的用户界面元素),你需要使用Vista和以后的不同方法。

您需要发送一个WM_GETTITLEBARINFOEX消息的窗口,以请求扩展标题栏信息。 wParam没有使用,应该是零。 lParam包含一个指向TITLEBARINFOEX结构的指针,它将接收所有的信息。 调用者负责为这个结构分配内存并设置它的cbSize成员。

为了从.NET应用程序中完成所有这些,你显然需要做一些P / Invoke。 首先定义你需要的常量,以及TITLEBARINFOEX结构:

 internal const int WM_GETTITLEBARINFOEX = 0x033F; internal const int CCHILDREN_TITLEBAR = 5; [StructLayout(LayoutKind.Sequential)] internal struct TITLEBARINFOEX { public int cbSize; public Rectangle rcTitleBar; [MarshalAs(UnmanagedType.ByValArray, SizeConst = CCHILDREN_TITLEBAR + 1)] public int[] rgstate; [MarshalAs(UnmanagedType.ByValArray, SizeConst = CCHILDREN_TITLEBAR + 1)] public Rectangle[] rgrect; } 

然后相应地定义SendMessage函数:

 [DllImport("user32.dll", CharSet = CharSet.Auto)] internal static extern IntPtr SendMessage( IntPtr hWnd, int uMsg, IntPtr wParam, ref TITLEBARINFOEX lParam); 

最后,你可以使用类似下面的代码来调用所有的混乱:

 internal static TITLEBARINFOEX GetTitleBarInfoEx(IntPtr hWnd) { // Create and initialize the structure TITLEBARINFOEX tbi = new TITLEBARINFOEX(); tbi.cbSize = Marshal.SizeOf(typeof(TITLEBARINFOEX)); // Send the WM_GETTITLEBARINFOEX message SendMessage(hWnd, WM_GETTITLEBARINFOEX, IntPtr.Zero, ref tbi); // Return the filled-in structure return tbi; } 

编辑:现在测试和运行Windows 7的笔记本电脑上工作。

请参阅以下内容:

http://blogs.microsoft.co.il/blogs/alex_golesh/archive/2009/09/20/wpf-quick-tip-how-to-get-wpf-window-client-area-size.aspx

我猜你正在尝试计算你必须制作应用程序窗口的大小,以便给出适量的客户区来完整显示一些WPF内容?

如果是这样的话,那么请记住,WPF的像素是在96dpi,你的显示器可能在不同的dpi运行…也正如其他答案所提到的主题影响有多大,你必须调整主窗口的大小来得到你想要的客户区。

或者,您可能能够在窗口的子控件上使用MinWidth / MinHeight。

对于大尺寸的窗户

 NON_CLIENT_AREA_HEIGHT = SystemParameters.WindowNonClientFrameThickness.Top + SystemParameters.WindowNonClientFrameThickness.Bottom + SystemParameters.WindowResizeBorderThickness.Top + SystemParameters.WindowResizeBorderThickness.Bottom; NON_CLIENT_AREA_WIDTH = SystemParameters.WindowNonClientFrameThickness.Left + SystemParameters.WindowNonClientFrameThickness.Right + SystemParameters.WindowResizeBorderThickness.Left + SystemParameters.WindowResizeBorderThickness.Right;