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的笔记本电脑上工作。
请参阅以下内容:
我猜你正在尝试计算你必须制作应用程序窗口的大小,以便给出适量的客户区来完整显示一些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;