4

A frequent operation in my Windows Table control, which I am reworking and moving into a DLL, is to get the height of a row. This is the maximum of

  • the height of text in the current font, in pixels
  • the current small icon height, in pixels (GetSystemMetrics(SM_CYSMICON))
  • the height of checkboxes, in pixels (determined on a WM_THEMECHANGED, when checkbox information is recalculated)

Calculating the text height, as far as I know, requires getting a DC, selecting the font in (and getting the SYSTEM_FONT if that's NULL), getting the text metrics, selecting the font out, and releasing the DC, all of which can error out/fail/etc. This means that virtually every function in my control can fail.

I can avoid this by storing the text height somewhere else, only calculating it when it changes. I know that text height is a property related to the DPI of the DC that GetDC(hwnd) returns. I would like my control to be DPI-agnostic because DPI awareness is per-process, not per-DLL/per-window.

At the same time, knowing when GetSystemMetrics(SM_CYSMICON) changes would also be useful.

So my questions are simple:

  • Is there a message that I can look for that will tell me that my DPI has changed and that I need to recalculate my text height?
  • Is there a message that will tell me that SM_CYSMICON has changed and that I need to recalculate everything? Is it the same one? (I know there is no reliable way to detect a GetSystemMetrics() failure (since 0 is a valid return and it does not set the last error code), so I am assuming it cannot fail with a valid parameter and am simply calling it each time I need to calculate the row height; this is just so I can queue a redraw when the value does change.) Would it also work for SM_CXSMICON?
  • In addition, looking back at my code, GetThemePartSize() takes a DC as well; do theme items like checkbox images scale with DPI? And if so, what messages do I look for in that case? The same one?
  • Alternative: is there a non-failing way to get the text height that I don't know about, given only a HWND and HFONT?

I will be happy to take a solution that was introduced in either Windows XP or Windows Vista; if there's a solution that was introduced in a newer version of Windows, then knowing about it could also be beneficial.

Thanks.

Community
  • 1
  • 1
andlabs
  • 11,290
  • 1
  • 31
  • 52
  • 2
    I expect you'll get a WM_SETTINGCHANGE message. I presume that you are writing per-process DPI aware app. Win 8.1 now has per-app DPI aware. And XP was different again. Do you really need to support XP? – David Heffernan Feb 28 '15 at 18:31
  • I'm not writing a DPI-aware app, but rather a control for other apps to use; I don't know if someone else who will use my DLL in their own program is, so I would rather play it safe. I phrased my question in that way because I'm not using anything Vista-specific yet, but in this new DLL's case I am free to drop XP support should I need something Vista-specific. (Prior to that, the Table control was written for another framework that still needed XP support. Now it is a standalone control, and I plan on asking the framework's users if they wouldn't mind if I drop XP support there too.) – andlabs Feb 28 '15 at 18:33
  • You are not expected to have to deal with a DPI change on the fly. The user is asked to log out and log back in. Try it. – Hans Passant Feb 28 '15 at 18:52
  • @HansPassant: A warning to the user that some applications may not process DPI changes correctly is no excuse for not supporting it in new code. – Ben Voigt Feb 28 '15 at 19:02
  • And doesn't Windows 8.1 or something support multiple monitors with different DPI? Wouldn't that cause problems on the fly as well? – andlabs Feb 28 '15 at 19:10
  • 1
    @andlabs Yes in Windows 8.1 different monitors can have different DPI values and properly written apps can auto adjust as they move between them - log out/in not required. It's a noble cause. Good luck with that :) – Jonathan Potter Feb 28 '15 at 19:50
  • 1
    Fundamentally this is the app developer's problem and not the component writer's problem. Nothing wrong with you asking for metrics. If you can't get metrics, then what chance of painting. What are these errors that you are so scared of? Windows isn't some vindictive thing that fails out of spite. If you write your code correctly it won't fail. – David Heffernan Feb 28 '15 at 21:55
  • What errors am I so scared of? Whatever error these functions could return, which could be anything; maybe something temporarily failed to work?? Please forgive me for this; I'm just that used to the rhetoric that *every error must be checked* that the idea that some (detectable) errors won't come up and that I can freely ignore them is rather mindblowing; [I even asked a similar question on Programmers a few weeks ago](http://programmers.stackexchange.com/questions/273349/whats-the-best-way-to-handle-windows-api-errors-in-response-to-system-messages). – andlabs Mar 01 '15 at 05:02
  • Of course thinking about it now I can reason why `GetTextMetrics()` shouldn't fail given a valid DC and a font that was successfully selected in, since the information that it returns should be readily available to GDI; same for `GetClientRect()` (which would have been a followup question). So now I'm not so sure of my predispositions... – andlabs Mar 01 '15 at 05:03
  • 1
    If you code it right, none of these things will fail. If they do, you are already hosed. You cannot be robust to that scenario. If you can't measure you won't be able to paint. You have worse problems. Advice to check for errors doesn't mean you need your code to function correctly in the face of them. Usual response for errors in the functions you name is that the code gives up since it cannot proceed. – David Heffernan Mar 01 '15 at 08:19
  • I see. Right now my code already does just give up if something goes wrong, logging a warning in debug mode as well. (Should I call `DefWindowProc()` in a message handler as well in this case, or would that just make a bad thing worse?) In that case I guess I'll just continue doing that (though I am reworking everything to be cleaner and reduce bugs elsewhere...). Thanks. – andlabs Mar 02 '15 at 01:20

0 Answers0