如何获取窗口最小化、最大化和关闭按钮的尺寸?

6

到目前为止,我尝试使用GetThemePartSize、GetThemeMetric、GetSystemMetrics、WM_GETTITLEBARINFOEX通过SendMessage和其他几个调用,但是没有一个能够接近真实的尺寸(启用主题的Windows 7)。

基本上我的问题是:如何获取这些按钮的大小(和位置,最好还有句柄),以及从GetThemePartSize检索到的值是什么意思?它们有什么用处?

我已经查看了这个答案和许多其他答案,但它们根本不起作用。

谢谢

更新

对于汉斯:

[DllImport("uxtheme", ExactSpelling=true)]
private extern static Int32 GetThemePartSize(IntPtr hTheme, IntPtr hdc, WindowPart part, WindowPartState state, ref RECT pRect, ThemeSize eSize, out SIZE size);

[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
    public int left; 
    public int top; 
    public int right;
    public int bottom;
}

[StructLayout(LayoutKind.Sequential)]
private struct SIZE
{
    public int cx;
    public int cy;
} 

private const int TS_TRUE = 1;
private const int CBS_NORMAL = 1;
private const int WP_CLOSEBUTTON = 18;
private const string VSCLASS_WINDOW = "WINDOW";

/* inside a method */
var rect = new RECT {left = 0, right = 200, top = 0, bottom = 200};
var size = new SIZE();
var windowHandle = new WindowInteropHelper({MyWindow}).Handle;
var theme = OpenThemeData(windowHandle, VSCLASS_WINDOW);
GetThemePartSize(theme, null, WP_CLOSEBUTTON, CBS_NORMAL, ref rect, TS_TRUE, ref size);

// result on w7 with default theme -> size.cx == 28, size.cy == 17

你打算如何处理这些信息? - siride
嗨,siride。这些问题已经在网络上反复提出了很多次,但我仍然找不到令人满意的答案。此外,有关该主题的MSDN条目和API描述最多只能算是平庸(尽管catch22.net为旧操作系统提供了一个不错的示例)。因此,首先驱使我的是好奇心。我的个人目标是准确测量左到右系统上方右侧菜单所占用的空间,并根据WPF演示应用程序中可用的空间放置/隐藏/调整控件。 - UnclePaul
2
有很多方法可以让这段代码出错。没有人能看到它。当你甚至没有指定需要的语言时,避免询问“发送给我代码”的问题。发布一小段代码片段,这些问题就会变得明显。 - Hans Passant
谢谢Hans的回复。有很多方法可以正确获取代码。而且也没有人需要看到它。不要认为一切都是关于某个人想让你交出代码。如果有人发布了一个问题,请仔细阅读并理解其意图。如果你这样做了,你就会看到.NET标签和链接(其中包括C、C++和Delphi的示例)。所以也许这个问题故意不局限于特定的语言,也许这个问题不是关于一些教材,而是急于理解底层概念? - UnclePaul
2个回答

2

在浏览Firefox 17.0.1源代码(即文件nsNativeThemeWin.cpp和nsUXThemeData.cpp)后,我能够提供一个部分解决方案,适用于运行在Vista或更新版本上的桌面应用程序,满足我的需求:

private const int DWMWA_CAPTION_BUTTON_BOUNDS = 5;

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int left;
    public int top;
    public int right; 
    public int bottom;
}

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

var windowHandle = new WindowInteropHelper(Main.Instance).Handle;
var buttonsRect = new RECT();
var sizeButtonsRect = Marshal.SizeOf(buttonsRect);
DwmGetWindowAttribute(windowHandle, DWMWA_CAPTION_BUTTON_BOUNDS, out buttonsRect, sizeButtonsRect);

存储在buttonsRect中的结果有些奇怪:宽度差(right - left == 105)恰好符合实际边界,然而高度差(29px)比按钮实际占据的区域大8像素。
由于这并不能完全回答任何问题,我将保留此帖子以便进一步回复。再次感谢Hans无价且深思熟虑的评论。正如您清楚地看到的,这一切都与编程语言和代码片段有关。

1

1
我查看了这两个框架,它们在它们所做的事情方面可能非常出色,但如果我没有弄错,它们基本上是改变客户区并绘制/放置自己的按钮。这确实可能是一种可行的解决方法,但由于问题是关于如何访问和计算各个按钮的大小,因此我不能将其标记为答案。无论如何+1,因为这两个项目都是使用玻璃上的Aero的好资源。 - UnclePaul

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