4

I use GetWindowRect in my program to get the coordinates of a window on the desktop. This works fine on a dozen or so PCs I have here for testing (XP-W8.1) but not on my one W10 PC with touch screen: the coordinates have an offset to the top-left. I googled both for a bug in Windows 10 and for something monitor related but cannot find anything, yet this seems like a commonly used function and the problem is easy to reproduce.

Anyone got any clues?

Code, simplified:

hwnd = FindWindow(NULL, windowname);
if (hwnd) {
  TRect r;
  GetWindowRect(hwnd, &r);
}
HWND hdt = GetDesktopWindow();
HDC dcdt = GetWindowDC(hdt);
// bitblt canvas to get window (won't work for high DPI setting)
Mike Versteeg
  • 1,615
  • 14
  • 28
  • 1
    If this is easy to reproduce, please show us your reproduction code, the values you would expect to see, the values that you observe, and your apps DPI awareness setting – David Heffernan May 19 '15 at 11:07
  • GetWindowRect works with pixels, doesn't that mean DPI is not relevant? – Mike Versteeg May 19 '15 at 12:21
  • DPI can be virtualized. Why don't you do what I asked? – David Heffernan May 19 '15 at 12:21
  • Adding code now. Thanks, that's indeed my problem. And as I want to support XP-10 there also does not appear to be an easy solution. Odd though that this does not work both ways, as that it what I would expect if there was true virtualisation. – Mike Versteeg May 19 '15 at 15:22
  • 2
    It's easy to support XP-10. You just add the DPI aware manifest, and support high DPI in the code. – David Heffernan May 19 '15 at 15:29
  • Yes, I learned that in the past two hours of doing research. However I do not think this is possible in C++ Builder, though apparently there is also an API call I can use. I would prefer to avoid this though, as I want to fix one minor thing and not new problems (I assume there is a good reason Embarcadero did not enable this by default). Anyway, you set me on the right path so I'll award you if you make your DPI virtualisation comment an answer. – Mike Versteeg May 19 '15 at 15:38
  • My VCL app (Delphi) is DPI aware. No need for API calls. Just a manifest. My app is system DPI aware so doesn't support Win8.1 per monitor DPI awareness. That's a little harder. No need for API calls. And even if there were, they are easy to add even if the stock RTL/VCL doesn't expose them. – David Heffernan May 19 '15 at 15:48
  • 1
    @MikeVersteeg: Just about anything can be done in C++Builder with a little work. You have access to the full Win32 API, and you can add manifests to C++Builder projects, either directly via the IDE in newer versions, or via an `.RC` file in older versions. – Remy Lebeau May 19 '15 at 18:41
  • 1
    See [Manifest Madness](http://blogs.msdn.com/b/chuckw/archive/2013/09/10/manifest-madness.aspx) for details on the embedded manifests. It's just a XML text file inserted as a Win32 resource, so it's not 'magic'. – Chuck Walbourn May 20 '15 at 06:52

1 Answers1

4

Your program is not DPI aware and so is subject to DPI virtualization. That means that the coordinates returned by functions like GetWindowRect will be virtualized coordinates and so will not match the true screen coordinates.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 2
    This also means that it's not specific to Windows 10 but can happen on any version back to Vista, given a high enough DPI display. – Adrian McCarthy May 19 '15 at 15:56
  • 1
    Thanks to everyone! I learned two new things here so very pleased with your support (and SO). – Mike Versteeg May 21 '15 at 10:28
  • Please note that apart from DPI awareness there are other reasons why GetWindowRect() may give wrong results. Windows draws a shadow border around all toplevel windows that may be 2 pixels or 7 pixels to the left, bottom and right. How to fix this see: http://stackoverflow.com/questions/34139450/getwindowrect-returns-a-size-including-invisible-borders – Elmue Aug 20 '16 at 18:31