Jump to content

RectRgn GetPos


Go to solution Solved by Deye,

Recommended Posts

Hi,

I'm trying to figure out how can I get the drawn rectangle Positions as if  it was a control placed on the main gui once PRIMARYDOWN mouse is up used with ControlGetPos (for instance)

I dont understand how i may get the positions of the rectangle and make it relative to the gui

in the example I'm trying to get a positive return if I will draw the rectangle over the button and false in the rectangle is drawn else where @not over the button

Thanks

#include <GUIConstants.au3>
#include <WinAPISysWin.au3>
#include <WinAPIGdi.au3>
#include <Misc.au3>

$hGui = GUICreate("Sample GUI", 406, 346)

$IdButton3 = GUICtrlCreateButton("Button_3", 68, 89, 65, 30)

GUISetState(@SW_SHOW)
Local $hDLL = DllOpen("user32.dll")


While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_PRIMARYDOWN
            _drawRect()
        Case $GUI_EVENT_CLOSE
            DllClose($hDLL)
            Exit
    EndSwitch
WEnd


Func _drawRect()
    $GUIPos = WinGetPos($hGui, "")

    Global $hRectangle_GUI = GUICreate("", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_TOOLWINDOW + $WS_EX_TOPMOST, $hGui)
    GUISetBkColor(0x000000)

    ; Get first mouse position
    $aMouse_Pos = MouseGetPos()
    $iX1 = $aMouse_Pos[0]
    $iY1 = $aMouse_Pos[1]

    While _IsPressed("01", $hDLL)
        $aMouse_Pos = MouseGetPos()
        $hMaster_Mask = _WinAPI_CreateRectRgn(0, 0, 0, 0)
        $hMask = _WinAPI_CreateRectRgn($iX1, $aMouse_Pos[1], $aMouse_Pos[0], $aMouse_Pos[1] + 1)   ; Bottom of rectangle
        _WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
        _WinAPI_DeleteObject($hMask)
        $hMask = _WinAPI_CreateRectRgn($iX1, $iY1, $iX1 + 1, $aMouse_Pos[1]) ; Left of rectangle
        _WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
        _WinAPI_DeleteObject($hMask)
        $hMask = _WinAPI_CreateRectRgn($iX1 + 1, $iY1 + 1, $aMouse_Pos[0], $iY1) ; Top of rectangle
        _WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
        _WinAPI_DeleteObject($hMask)
        $hMask = _WinAPI_CreateRectRgn($aMouse_Pos[0], $iY1, $aMouse_Pos[0] + 1, $aMouse_Pos[1])  ; Right of rectangle
        _WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
        _WinAPI_DeleteObject($hMask)
        ; Set overall region
        _WinAPI_SetWindowRgn($hRectangle_GUI, $hMaster_Mask)
        If WinGetState($hRectangle_GUI) < 15 Then GUISetState()
    WEnd
    ConsoleWrite(_hWnd_IsVisible($IdButton3, $hRectangle_GUI) & @LF)
    
    GUIDelete($hRectangle_GUI)
EndFunc   ;==>_drawRect

Func _hWnd_IsVisible($hWnd, $hWnd_ParentGui = 0)

    Local $tRect_hWnd = _WinAPI_GetWindowRect($hWnd)
    Local $h_Rgn_hWnd = _WinAPI_CreateRectRgn(DllStructGetData($tRect_hWnd, 1), DllStructGetData($tRect_hWnd, 2), DllStructGetData($tRect_hWnd, 3), DllStructGetData($tRect_hWnd, 4))

    Local $tRect_hWndPrev, $h_Rgn_hWndPrev

    Local $aList = WinList()

    For $i = 1 To $aList[0][0]
        If $aList[$i][1] = $hWnd Then ExitLoop
        If BitAND(WinGetState($aList[$i][1]), 2) And $aList[$i][1] <> $hWnd_ParentGui Then
            $tRect_hWndPrev = _WinAPI_GetWindowRect($aList[$i][1])
            $h_Rgn_hWndPrev = _WinAPI_CreateRectRgn(DllStructGetData($tRect_hWndPrev, 1), DllStructGetData($tRect_hWndPrev, 2), DllStructGetData($tRect_hWndPrev, 3), DllStructGetData($tRect_hWndPrev, 4))
            _WinAPI_CombineRgn($h_Rgn_hWnd, $h_Rgn_hWnd, $h_Rgn_hWndPrev, $RGN_DIFF)
            _WinAPI_DeleteObject($h_Rgn_hWndPrev)
        EndIf
    Next

    Local $iRes = _WinAPI_GetRgnBox($h_Rgn_hWnd, $tRect_hWnd)
    _WinAPI_DeleteObject($h_Rgn_hWnd)

    Switch $iRes
        Case 1 ; $NULLREGION
            Return 0
        Case 2 ; $SIMPLEREGION
            Return 1
        Case 3 ; $COMPLEXREGION
            Return 1
        Case Else ; 0 = Error
            Return -1
    EndSwitch

EndFunc   ;==>_hWnd_IsVisible

 

Edited by Deye
Link to post
Share on other sites

Just updated my question .. The example now includes @kafu's example from here in hopes that it can be worked out in the suggested way 

the example is roughly put there are many things that aren't getting properly considered ( I know)

in the example I'm trying to get a positive return if I will draw the rectangle over the button and false in the rectangle is drawn else where @not over the button

if not and this  can get  done in another way, Please suggest 

Thanks

 

Edited by Deye
Link to post
Share on other sites

Try this  - works for me :

#include <Constants.au3>
#include <GUIConstants.au3>
#include <WinAPISysWin.au3>
#include <WinAPIGdi.au3>
#include <Misc.au3>
#include <WinAPIConv.au3>

$hGui = GUICreate("Sample GUI", 406, 346)

$IdButton3 = GUICtrlCreateButton("Button_3", 68, 89, 65, 30)

GUISetState(@SW_SHOW)
Local $hDLL = DllOpen("user32.dll"), $aPos


While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_PRIMARYDOWN
            $aPos = _drawRect()
            MsgBox ($MB_SYSTEMMODAL,"",Check ($hGui, $IdButton3, $aPos))
        Case $GUI_EVENT_CLOSE
            DllClose($hDLL)
            Exit
    EndSwitch
WEnd


Func _drawRect()
    $GUIPos = WinGetPos($hGui, "")

    Global $hRectangle_GUI = GUICreate("", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_TOOLWINDOW + $WS_EX_TOPMOST, $hGui)
    GUISetBkColor(0x000000)

    ; Get first mouse position
    $aMouse_Pos = MouseGetPos()
    $iX1 = $aMouse_Pos[0]
    $iY1 = $aMouse_Pos[1]

    While _IsPressed("01", $hDLL)
        $aMouse_Pos = MouseGetPos()
        $hMaster_Mask = _WinAPI_CreateRectRgn(0, 0, 0, 0)
        $hMask = _WinAPI_CreateRectRgn($iX1, $aMouse_Pos[1], $aMouse_Pos[0], $aMouse_Pos[1] + 1)   ; Bottom of rectangle
        _WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
        _WinAPI_DeleteObject($hMask)
        $hMask = _WinAPI_CreateRectRgn($iX1, $iY1, $iX1 + 1, $aMouse_Pos[1]) ; Left of rectangle
        _WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
        _WinAPI_DeleteObject($hMask)
        $hMask = _WinAPI_CreateRectRgn($iX1 + 1, $iY1 + 1, $aMouse_Pos[0], $iY1) ; Top of rectangle
        _WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
        _WinAPI_DeleteObject($hMask)
        $hMask = _WinAPI_CreateRectRgn($aMouse_Pos[0], $iY1, $aMouse_Pos[0] + 1, $aMouse_Pos[1])  ; Right of rectangle
        _WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
        _WinAPI_DeleteObject($hMask)
        ; Set overall region
        _WinAPI_SetWindowRgn($hRectangle_GUI, $hMaster_Mask)
        If WinGetState($hRectangle_GUI) < 15 Then GUISetState()
    WEnd
    GUIDelete($hRectangle_GUI)
    Return StringSplit ($iX1 & "/" & $iY1 & "/" & $aMouse_Pos[0] & "/" & $aMouse_Pos[1],"/", $STR_NOCOUNT)
EndFunc   ;==>_drawRect

Func Check ($hWnd, $idCtrl, $aPos)
    Local $tPoint = DllStructCreate("int X;int Y")
    DllStructSetData($tPoint, "X", $aPos[0])
    DllStructSetData($tPoint, "Y", $aPos[1])
    _WinAPI_ScreenToClient($hWnd, $tPoint)
    $aPos[0] = DllStructGetData($tPoint, "X")
    $aPos[1] = DllStructGetData($tPoint, "Y")
    DllStructSetData($tPoint, "X", $aPos[2])
    DllStructSetData($tPoint, "Y", $aPos[3])
    _WinAPI_ScreenToClient($hWnd, $tPoint)
    $aPos[2] = DllStructGetData($tPoint, "X")
    $aPos[3] = DllStructGetData($tPoint, "Y")
    Local $idPos = ControlGetPos ($hWnd, "", $idCtrl)
    Return $idPos[0] >= $aPos[0] and $idPos[1] >= $aPos[1] and $idPos[0]+$idPos[2]-1 <= $aPos[2] and $idPos[1]+$idPos[3]-1 <= $aPos[3]
EndFunc

 

Link to post
Share on other sites
  • Solution

@Nine Not quite there: if you draw  a  rectangle  anywhere over a control it should return true !!

i tried doing it your way and it seemed to work for a while till I tried drawing the rectangle in a reversed way then the calculations need to change apparently but didn't get to make it work

;.......>
    Local $idPos = ControlGetPos ($hWnd, "", $idCtrl)
    If $idPos[0] > $aPos[2] Then
    ElseIf $aPos[2] > $idPos[0] + $idPos[2] And $aPos[0] > $idPos[0] + $idPos[2] Then
    Else
        If $aPos[3] + ($aPos[1] - $aPos[3]) < $idPos[1] Or $aPos[3] > $idPos[1] + $idPos[3] Then
        Else
            Return True
        EndIf
    EndIf
    Return False

Edit: maybe this will do it:

;.......>
    Local $idPos = ControlGetPos ($hWnd, "", $idCtrl)
    $RectR = $aPos[2] > $aPos[0] ? $aPos[2] : $aPos[0]
    $RectL = ($RectR = $aPos[2] ? $aPos[0] : $aPos[2])
    $RectT = $aPos[3] < $aPos[1] ? $aPos[3] : $aPos[1]
    $RectB = ($RectT = $aPos[3] ? $aPos[1] : $aPos[3])

    Local $idPos = ControlGetPos($hWnd, "", $idCtrl)
    If $idPos[0] > $RectR Then
    ElseIf $RectR > $idPos[0] + $idPos[2] And $RectL > $idPos[0] + $idPos[2] Then
    Else
        If $RectT + ($RectB - $RectT) < $idPos[1] Or $RectT > $idPos[1] + $idPos[3] Then
        Else
            Return True
        EndIf
    EndIf
    Return False
EndFunc   ;==>Check

maybe if we could get the rect pointers of the $hRectangle_GUI  relative to the main gui  it be easier to make it work with kafu's example
 

 

Edited by Deye
Link to post
Share on other sites
5 hours ago, Deye said:

if you draw  a  rectangle  anywhere over a control it should return true !!

Ah, I thought the rectangle need to cover all the control, then change the return to this :

Return $idPos[0] <= $aPos[2] And $idPos[1] <= $aPos[3] And $idPos[0] + $idPos[2] - 1 >= $aPos[0] And $idPos[1] + $idPos[3] - 1 >= $aPos[1]

Makes it more readable. 

Ya,  I forgot about drawing the rectangle from bottom to top or right to left.  Good catch :)

 

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
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...