Sign in to follow this  
Followers 0
Jex

Client Position

8 posts in this topic

#1 ·  Posted (edited)

How can i find client position? That question looking easy but i can't find solution..

WinGetPos giving window position and i can't add + pixel for find client position because have menu and if im use another Windows skin that client position will be not true.

ControlGetPos giving window relative coordinate and that mean X=0 Y=0

I need WinGetClientPos :P

I'm tried AutoItSetOptions too but still can't find Window Client pos..

I need find client position for my Image Editor.

Edit : I'm found GetClientRect Function ( http://msdn2.microsoft.com/en-us/library/ms633503.aspx )

Edited by Jex

Share this post


Link to post
Share on other sites



I'm not sure if this will help but look into Opt("MouseCoordMode", 2).

Sets the way coords are used in the mouse functions, either absolute coords or coords relative to the current active window:

0 = relative coords to the active window

1 = absolute screen coordinates (default)

2 = relative coords to the client area of the active window


Agreement is not necessary - thinking for one's self is!

My-Colors.jpg

cuniform2.gif

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Func WinGetClientPos($Handle)
    $hwnd = WinGetHandle($Handle)
    $cPos = DllStructCreate("long;long;long;long")
    DllCall("user32.dll", "int", "GetClientRect", "hwnd", $hwnd, "ptr", DllStructGetPtr($cPos))
    Dim $cPos2[4] = [DllStructGetData($cPos, 1), DllStructGetData($cPos, 2), DllStructGetData($cPos, 3), DllStructGetData($cPos, 4)]
    Return $cPos2
EndFunc

Giving client relative coordinate ;)

Buffy opts not help.

Edit : Now im see Autoit have that function ( _WinAPI_GetClientRect )

Edit2 : I'm said Buffy but your nick Fossil Rock :P ?!

Edited by Jex

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Another way to do that UDF, just for fun:

#include <array.au3>

$PID = Run("Notepad.exe")
WinWait("Untitled - Notepad")
$hNotepad = WinGetHandle("Untitled - Notepad")
$avResult = _WinGetClientPos($hNotepad)
_ArrayDisplay($avResult, "Client Pos (Relative)")
$avResult = _WinGetClientPos($hNotepad, 1)
_ArrayDisplay($avResult, "Client Pos (Absolute)")
ProcessClose($PID)

; Returns X/Y coord of client are, absolute to the desktop if $fAbsolute <> 0
Func _WinGetClientPos($hWin, $fAbsolute = 0)
    If Not WinActivate($hWin) Then Return SetError(1, 0, 0)
    
    Local $cPos = DllStructCreate("long;long;long;long")
    DllCall("user32.dll", "int", "GetClientRect", "hwnd", $hWin, "ptr", DllStructGetPtr($cPos))
    Local $cPos2[4] = [DllStructGetData($cPos, 1), DllStructGetData($cPos, 2), DllStructGetData($cPos, 3), DllStructGetData($cPos, 4)]
    
    If $fAbsolute Then
        WinActivate($hWin)
        WinWaitActive($hWin)
        Local $MousePosSav = MouseGetPos()
        Local $MouseModeSav = Opt("MouseCoordMode", 2)
        MouseMove(0, 0, 0)
        Opt("MouseCoordMode", 1)
        Local $avRET = MouseGetPos()
        Opt("MouseCoordMode", $MouseModeSav)
        MouseMove($MousePosSav[0], $MousePosSav[1], 0)
        $cPos2[0] = $avRET[0]
        $cPos2[1] = $avRET[1]
        $cPos2[2] = $avRET[0] + $cPos2[2]
        $cPos2[3] = $avRET[1] + $cPos2[3]
    EndIf
    
    Return $cPos2
EndFunc   ;==>_WinGetClientPos

:P

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

PsaltyDS very thanks that method working but have problems.

$Timer = TimerInit()
            $Position = _WinGetClientPos(WinGetHandle($GUI), 1)
            MsgBox("", "", Round(TimerDiff($Timer), 0) & "ms")

+1000ms

and i can't loop that function because moving mouse every loop.

I need find better way for get client position :)

Edited by Jex

Share this post


Link to post
Share on other sites

PsaltyDS very thanks that method working but have problems.

$Timer = TimerInit()
            $Position = _WinGetClientPos(WinGetHandle($GUI), 1)
            MsgBox("", "", Round(TimerDiff($Timer), 0) & "ms")oÝ÷ ÛítÓI¬jwbq©÷öÙh¢aj×îËb¢vÞq«¬zj/x&¢ëz÷«ÊZ(¤Þy×âÖ޶׫Á¬¢¸µÉbz{i¢È­ÿªê-xbçl¢g¨~Ø^¥ªí±©Ý~§v+pjËaz·ªº*Þéí¶§²êÞ¶«z«¢­çpwhìiËb½ëajÛh¢F¥Ø^)N¬½êìåy«Þ²ØZ¶êm¢Ø^r^©"ayÆ¥©Ý­êeë"i¢X¬yÊ+ë,jëh×6#include <array.au3>

$PID = Run("Notepad.exe")
WinWait("Untitled - Notepad")
$hNotepad = WinGetHandle("Untitled - Notepad")
WinActivate($hNotepad)
WinWaitActive($hNotepad)

$iTimer = TimerInit()
$avResult = _WinGetClientPos() ; Relative
_ArrayDisplay($avResult, "Client Pos (Relative) in " & Round(TimerDiff($iTimer) / 1000, 3) & "secs")

Sleep(2000)

$iTimer = TimerInit()
$avResult = _WinGetClientPos(1) ; Absolute (to desktop)
_ArrayDisplay($avResult, "Client Pos (Absolute) in " & Round(TimerDiff($iTimer) / 1000, 3) & "secs")

ProcessClose($PID)

; Returns X/Y coord of client area of the active window; absolute to the desktop if $fAbsolute <> 0
Func _WinGetClientPos($fAbsolute = 0)
    Local $cPos = DllStructCreate("long;long;long;long"), $hWin = WinGetHandle("")
    DllCall("user32.dll", "int", "GetClientRect", "hwnd", $hWin, "ptr", DllStructGetPtr($cPos))
    Local $cPos2[4] = [DllStructGetData($cPos, 1), DllStructGetData($cPos, 2), DllStructGetData($cPos, 3), DllStructGetData($cPos, 4)]
    
    If $fAbsolute Then
        Local $MousePosSav = MouseGetPos()
        Local $MouseModeSav = Opt("MouseCoordMode", 2)
        MouseMove(0, 0, 0)
        Opt("MouseCoordMode", 1)
        Local $avRET = MouseGetPos()
        Opt("MouseCoordMode", $MouseModeSav)
        MouseMove($MousePosSav[0], $MousePosSav[1], 0)
        $cPos2[0] = $avRET[0]
        $cPos2[1] = $avRET[1]
        $cPos2[2] = $avRET[0] + $cPos2[2]
        $cPos2[3] = $avRET[1] + $cPos2[3]
    EndIf

    Return $cPos2
EndFunc   ;==>_WinGetClientPos

I can't help you with the mouse movement. The fuction moves the mouse exactly twice, at speed = 0 (instantaneous), and puts the both the mouse mode and mouse pos where they were before it started. This all happens too fast to see on my computer.

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Very thanks now working instantly :)

I'm changed code and now find client coordinate and size in 0ms ( _WinGetClientPos find in 1 or 2 ms ^_^ ) and not need move mouse.

Just in startup use that "Global $Client = _WinGetClientPos(1)" ( I mean after created GUI ) and later use "GetClientPos("Title")"

I think that method can find coordinates 100% true, if Windows Skin not changed but i'm not sure.

#include <Array.au3>

$tNotepad = "Untitled - Notepad"
$PID = Run("Notepad.exe")
WinWait($tNotepad)
$hNotepad = WinGetHandle($tNotepad)
WinActivate($hNotepad)
WinWaitActive($hNotepad)

Global $Client = _WinGetClientPos(1)
$iTimer = TimerInit()
$ClientPos = GetClientPos($tNotepad)
_ArrayDisplay($ClientPos, "Client position and size found in " & Round(TimerDiff($iTimer), 0) & "ms")
ProcessClose($PID)

Func GetClientPos($wTitle = "")
    Local $cPos[6]
    $wPos = WinGetPos($wTitle)
    $cPos[0] = $wPos[0] + $Client[0]
    $cPos[1] = $wPos[1] + $Client[1]
    $cPos[2] = ($wPos[0] + $wPos[2]) - $Client[2]
    $cPos[3] = ($wPos[1] + $wPos[3]) - $Client[3]
    $cPos[4] = $cPos[2] - $cPos[0]
    $cPos[5] = $cPos[3] - $cPos[1]
    Return $cPos
EndFunc   ;==>GetClientPos

Func _WinGetClientPos($fAbsolute = 0)
    Local $cPos = DllStructCreate("long;long;long;long"), $hWin = WinGetHandle("")
    DllCall("user32.dll", "int", "GetClientRect", "hwnd", $hWin, "ptr", DllStructGetPtr($cPos))
    Local $cPos2[4] = [DllStructGetData($cPos, 1), DllStructGetData($cPos, 2), DllStructGetData($cPos, 3), DllStructGetData($cPos, 4)]
    If $fAbsolute Then
        Local $MousePosSav = MouseGetPos()
        Local $MouseModeSav = Opt("MouseCoordMode", 2)
        MouseMove(0, 0, 0)
        Opt("MouseCoordMode", 1)
        Local $avRET = MouseGetPos()
        Opt("MouseCoordMode", $MouseModeSav)
        MouseMove($MousePosSav[0], $MousePosSav[1], 0)
        $wPos = WinGetPos("")
        $cPos2[0] = $avRET[0] - $wPos[0]
        $cPos2[1] = $avRET[1] - $wPos[1]
        $cPos2[2] = ($wPos[0] + $wPos[2]) - ($avRET[0] + $cPos2[2])
        $cPos2[3] = ($wPos[1] + $wPos[3]) - ($avRET[1] + $cPos2[3])
    EndIf
    Return $cPos2
EndFunc   ;==>_WinGetClientPos
Edited by Jex

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Use the _WinAPI_ClientToScreen($hWnd, ByRef $tPoint)

and _WinAPI_ScreenToClient($hWnd, ByRef $tPoint) functions to get the position of the client area.

Have a look at the help file to use the functions.

Easy and no hacks required via positioning of the mouse...

Edited by elloco

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0