【问题标题】:How to retrieve the size of the Minimize, Maximize and Close button of a Window?如何检索窗口的最小化、最大化和关闭按钮的大小?
【发布时间】:2012-12-16 05:20:30
【问题描述】:

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

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

我已经看过this answer 和许多其他人,但它们根本不起作用。

谢谢

更新

对于汉斯:

[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。这些问题在网上被问了一遍又一遍,但我找不到任何令人满意的答案。此外,关于该主题的 MSDN 条目和 API 描述充其量是平庸的(尽管 catch22.net 为旧操作系统提供了一个很好的示例)。所以首先是好奇心驱使我。我的个人目标是准确测量右上角菜单占用的空间(在从左到右的系统上)并根据 WPF 演示应用程序中的可用空间在其旁边放置/隐藏/调整控件大小。
  • 有很多方法可以让这段代码出错。没有人能看到它。当您甚至没有指定您需要的语言时,请避免询问“发送我的代码”问题。发布一个 sn-p,让这些事情变得显而易见。
  • 感谢汉斯的回复。有很多方法可以让代码正确。无论如何,没有人需要看到它。避免认为一切都是关于某人希望您分发代码。如果有人发布问题,请尝试仔细阅读并理解其意图。如果您这样做了,您会看到 .NET 标记和链接(带有 C、C++ 和 Delphi 中的示例)。所以也许这个问题不是故意对特定语言短视,也许问题不是关于一些讲义,而是想要理解基本概念?

标签: .net wpf windows titlebar


【解决方案1】:

在浏览了 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 中存储的结果有点奇怪:宽度差(右 - 左 == 105)完全符合实际边界,但是高度差(29px)比按钮实际占用的区域大 8 个像素。

由于这并没有真正完整地回答任何问题,因此我将保留此线程以供进一步答复。

再次感谢 Hans 的宝贵意见和深思熟虑的评论。如您所见,这完全是关于编程语言和代码 sn-p。

【讨论】:

    【解决方案2】:

    您可以将 Microsoft.Windows.Shell.dll 与自定义 chrome 窗口库结合使用来修改或处理您的窗口按钮。我正在使用它来创建 Windows 8 ui 风格的应用程序

    http://www.codeproject.com/Articles/131515/WPF-Custom-Chrome-Library

    http://archive.msdn.microsoft.com/WPFShell

    【讨论】:

    • 我查看了这两个框架,它们可能很擅长它们的工作,但是,如果我没记错的话,它们基本上会更改客户区域并绘制/放置自己的按钮。对于某些人来说,这可能确实是一种可能的解决方法,但由于问题是关于如何访问和计算各个按钮的大小,我无法将其标记为答案。无论如何+1,因为这两个项目都是在玻璃上使用航空的好资源。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-04
    • 2016-03-04
    • 2010-09-25
    • 2011-03-13
    相关资源
    最近更新 更多