├── .gitattributes ├── README.md └── WinGetPosEx.ahk /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AutoHotkey-Lib-WinGetPosEx -------------------------------------------------------------------------------- /WinGetPosEx.ahk: -------------------------------------------------------------------------------- 1 | ;------------------------------ 2 | ; 3 | ; Function: WinGetPosEx 4 | ; 5 | ; Original author: jballi (https://autohotkey.com/boards/viewtopic.php?t=3392) 6 | ; 7 | ; Update author: RiseUp 8 | ; 9 | ; Description: 10 | ; 11 | ; Gets the position, size, and offset of a window. See the *Remarks* section 12 | ; for more information. 13 | ; 14 | ; Parameters: 15 | ; 16 | ; hWindow - Handle to the window. 17 | ; 18 | ; X, Y, Width, Height - Output variables. [Optional] If defined, these 19 | ; variables contain the coordinates of the window relative to the 20 | ; upper-left corner of the screen (X and Y), and the Width and Height of 21 | ; the window. 22 | ; 23 | ; Offset_Left, Offset_Top, Offset_Right, Offset_Bottom - Output variables. 24 | ; [Optional] Offset, in pixels, of the actual position of the window 25 | ; versus the position of the window as reported by GetWindowRect. If 26 | ; moving the window to specific coordinates, add these offset values to 27 | ; the appropriate coordinate (X and/or Y) to reflect the true size of the 28 | ; window. 29 | ; 30 | ; Returns: 31 | ; 32 | ; If successful, the address of a RECTPlus structure is returned. The first 33 | ; 16 bytes contains a RECT structure that contains the dimensions of the 34 | ; bounding rectangle of the specified window. The dimensions are given in 35 | ; screen coordinates that are relative to the upper-left corner of the screen. 36 | ; The next 16 bytes contain the offsets (4-byte integer for each of left, 37 | ; top, right, and bottom offsets). 38 | ; 39 | ; Also if successful (and if defined), the output variables (X, Y, Width, 40 | ; Height, Offset_Left, Offset_Top, Offset_Right, and Offset_Bottom) are 41 | ; updated. See the *Parameters* section for more more information. 42 | ; 43 | ; If not successful, FALSE is returned. 44 | ; 45 | ; Requirement: 46 | ; 47 | ; Windows 2000+ 48 | ; 49 | ; Remarks, Observations, and Changes: 50 | ; 51 | ; * Starting with Windows Vista, Microsoft includes the Desktop Window Manager 52 | ; (DWM) along with Aero-based themes that use DWM. Aero themes provide new 53 | ; features like a translucent glass design with subtle window animations. 54 | ; Unfortunately, the DWM doesn't always conform to the OS rules for size and 55 | ; positioning of windows. If using an Aero theme, many of the windows are 56 | ; actually larger than reported by Windows when using standard commands (Ex: 57 | ; WinGetPos, GetWindowRect, etc.) and because of that, are not positioned 58 | ; correctly when using standard commands (Ex: gui Show, WinMove, etc.). This 59 | ; function was created to 1) identify the true position and size of all 60 | ; windows regardless of the window attributes, desktop theme, or version of 61 | ; Windows and to 2) identify the appropriate offset that is needed to position 62 | ; the window if the window is a different size than reported. 63 | ; 64 | ; * The true size, position, and offset of a window cannot be determined until 65 | ; the window has been rendered. See the example script for an example of how 66 | ; to use this function to position a new window. 67 | ; 68 | ; * 20150906: The "dwmapi\DwmGetWindowAttribute" function can return odd errors 69 | ; if DWM is not enabled. One error I've discovered is a return code of 70 | ; 0x80070006 with a last error code of 6, i.e. ERROR_INVALID_HANDLE or "The 71 | ; handle is invalid." To keep the function operational during this types of 72 | ; conditions, the function has been modified to assume that all unexpected 73 | ; return codes mean that DWM is not available and continue to process without 74 | ; it. When DWM is a possibility (i.e. Vista+), a developer-friendly messsage 75 | ; will be dumped to the debugger when these errors occur. 76 | ; 77 | ; * 20171126: (RiseUp) Changed function to return 4 offset values instead of 2. 78 | ; Windows 10 has different offsets for the top versus the bottom of a window, 79 | ; so this function no longer assumes a symmetrical offset border around a 80 | ; given window. 81 | ; 82 | ; Credit: 83 | ; 84 | ; Idea and some code from *KaFu* (AutoIt forum) 85 | ; 86 | ;------------------------------------------------------------------------------- 87 | WinGetPosEx(hWindow,ByRef X="",ByRef Y="",ByRef Width="",ByRef Height="" 88 | ,ByRef Offset_Left="",ByRef Offset_Top="" 89 | ,ByRef Offset_Right="",ByRef Offset_Bottom="") 90 | { 91 | Static Dummy5693 92 | ,RECTPlus 93 | ,S_OK:=0x0 94 | ,DWMWA_EXTENDED_FRAME_BOUNDS:=9 95 | 96 | ;-- Workaround for AutoHotkey Basic 97 | PtrType:=(A_PtrSize=8) ? "Ptr":"UInt" 98 | 99 | ;-- Get the window's dimensions 100 | ; Note: Only the first 16 bytes of the RECTPlus structure are used by the 101 | ; DwmGetWindowAttribute and GetWindowRect functions. 102 | VarSetCapacity(RECTPlus,32,0) 103 | DWMRC:=DllCall("dwmapi\DwmGetWindowAttribute" 104 | ,PtrType,hWindow ;-- hwnd 105 | ,"UInt",DWMWA_EXTENDED_FRAME_BOUNDS ;-- dwAttribute 106 | ,PtrType,&RECTPlus ;-- pvAttribute 107 | ,"UInt",16) ;-- cbAttribute 108 | 109 | if (DWMRC<>S_OK) 110 | { 111 | if ErrorLevel in -3,-4 ;-- Dll or function not found (older than Vista) 112 | { 113 | ;-- Do nothing else (for now) 114 | } 115 | else 116 | outputdebug, 117 | (ltrim join`s 118 | Function: %A_ThisFunc% - 119 | Unknown error calling "dwmapi\DwmGetWindowAttribute". 120 | RC=%DWMRC%, 121 | ErrorLevel=%ErrorLevel%, 122 | A_LastError=%A_LastError%. 123 | "GetWindowRect" used instead. 124 | ) 125 | 126 | ;-- Collect the position and size from "GetWindowRect" 127 | DllCall("GetWindowRect",PtrType,hWindow,PtrType,&RECTPlus) 128 | } 129 | 130 | ;-- Populate the output variables 131 | X:=Left := NumGet(RECTPlus,0,"Int") 132 | Y:=Top := NumGet(RECTPlus,4,"Int") 133 | Right := NumGet(RECTPlus,8,"Int") 134 | Bottom := NumGet(RECTPlus,12,"Int") 135 | Width := Right-Left 136 | Height := Bottom-Top 137 | Offset_Left := 0 138 | Offset_Top := 0 139 | Offset_Right := 0 140 | Offset_Bottom := 0 141 | 142 | ;-- If DWM is not used (older than Vista or DWM not enabled), we're done 143 | if (DWMRC<>S_OK) 144 | Return &RECTPlus 145 | 146 | ;-- Collect dimensions via GetWindowRect 147 | VarSetCapacity(RECT,16,0) 148 | DllCall("GetWindowRect",PtrType,hWindow,PtrType,&RECT) 149 | GWR_Left := NumGet(RECT,0,"Int") 150 | GWR_Top := NumGet(RECT,4,"Int") 151 | GWR_Right := NumGet(RECT,8,"Int") 152 | GWR_Bottom := NumGet(RECT,12,"Int") 153 | 154 | ;-- Calculate offsets and update output variables 155 | NumPut(Offset_Left := Left - GWR_Left,RECTPlus,16,"Int") 156 | NumPut(Offset_Top := Top - GWR_Top ,RECTPlus,20,"Int") 157 | NumPut(Offset_Right := GWR_Right - Right ,RECTPlus,24,"Int") 158 | NumPut(Offset_Bottom := GWR_Bottom - Bottom ,RECTPlus,28,"Int") 159 | 160 | Return &RECTPlus 161 | } 162 | --------------------------------------------------------------------------------