Skip to content

Commit

Permalink
Change offsets returned to include 4 separate values
Browse files Browse the repository at this point in the history
Instead of assuming a symmetrical border (which is inaccurate), this
updated function will now return an offset value for each of the 4 sides
of a given window.
  • Loading branch information
pacobyte committed Nov 26, 2017
1 parent 5297557 commit 2d6e8e4
Showing 1 changed file with 44 additions and 27 deletions.
71 changes: 44 additions & 27 deletions WinGetPosEx.ahk
Expand Up @@ -2,6 +2,10 @@
;
; Function: WinGetPosEx
;
; Original author: jballi (https://autohotkey.com/boards/viewtopic.php?t=3392)
;
; Update author: RiseUp
;
; Description:
;
; Gets the position, size, and offset of a window. See the *Remarks* section
Expand All @@ -16,24 +20,25 @@
; upper-left corner of the screen (X and Y), and the Width and Height of
; the window.
;
; Offset_X, Offset_Y - Output variables. [Optional] Offset, in pixels, of the
; actual position of the window versus the position of the window as
; reported by GetWindowRect. If moving the window to specific
; coordinates, add these offset values to the appropriate coordinate
; (X and/or Y) to reflect the true size of the window.
; Offset_Left, Offset_Top, Offset_Right, Offset_Bottom - Output variables.
; [Optional] Offset, in pixels, of the actual position of the window
; versus the position of the window as reported by GetWindowRect. If
; moving the window to specific coordinates, add these offset values to
; the appropriate coordinate (X and/or Y) to reflect the true size of the
; window.
;
; Returns:
;
; If successful, the address of a RECTPlus structure is returned. The first
; 16 bytes contains a RECT structure that contains the dimensions of the
; bounding rectangle of the specified window. The dimensions are given in
; screen coordinates that are relative to the upper-left corner of the screen.
; The next 8 bytes contain the X and Y offsets (4-byte integer for X and
; 4-byte integer for Y).
; The next 16 bytes contain the offsets (4-byte integer for each of left,
; top, right, and bottom offsets).
;
; Also if successful (and if defined), the output variables (X, Y, Width,
; Height, Offset_X, and Offset_Y) are updated. See the *Parameters* section
; for more more information.
; Height, Offset_Left, Offset_Top, Offset_Right, and Offset_Bottom) are
; updated. See the *Parameters* section for more more information.
;
; If not successful, FALSE is returned.
;
Expand Down Expand Up @@ -69,12 +74,19 @@
; it. When DWM is a possibility (i.e. Vista+), a developer-friendly messsage
; will be dumped to the debugger when these errors occur.
;
; * 20171126: (RiseUp) Changed function to return 4 offset values instead of 2.
; Windows 10 has different offsets for the top versus the bottom of a window,
; so this function no longer assumes a symmetrical offset border around a
; given window.
;
; Credit:
;
; Idea and some code from *KaFu* (AutoIt forum)
;
;-------------------------------------------------------------------------------
WinGetPosEx(hWindow,ByRef X="",ByRef Y="",ByRef Width="",ByRef Height="",ByRef Offset_X="",ByRef Offset_Y="")
WinGetPosEx(hWindow,ByRef X="",ByRef Y="",ByRef Width="",ByRef Height=""
,ByRef Offset_Left="",ByRef Offset_Top=""
,ByRef Offset_Right="",ByRef Offset_Bottom="")
{
Static Dummy5693
,RECTPlus
Expand All @@ -87,7 +99,7 @@ WinGetPosEx(hWindow,ByRef X="",ByRef Y="",ByRef Width="",ByRef Height="",ByRef O
;-- Get the window's dimensions
; Note: Only the first 16 bytes of the RECTPlus structure are used by the
; DwmGetWindowAttribute and GetWindowRect functions.
VarSetCapacity(RECTPlus,24,0)
VarSetCapacity(RECTPlus,32,0)
DWMRC:=DllCall("dwmapi\DwmGetWindowAttribute"
,PtrType,hWindow ;-- hwnd
,"UInt",DWMWA_EXTENDED_FRAME_BOUNDS ;-- dwAttribute
Expand Down Expand Up @@ -116,14 +128,16 @@ WinGetPosEx(hWindow,ByRef X="",ByRef Y="",ByRef Width="",ByRef Height="",ByRef O
}

;-- Populate the output variables
X:=Left :=NumGet(RECTPlus,0,"Int")
Y:=Top :=NumGet(RECTPlus,4,"Int")
Right :=NumGet(RECTPlus,8,"Int")
Bottom :=NumGet(RECTPlus,12,"Int")
Width :=Right-Left
Height :=Bottom-Top
OffSet_X:=0
OffSet_Y:=0
X:=Left := NumGet(RECTPlus,0,"Int")
Y:=Top := NumGet(RECTPlus,4,"Int")
Right := NumGet(RECTPlus,8,"Int")
Bottom := NumGet(RECTPlus,12,"Int")
Width := Right-Left
Height := Bottom-Top
Offset_Left := 0
Offset_Top := 0
Offset_Right := 0
Offset_Bottom := 0

;-- If DWM is not used (older than Vista or DWM not enabled), we're done
if (DWMRC<>S_OK)
Expand All @@ -132,13 +146,16 @@ WinGetPosEx(hWindow,ByRef X="",ByRef Y="",ByRef Width="",ByRef Height="",ByRef O
;-- Collect dimensions via GetWindowRect
VarSetCapacity(RECT,16,0)
DllCall("GetWindowRect",PtrType,hWindow,PtrType,&RECT)
GWR_Width :=NumGet(RECT,8,"Int")-NumGet(RECT,0,"Int")
;-- Right minus Left
GWR_Height:=NumGet(RECT,12,"Int")-NumGet(RECT,4,"Int")
;-- Bottom minus Top

;-- Calculate offsets and update output variables
NumPut(Offset_X:=(Width-GWR_Width)//2,RECTPlus,16,"Int")
NumPut(Offset_Y:=(Height-GWR_Height)//2,RECTPlus,20,"Int")
GWR_Left := NumGet(RECT,0,"Int")
GWR_Top := NumGet(RECT,4,"Int")
GWR_Right := NumGet(RECT,8,"Int")
GWR_Bottom := NumGet(RECT,12,"Int")

;-- Calculate offsets and update output variables
NumPut(Offset_Left := Left - GWR_Left,RECTPlus,16,"Int")
NumPut(Offset_Top := Top - GWR_Top ,RECTPlus,20,"Int")
NumPut(Offset_Right := GWR_Right - Right ,RECTPlus,24,"Int")
NumPut(Offset_Bottom := GWR_Bottom - Bottom ,RECTPlus,28,"Int")

Return &RECTPlus
}

0 comments on commit 2d6e8e4

Please sign in to comment.