Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retrieve the size of the Minimize, Maximize and Close button of a Window?

So far I tried using GetThemePartSize, GetThemeMetric, GetSystemMetrics, WM_GETTITLEBARINFOEX via SendMessage and a couple of other calls, but nothing comes even close to the real dimensions (Windows 7 with themes enabled).

Basically my questions are: How to get the size (and location, ideally even handle) of these buttons and what do the retrieved values from GetThemePartSize even mean? What are they good for?

I already looked at this answer and many others, but they simply don't work.

Thank you

Update

For Hans:

[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
like image 220
UnclePaul Avatar asked Oct 22 '22 20:10

UnclePaul


2 Answers

After browsing the Firefox 17.0.1 source code (namely the files nsNativeThemeWin.cpp and nsUXThemeData.cpp), I was able to come up with a partial solution for desktops apps running on Vista or newer that satisfied my needs:

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);

The results stored in buttonsRect are somewhat strange: The width difference (right - left == 105) fits the actually bounds exactly, however, the height difference (29px) is 8 pixel larger than the area the buttons are actually occupying.

Since this doesn't really answer any of the questions in full, I will leave this thread open for further responses.

Thanks again Hans for your invaluable and well-thought-out comment. As you can clearly see, it was all about the programming language and the code snippet.

like image 146
UnclePaul Avatar answered Oct 27 '22 01:10

UnclePaul


You can use the Microsoft.Windows.Shell.dll in combination with the custom chrome window library to modify or address your window buttons. I am using this in order to create windows 8 ui styled applications

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

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

like image 30
Marco Klein Avatar answered Oct 27 '22 00:10

Marco Klein