Page 1 of 3

[Function] WinGetPosEx v0.1 (Preview) - Get the real position and size of a window

Posted: 19 Apr 2014, 22:04
by jballi
Introduction
With the introduction of the Desktop Window Manager (DWM) and Aero themes in Windows Vista, the size and position of windows has never been the same. The OS says that the window is one size but when displayed, the window can be another (usually larger) size. The WinGetPosEx function is an attempt to help the developer to identify the correct position and size of a window regardless of window attributes, desktop theme, or version of Windows.

WinGetPosEx
Key features:
  • Actual dimensions. Get the actual position and size of a window.
  • Offset values. If the window is a different size than reported by the OS, offset values are returned to assist the developer to set the position of the window.
The Code
The function and example script are attached to this post.

Skrell has created an alternate version of the function that might be useful for some developers when run on Windows XP. You can find it here.

Issues/Considerations
A few considerations:
  • Preview. Yes, this still a preview release.
  • Compatibility. This function was designed to run on Windows 2000+ and on all versions of AutoHotkey. Although I've tested it on most versions of AutoHotkey, I only have a Windows 7 box to test on. I have no idea if this will work correctly on any other version of Windows. If you find any bugs or have any compatibility problems, please let me know.
---------------------------------------------------------------------------
Release Notes

v0.0.1
Prototype.

v0.0.2 (Prototype)
Minor changes to the function and to the example.

v0.1 (Preview)
Fixed bug when DWM is not enabled.

Re: [Function] WinGetPosEx v0.0.1 - Get the real size of win

Posted: 20 Apr 2014, 04:34
by joedf
Seems to run great! No runtime errors.
[Passed] WinXP, Win7 and Win8

just one little quirk on Win8
screenshot
Regards

Re: [Function] WinGetPosEx v0.0.1 - Get the real size of win

Posted: 20 Apr 2014, 07:40
by guest3456
Well done

Here is a thread I made a while ago on old forum showing the issue (use google cache if autohotkey.com is down):
http://www.autohotkey.com/board/topic/8 ... ero-theme/

and you can see that my workaround was to change the window style with:

Code: Select all

Gui, +LastFound
ThisGuiHwnd := WinExist()
DllCall("uxtheme\SetWindowTheme", "Uint", ThisGuiHwnd, "Uint", 0, "UintP", 0)
I'm not sure if its the same as using DwmSetWindowAttribute but it looks similar visually

Re: [Function] WinGetPosEx v0.0.1 - Get the real size of win

Posted: 20 Apr 2014, 10:11
by Skrell
this looks amazing! my only question is does this function account for the removed "pink space" on themes in XP? I hope you know what i'm talking about, but certain themes have portions of the window frame removed using a special "pink color" and this throws off the size of windows by autohotkey. I'm really hoping that this function could address this. Thanks again!!!

Re: [Function] WinGetPosEx v0.0.1 - Get the real size of win

Posted: 20 Apr 2014, 21:57
by jballi
Thanks to everyone for your feedback.
joedf wrote:Seems to run great! No runtime errors.
[Passed] WinXP, Win7 and Win8

just one little quirk on Win8
screenshot
This appears to be more that a "little quirk" on Windows 8. Does this happen all the time or only with certain window attributes? I don't have Windows 8 so any help you could provide would be beneficial.
guest3456 wrote:Here is a thread I made a while ago on old forum showing the issue (use google cache if autohotkey.com is down):
http://www.autohotkey.com/board/topic/8 ... ero-theme/

and you can see that my workaround was to change the window style with:

Code: Select all

Gui, +LastFound
ThisGuiHwnd := WinExist()
DllCall("uxtheme\SetWindowTheme", "Uint", ThisGuiHwnd, "Uint", 0, "UintP", 0)
I completely forgot about the "SetWindowTheme" function. I will try add this to the example script for Windows XP users. Thanks.
Skrell wrote:my only question is does this function account for the removed "pink space" on themes in XP? I hope you know what i'm talking about, but certain themes have portions of the window frame removed using a special "pink color" and this throws off the size of windows by autohotkey. I'm really hoping that this function could address this.
I truly wish I knew what you were talking about. I used Windows XP for many years and I don't remember anything like that. But then again, my memory... Maybe if you sent me screen shot.

As it is coded right now, the function assumes that if the Desktop Window Manager (DWM) is not available then the standard core OS function (i.e. "GetWindowRect") will return the correct position and size the window. If this is not the case then I'll either have to make some changes or the value of this function will be limited.

Re: [Function] WinGetPosEx v0.0.1 - Get the real size of win

Posted: 20 Apr 2014, 22:00
by joedf
Only the first option seems to cause it
The "toggle non-client rendering policy" everything else works fine

Re: [Function] WinGetPosEx v0.0.1 - Get the real size of win

Posted: 20 Apr 2014, 23:53
by Skrell
This is what i mean: Here is a picture of a winxp skin that includes a "pink" region which is removed as the window is rendered. Autohotkey doesn't account for this(i think) and hence doesn't report the "real" size of the visible window. Does this make any more sense now? http://tinypic.com/view.php?pic=1zzl6vt&s=8

Re: [Function] WinGetPosEx v0.0.1 - Get the real size of win

Posted: 20 Apr 2014, 23:54
by guest3456
jballi wrote: I completely forgot about the "SetWindowTheme" function. I will try add this to the example script for Windows XP users. Thanks.
I don't think this matters for XP users. From what I've seen the bug only occurs since the addition of the DWM (Aero Theme) on Win Vista+. So the normal WinGetPos should work for XP. I was just posting an alternative that I used when I posted that bug report years ago
joedf wrote:Only the first option seems to cause it
The "toggle non-client rendering policy" everything else works fine
I don't get this on Win 8. Everything works fine for me in the test script

Re: [Function] WinGetPosEx v0.0.1 - Get the real size of win

Posted: 21 Apr 2014, 02:36
by joedf
@guest3456
Really? I guess my test is faulty... Because I actually tested on the Win8 Cobsumer preview :P hehe it is outdated I guess :(

Re: [Function] WinGetPosEx v0.0.1 - Get the real size of win

Posted: 21 Apr 2014, 03:18
by jballi
Skrell wrote:This is what i mean: Here is a picture of a winxp skin that includes a "pink" region which is removed as the window is rendered. Autohotkey doesn't account for this(i think) and hence doesn't report the "real" size of the visible window. Does this make any more sense now? http://oi59.tinypic.com/1zzl6vt.jpg
No, I afraid this doesn't help. I have no idea what I'm looking at.

As discussed earlier, Windows XP uses the "GetWindowRect" function to collect the position and size of the window. Is it possible that the "pink" region has been made entirely translucent? If this is the case, the "GetWindowRect" function would return a value that is correct but the window would appear to be a different size.
guest3456 wrote:
jballi wrote: I completely forgot about the "SetWindowTheme" function. I will try add this to the example script for Windows XP users. Thanks.
I don't think this matters for XP users. From what I've seen the bug only occurs since the addition of the DWM (Aero Theme) on Win Vista+. So the normal WinGetPos should work for XP. I was just posting an alternative that I used when I posted that bug report years ago
Although I labeled it an "example" script, I use the example script as a means of testing the function under many conditions. Adding use of the "SetWindowTheme" function in the example script just increases the number of conditions that could occur in real life. When people, like yourself, run the example script, they help to confirm the function works or doesn't work under certain conditions.
guest3456 wrote:
joedf wrote:Only the first option seems to cause it
The "toggle non-client rendering policy" everything else works fine
I don't get this on Win 8. Everything works fine for me in the test script
Interesting results. Even if joedf thinks that it might be because of early-release version of the Windows 8, it is something to keep on eye on. Thanks for the feedback.

Re: [Function] WinGetPosEx v0.0.1 - Get the real size of win

Posted: 21 Apr 2014, 10:18
by Skrell
As discussed earlier, Windows XP uses the "GetWindowRect" function to collect the position and size of the window. Is it possible that the "pink" region has been made entirely translucent? If this is the case, the "GetWindowRect" function would return a value that is correct but the window would appear to be a different size.
Yes this is essentially what i mean. Is there any way to get the non-translucent area only? Or is that really not the point of your function?

Re: [Function] WinGetPosEx v0.0.1 - Get the real size of win

Posted: 21 Apr 2014, 14:58
by jballi
Skrell wrote:
jballi wrote:As discussed earlier, Windows XP uses the "GetWindowRect" function to collect the position and size of the window. Is it possible that the "pink" region has been made entirely translucent? If this is the case, the "GetWindowRect" function would return a value that is correct but the window would appear to be a different size.
Yes this is essentially what i mean. Is there any way to get the non-translucent area only? Or is that really not the point of your function?
The second part. Identifying and reporting the idiosyncrasies of a particular theme is definitely out of scope for this function. Sorry. I wish I could be more helpful.

Re: [Function] WinGetPosEx v0.0.1 - Get the real size of win

Posted: 21 Apr 2014, 15:55
by Skrell
jballi wrote:
Skrell wrote:
jballi wrote:As discussed earlier, Windows XP uses the "GetWindowRect" function to collect the position and size of the window. Is it possible that the "pink" region has been made entirely translucent? If this is the case, the "GetWindowRect" function would return a value that is correct but the window would appear to be a different size.
Yes this is essentially what i mean. Is there any way to get the non-translucent area only? Or is that really not the point of your function?
The second part. Identifying and reporting the idiosyncrasies of a particular theme is definitely out of scope for this function. Sorry. I wish I could be more helpful.
Ok, thanks anyway.

Re: [Function] WinGetPosEx v0.0.2 - Get the real size of win

Posted: 22 Apr 2014, 06:57
by jballi
v0.0.2 (Prototype)
Minor changes to the function (no functional changes).
Minor changes to the example to add more flexibility (hopefully) to toggling the current theme.

As always, please let me know if you find any problems. If you find a bug or idiosyncrasy, please let me know about it and be sure to include what version of Windows and version of AutoHotkey you are using.

Thanks for your help.

Re: [Function] WinGetPosEx v0.0.2 - Get the real size of win

Posted: 22 Apr 2014, 08:13
by Skrell
Any idea if this version of WinGetPos works faster/slower than the built in autohotkey function?

Re: [Function] WinGetPosEx v0.0.2 - Get the real size of win

Posted: 22 Apr 2014, 10:57
by jballi
Skrell wrote:Any idea if this version of WinGetPos works faster/slower than the built in autohotkey function?
I know the function is fast but I haven't run any performance tests on it.

Generally speaking, an AutoHotkey command or function is always going to perform faster, usually significantly faster (relatively speaking), than script code. This is because an AutoHotkey command is running compiled code where as the script is running interpreted code. A script function has a bit more overhead that straight in-line code because AutoHotkey does some pre-processing and post-processing when calling a function.

For this type of function, speed is usually not a significant factor because it usually is only called a few times here and there. It's not the type of code that you run hundreds or thousands of times per session.

If speed becomes a serious factor for some reason and the script is running on Vista+, you can pre-load the dwmapi.dll library once before calling the function. See the "DllCall" section of the documentation for more information.

I hope this answers your question.

Re: [Function] WinGetPosEx v0.0.2 - Get the real size of win

Posted: 22 Apr 2014, 13:35
by joedf
I'll maybe run a test with QPC from L1.
I'll edit this post with the results.

Re: [Function] WinGetPosEx v0.0.2 - Get the real size of win

Posted: 22 Apr 2014, 14:38
by Skrell
joedf wrote:I'll maybe run a test with QPC from L1.
I'll edit this post with the results.
What is QPC from L1? I'd be curious as to how one would benchmark AHK code.

Re: [Function] WinGetPosEx v0.0.2 - Get the real size of win

Posted: 27 Apr 2014, 16:56
by joedf
Sorry for the late response.
"QPC from L1" is LearningOne's version of QPX() which uses QueryPerformanceCounter
see http://www.autohotkey.com/board/topic/9 ... code-runs/

Code: Select all

Best Results
----------------------------------------------
WinGetPos <<
   0.000036  100%
WinGetPosEx
   0.000202  561%
   
WinGetPos
Min: 0.000024   66%
Ave: 0.000036  100%
Max: 0.000064  180%
Tot: 0.000357

WinGetPosEx
Min: 0.000154   76%
Ave: 0.000202  100%
Max: 0.000232  115%
Tot: 0.002015


Worst Results
----------------------------------------------
WinGetPos <<
   0.000029  100%
WinGetPosEx
   0.000451 1555%
   
WinGetPos
Min: 0.000023   79%
Ave: 0.000029  100%
Max: 0.000050  176%
Tot: 0.000287

WinGetPosEx
Min: 0.000166   37%
Ave: 0.000451  100%
Max: 0.001635  362%
Tot: 0.004513

Re: [Function] WinGetPosEx v0.0.2 - Get the real size of win

Posted: 30 May 2014, 02:03
by Drugwash
Having just read the comments without looking at the code, I was wondering if for Skrell's situation on XP a call to GetWindowRgnBox() might help in getting the correct width and height of a window. Top-left corner should be calculated separately though, since the API returns region coordinates relative to upper-left corner of the window, not relative to the screen. If only width and height are required, this can be simply done as below:

Code: Select all

VarSetCapacity(RECT, 16, 0)
DllCall("GetWindowRgnBox", Ptr, hwnd, Ptr, &RECT)
w := NumGet(RECT, 8, "Int")-NumGet(RECT, 0, "Int"), h := NumGet(RECT, 12, "Int")-NumGet(RECT, 4, "Int")