5

I'm coding in c++ on windows 10 - straight win32 API.

I wanted to make a window show up in the top right of the screen. As I was doing this, I noticed that screen coordinates for a maximized window are left=-8, top=-8, right=1936, bottom=1088.

Also, when I position a window so right=1920 and top=0, there's about an 8 pixel gap on the right. I tried moving the window around to see what screen coordinates I got.

rect.left for a nonmaximized window can go from -7 to 1912.

so things are slid by 7 pixels ? WTF microsoft ??

How am I supposed to come up with the rec.right=1913 value to position my window aligned to right side of screen without that dang gap ?

But rect.right of 1920 leaves a gap. So rect.right of 1912 would leave MORE of a gap...

And I need a solution that'll work back to Vista. Pre win10, that rect.right should be 1920 like ya expect.

Whaaaaat is going on here? I'm about to start throwing knives around !!

Code wise, this is just what GetWindowRect is reporting... (excuse my weird debugging function)

::GetWindowRect (_wndo, r);

DBG("ExtRc l=`d r=`d t=`d b=`d w=`d h=`d",
r->left, r->right, r->top, r->bottom, r->right-r->left, r->bottom-r->top);
Stephen Hazel
  • 859
  • 2
  • 12
  • 27
  • Don't throw knives around. Those break windows. – rubenvb Feb 26 '17 at 20:06
  • yeah it does NOT take much to break windows 10 seems ta me...:((( – Stephen Hazel Feb 26 '17 at 20:08
  • Well that's not a good question - needs some improvement. Code? Images? You read on non-client area, didn't you? – Roman R. Feb 26 '17 at 20:22
  • Ok, I've figured out what's going on here. GetWindowRect and GetClientRect report a width difference of 16. So 8 pixels per side. BUT, on win10 the borders are only 1 pixel wide. So GetWindowRect is reporting an imaginary border that's 7 pixels left of where the ACTUAL BORDER is drawn in screen pixels. My question still stands about the best way to calculate this dang 7 pixel offset though. Which fricken buried Windoes API do I use ??? – Stephen Hazel Feb 26 '17 at 21:09
  • 3
    Fun stuff. Try `DwmGetWindowAttribute` with the attribute `DWMWA_EXTENDED_FRAME_BOUNDS`: https://msdn.microsoft.com/en-us/library/windows/desktop/aa969515(v=vs.85).aspx – Christopher Oicles Feb 26 '17 at 22:03
  • @ChristopherOicles put that in an answer cuz that's my answer. I also don't wanna hear Raymond Chen taling about maintaining compatibility with previous windows versions and dubious coders. This looks like total broken-ness to me. Also, it takes a while for that function to WORK and I'm not sure why. I open a dialog in what i THINK would be top right and it shows the gap but THAT func and GetWindowRect give me the SAME values if the window is opened hidden. I swear I'm goin for the knives !! – Stephen Hazel Feb 26 '17 at 22:33
  • 2
    Go ahead and accept your own answer, it is more detailed than anything I would write. Raymond Chen is cool tho. – Christopher Oicles Feb 27 '17 at 21:46
  • He is! But the things he says about Microsoft straining to keep compatibility are nooooo longer true :( – Stephen Hazel Feb 28 '17 at 01:31

2 Answers2

10

Well thanks to @ChristopherOicles This is really his answer. Duplicate this as your own (or tweak it, whatever) and I'll accept your's.

What's going on is microsoft wrecking border widths in windows 10.

GetWindowRect returns the outside window coordinates as screen coordinates. GetClientRect returns the inside the window coordinates. Up until Windows 10 (F U Win10 !!),

The difference in width and height between them was the width and height of the borders.

Upon win10, the border width reports 16 pixels, so 8 pixels a side. However, only 1 of those pixels are visible. 7 of them are transparent. So your window has a transparent 7 pixels to the left, right, and bottom.

So you need to take those transparent 7 pixels into account if you're going to line up the window on the screen programmatically. The user doesn't want that 7 pixel gap next to the screen border !

DwmGetWindowAttribute with the attribute DWMWA_EXTENDED_FRAME_BOUNDS will get you the width and height of the ACTUALLY SHOWING part of the border in screen coordinates. So similar to GetWindowRect, but the rect does not include the invisible-ness.

You're still going to need GetWindowRect most of the time to set the width and height of your window and those 7 pixels per side of invisible-ness are needed to size the window properly programmatically.

So use the difference between the .left of the rect GetWindowRect returns and .left of what DwmTerribleName returns to get that 7 pixels of offset.

In my opinion, whoever did this at Microsoft should be immediately shot. This is a hoop I didn't need to jump through. This breaks compatibility with the past.

Stephen Hazel
  • 859
  • 2
  • 12
  • 27
  • It seems that DwmGetWindowAttribute + DWMWA_EXTENDED_FRAME_BOUNDS only tells you the true position of the window after the window becomes visible (if ShowWindow has not been called, it gives the same result as GetWindowRect - which includes the 7px border). This means you need to reposition the window (7px to the left) after it is already shown - how can you avoid this movement flicker? – Haighstrom Dec 17 '21 at 22:54
2

This is because of the width of the window border and other factors, which vary depending on OS version, user preference, and DPI settings. See the GetSystemMetrics function.

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
  • ok, I've found GetWindowRect and GetClientRect report a border width difference of 16 pixels. So 8 pixels on a side. But the ACTUAL border width on win10 is 1 pixel. Got an API for me to figure out how much of the reported 8 pixel border width is "just air". How do I get that magic 7 out of the windows API ?? Only way I've calc'd border width before is difference of GetWindowRect width and GetClientRect width / 2. That calc no longer holds in win10. So how do I know to offset by 7 ? – Stephen Hazel Feb 26 '17 at 21:21
  • 2
    GetSystemMetrics doesn't get me that 7 pixel offset. DwmGetWindowAttribute with the attribute DWMWA_EXTENDED_FRAME_BOUNDS: does. – Stephen Hazel Feb 26 '17 at 22:35