6

I'm trying to adjust the caption of my main window to show as much of a file name as is possible to fit in the caption area. So, I'm looking to calculate the width of the area marked up here in the red rectangle:

enter image description here

Now, I would ideally like to have code that can use whatever system metrics are available and thereby avoid being caught out by all the various platform/theme/dpi variations that can exist.

How can this be done, if indeed it is even possible?

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 3
    Use `WM_NCHITTEST` to scan across until you hit the minimize button? – Jonathan Potter Nov 19 '15 at 20:44
  • 3
    I'd start with [`WM_GETTITLEBARINFOEX`](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969436(v=vs.85).aspx) and get rid of the rectangles that the various buttons occupy. I'm not sure how accurate this is compared to other methods or if this will be future-proof... See also [this](http://blogs.msdn.com/b/oldnewthing/archive/2014/05/05/10522553.aspx) – andlabs Nov 19 '15 at 20:45

2 Answers2

3

As andlabs said in the comments, the WM_GETTITLEBARINFOEX message can be used to obtain the required information.

This message can be sent to the window and the TITLEBARINFOEX struct is populated with the state and location of the titlebar and each of its buttons. From there it is a simple task to determine how much space is available for the caption.

Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
-1

First, call GetTitleBarInfo, passing a pointer to the TITLEBARINFO structure:

TITLEBARINFO tbi;
GetTitleBarInfo(hwnd, &tbi);

The width of the titlebar is tbi.rcTitlebar.right - tbi.rcTitlebar.left. But that includes the three buttons (Close, Minimize, and Maximize). The width of one button is GetSystemMetrics(SM_CXSIZE), so the width of the title bar minus the three buttons is

(tbi.rcTitlebar.right - tbi.rcTitlebar.left) - (3 * GetSystemMetrics(SM_CXSIZE))

Of course, the code works on all versions of Windows where the width of each of the 3 buttons is equal

lost_in_the_source
  • 10,998
  • 9
  • 46
  • 75
  • Based on the assumption, that no application will ever use a help button. This is worse than what was suggested by andlabs in his [comment](http://stackoverflow.com/questions/33813965/how-can-i-measure-the-width-of-the-caption-bar-available-for-text/33838362#comment55393560_33813965) a day prior to you posting this answer. [WM_GETTITLEBARINFOEX](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969436.aspx) doesn't require guessing. – IInspectable Nov 22 '15 at 18:23
  • If the application uses a help button, just multiply by 4 instead of 3 @IInspectable – lost_in_the_source Nov 22 '15 at 18:35
  • Based on the assumption, that all buttons are the same size, and they use no spacing. – IInspectable Nov 22 '15 at 18:39
  • Dialogs that use a help button will not have minimize or maximize buttons. You'd have to observe window styles to see how many buttons there are. And remember that the Close button on Vista/7 Aero is wider than the other buttons. Also imagine a hypothetical version of Windows in which `CS_NOCLOSE` doesn't show a close button at all, instead of drawing a disabled one. I don't know if `WM_GETTITLEBARINFOEX` will give you a zero rect for buttons that are absent, but if it does, then using that would avoid the need to figure out what buttons a titlebar does have. If you still need XP, though... – andlabs Nov 27 '15 at 21:06
  • The only other issue that is in the way of the question that the OP asked is that the spacing between elements, margins around the titlebar, and size of the system menu icon are not taken into consideration. If you're custom-drawing a titlebar, you'll probably wind up ellipsizing a bit too far, but I doubt it'll be significant enough to be worrisome. – andlabs Nov 27 '15 at 21:09
  • @andlabs WM_GETTITLEBARINFOEX gives you a state flag for each button that indicates its visibility – David Heffernan Nov 28 '15 at 09:16