6

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
Community
  • 1
  • 1
UnclePaul
  • 515
  • 5
  • 17
  • What are you going to do with this information? – siride Jan 01 '13 at 16:13
  • Hi siride. The questions have been asked on the net over and over again and yet I couldn't find any satisfying answer. Additionally the MSDN entries and API descriptions on that topics are mediocre at best (although catch22.net has a nice example for older OS). So first and foremost it's curiosity what drives me. My personal goal is to accurately measure the space the upper right menu takes (on Left-To-Right systems) and place/ hide/ resize controls next to it depending on the available space in a WPF demo app. – UnclePaul Jan 01 '13 at 16:31
  • 2
    Lots of ways to get this code wrong. Nobody can see it. Avoid asking a send-me-the-codes question when you don't even specify the language you need. Post a snippet so these things become obvious. – Hans Passant Jan 01 '13 at 16:34
  • Thank you Hans for your reply. There are a lot of ways of getting the code right. And nobody needs to see it anyway. Avoid thinking that everything is about someone wanting you to hand out code. If someone posts a question, try to read it carefully and understand the intention. If you would have done so, you would have seen the .NET tag and the links (with examples in C, C++ and Delphi). So maybe the question is intentionally not myopic about a specific language and maybe the question is not about some handouts, but urge to understand the underlying concepts? – UnclePaul Jan 01 '13 at 17:23

2 Answers2

2

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.

UnclePaul
  • 515
  • 5
  • 17
1

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

Marco Klein
  • 683
  • 5
  • 19
  • 1
    I looked at both frameworks and they are probably great at what they do, but, if I'm not mistaken, they basically change the client area and draw/place their own buttons instead. This might indeed be a possible workaround for some, but since the question is about how to access and calculate the size of the individual buttons I cannot mark it as the answer. +1 anyhow, because both projects are good resources for working with aero on glass. – UnclePaul Jan 01 '13 at 20:21