获取比WinGetPos更准确的窗口位置大小信息

由于一些窗口特效的原故, WinGetPos获取的窗口大小与显示效果是不一致的, 可以看到有很大的空隙

获取比WinGetPos更准确的窗口位置大小信息

可以用另一个函数获得更精确的位置和大小

WinGetPosEx(hwnd, byref x := 0, byref y := 0, byref w := 0, byref h := 0){
    VarSetCapacity(rect, 16)
    if !DllCall("dwmapi\DwmGetWindowAttribute", "ptr", hwnd, "uint", 9, "ptr", &rect, "uint", 16) {
        x := NumGet(rect, "int")
        y := NumGet(rect, 4, "int")
        w := NumGet(rect, 8, "int") - x
        h := NumGet(rect, 12, "int") - y
        return true
    }
}

使用:

hwnd := WinExist("A")

WinGetPos, x1, y1, w1, h1, ahk_id %hwnd%
WinGetPosEx(hwnd, x2, y2, w2, h2)

MsgBox % "
(
WinGetPos`t|`tWinGetPosEx
x1: " x1 "`t`t|`tx2: " x2 "
y1: " y1 "`t`t|`ty2: " y2 "
w1: " w1 "`t`t|`tw2: " w2 "
h1: " h1 "`t`t|`th2: " h2 "
)"

这样就完美贴合了

获取比WinGetPos更准确的窗口位置大小信息

给使用V2的朋友等效的函数:

WinGetPosEx(hwnd, &x?, &y?, &w?, &h?){
    if !DllCall("dwmapi\DwmGetWindowAttribute", "ptr", hwnd, "uint", 9, "ptr", rect := Buffer(16), "uint", 16) {
        x := NumGet(rect, "int")
        y := NumGet(rect, 4, "int")
        w := NumGet(rect, 8, "int") - x
        h := NumGet(rect, 12, "int") - y
        return true
    }
}

给TA捐赠
共{{data.count}}人
人已捐赠
其他

双方案快速查帮助

2022-9-25 11:21:58

其他案例

excelio v1使用心得(1)

2022-9-26 19:21:55

5 条回复 A文章作者 M管理员
  1. maxs

    WinMove有类似的函数吗?

    • Tebayaki

      不清楚你的意思, 涉及到窗口坐标可以通过这两个函数间接实现

    • jly

      WinMove和WinGetPos的xywh都是一 一对应的。 你用WinMove的时候,对xy加上或者减去相应的误差就可以了。 可以参考这个函数,它返回了xy的误差(注:y的误差它计算错了,其实用两个y值相减就行)。 https://www.autohotkey.com/boards/viewtopic.php?f=6&t=3392 WinGetPosEx(hWindow,ByRef X=””,ByRef Y=””,ByRef Width=””,ByRef Height=””,ByRef Offset_X=””,ByRef Offset_Y=””) { 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,24,0) DWMRC:=DllCall(“dwmapiDwmGetWindowAttribute” ,PtrType,hWindow ;– hwnd ,”UInt”,DWMWA_EXTENDED_FRAME_BOUNDS ;– dwAttribute ,PtrType,&RECTPlus ;– pvAttribute ,”UInt”,16) ;– cbAttribute if (DWMRCS_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 “dwmapiDwmGetWindowAttribute”. 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_X:=0 OffSet_Y:=0 ;– If DWM is not used (older than Vista or DWM not enabled), we’re done if (DWMRCS_OK) Return &RECTPlus ;– 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”) Return &RECTPlus }

  2. maxs

    您好,我想用在窗口分屏的代码里。代码的思路是获取显示器的长和宽,计算出所需要 窗口的x,y,w,h。但就是您所研究的“误差”,导致a窗口和b窗口之间会有缝隙。 分屏代码最后一步WinMove, A,, x, y, w, h。所以想知道能不能有个WinMoveEx函数啊,对其校正,实现无缝

    • jly

      WinGetPosEx 获取的xywh 和 WinGetPos 获取的xywh 相差多少,你使用WinMove的时候,加减相应的差就可以了。

个人中心
购物车
优惠劵
有新私信 私信列表
搜索