;------------------------------ ; ; 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 ; for more information. ; ; Parameters: ; ; hWindow - Handle to the window. ; ; X, Y, Width, Height - Output variables. [Optional] If defined, these ; variables contain the coordinates of the window relative to the ; upper-left corner of the screen (X and Y), and the Width and Height 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 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_Left, Offset_Top, Offset_Right, and Offset_Bottom) are ; updated. See the *Parameters* section for more more information. ; ; If not successful, FALSE is returned. ; ; Requirement: ; ; Windows 2000+ ; ; Remarks, Observations, and Changes: ; ; * Starting with Windows Vista, Microsoft includes the Desktop Window Manager ; (DWM) along with Aero-based themes that use DWM. Aero themes provide new ; features like a translucent glass design with subtle window animations. ; Unfortunately, the DWM doesn't always conform to the OS rules for size and ; positioning of windows. If using an Aero theme, many of the windows are ; actually larger than reported by Windows when using standard commands (Ex: ; WinGetPos, GetWindowRect, etc.) and because of that, are not positioned ; correctly when using standard commands (Ex: gui Show, WinMove, etc.). This ; function was created to 1) identify the true position and size of all ; windows regardless of the window attributes, desktop theme, or version of ; Windows and to 2) identify the appropriate offset that is needed to position ; the window if the window is a different size than reported. ; ; * The true size, position, and offset of a window cannot be determined until ; the window has been rendered. See the example script for an example of how ; to use this function to position a new window. ; ; * 20150906: The "dwmapi\DwmGetWindowAttribute" function can return odd errors ; if DWM is not enabled. One error I've discovered is a return code of ; 0x80070006 with a last error code of 6, i.e. ERROR_INVALID_HANDLE or "The ; handle is invalid." To keep the function operational during this types of ; conditions, the function has been modified to assume that all unexpected ; return codes mean that DWM is not available and continue to process without ; 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_Left="",ByRef Offset_Top="" ,ByRef Offset_Right="",ByRef Offset_Bottom="") { Static Dummy5693 ,RECTPlus ,S_OK:=0x0 ,DWMWA_EXTENDED_FRAME_BOUNDS:=9 ;-- Workaround for AutoHotkey Basic PtrType:=(A_PtrSize=8) ? "Ptr":"UInt" ;-- 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,32,0) DWMRC:=DllCall("dwmapi\DwmGetWindowAttribute" ,PtrType,hWindow ;-- hwnd ,"UInt",DWMWA_EXTENDED_FRAME_BOUNDS ;-- dwAttribute ,PtrType,&RECTPlus ;-- pvAttribute ,"UInt",16) ;-- cbAttribute if (DWMRC<>S_OK) { if ErrorLevel in -3,-4 ;-- Dll or function not found (older than Vista) { ;-- Do nothing else (for now) } else outputdebug, (ltrim join`s Function: %A_ThisFunc% - Unknown error calling "dwmapi\DwmGetWindowAttribute". RC=%DWMRC%, ErrorLevel=%ErrorLevel%, A_LastError=%A_LastError%. "GetWindowRect" used instead. ) ;-- Collect the position and size from "GetWindowRect" DllCall("GetWindowRect",PtrType,hWindow,PtrType,&RECTPlus) } ;-- 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_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) Return &RECTPlus ;-- Collect dimensions via GetWindowRect VarSetCapacity(RECT,16,0) DllCall("GetWindowRect",PtrType,hWindow,PtrType,&RECT) 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 }