Chimp

how to find the window(s) below another window?

13 posts in this topic

#1 ·  Posted (edited)

this is a draft snippet about using windows GUI as draggable "cards".
what I'm trying to achieve is a way to know on what "card" (on what window)  the dragged card has been dropped.
I would prefer not to have to use an array to store all the windows "cards", and have to search through that array to see if the dropped card is on one of that stored in the array, but a way (a function) that will return "directly" the handle of the "card" that received the dropped "window" that is the window(s) below the dropped window. (maybe ther is a _WinAPI* for that?).
Any suggestion is welcome.
(sorry for my bad attempt at this English explanation)

#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <APISysConstants.au3>
#include <WinAPI.au3>
#include <GUIMenu.au3>
#include <WinAPIProc.au3>
#include <WinAPISys.au3>

; https://www.autoitscript.com/forum/topic/164271-detect-when-any-and-all-windows-have-moved/?do=findComment&comment=1198129
Global $hEventProc = DllCallbackRegister(_EventProc, "none", "ptr;dword;hwnd;long;long;dword;dword")
Global $hEventHook = _WinAPI_SetWinEventHook($EVENT_MIN, $EVENT_MAX, DllCallbackGetPtr($hEventProc))

OnAutoItExitRegister(OnAutoItExit) ; clear the hook on exit

Global $hMainWin = GUICreate('My main GUI', 400, 250, 50, 50)
GUISetState(@SW_SHOW)

$hGUI_Child0 = GUICreate('hand', 100, 100, 10, 0, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child0) ; a 2-element array containing Width and Height of window's client area (inner area excluding borders).
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG) ; this allow dragging of the "card" by click on "card" and drag.
GUICtrlCreateIcon("shell32.dll", 29, 0, 0, $aHostDim[0], $aHostDim[1]) ; put something to see on the card
GUISetState(@SW_SHOW, $hGUI_Child0)
_WinAPI_SetParent($hGUI_Child0, $hMainWin) ; trap this child gui within the main gui
;
$hGUI_Child1 = GUICreate('tree', 100, 100, 25, 15, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child1)
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlCreateIcon("shell32.dll", 42, 0, 0, $aHostDim[0], $aHostDim[1])
GUISetState(@SW_SHOW, $hGUI_Child1)
_WinAPI_SetParent($hGUI_Child1, $hMainWin)
;
$hGUI_Child2 = GUICreate('star', 100, 100, 40, 30, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlCreateIcon("shell32.dll", 44, 0, 0, $aHostDim[0], $aHostDim[1])
GUISetState(@SW_SHOW, $hGUI_Child2)
_WinAPI_SetParent($hGUI_Child2, $hMainWin)

MsgBox(0, "Pause", "Drag images on the Main GUI" & @CRLF & "Click OK to end")

Func _EventProc($hEventHook, $iEvent, $hWnd, $iObjectID, $iChildID, $iThreadId, $iEventTime)
    #forceref $hEventHook, $iObjectID, $iChildID, $iThreadId, $iEventTime
    ; Static $lastevent
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/dd318066%28v=vs.85%29.aspx
    Switch $iEvent
        Case $EVENT_SYSTEM_MOVESIZESTART
            ; ConsoleWrite("Start:" & @TAB & $iEvent & @TAB & $hWnd & @TAB & $iObjectID & @TAB & $iChildID & @CRLF)

        Case $EVENT_SYSTEM_MOVESIZEEND ; to be used as drop
            if _WinAPI_GetAncestor($hWnd) = $hMainWin Then
                ConsoleWrite(WinGetTitle($hWnd) & " dropped on.... ???" & @CRLF)
            EndIf
        Case Else
            #cs If $iEvent <> $lastevent Then
                ConsoleWrite("event:" & @TAB & $iEvent & @CRLF)
                $lastevent = $iEvent
            #ce EndIf
    EndSwitch
EndFunc   ;==>_EventProc

Func OnAutoItExit()
    _WinAPI_UnhookWinEvent($hEventHook)
    DllCallbackFree($hEventProc)
EndFunc   ;==>OnAutoItExit

 

Edited by Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites



#3 ·  Posted (edited)

Maybe you can use something like this. It might be necessary to exclude the window being dragged from the list.

 

#include <misc.au3>

HotKeySet("{ESC}", "_Exit")

Local $aMousePos, $_hWnd_OnPos

While 1
    Sleep(10)
    If _IsPressed("01") Then
        $aMousePos = MouseGetPos()
        $_hWnd_OnPos = _hWnd_Visible_AtPos($aMousePos[0], $aMousePos[1])
        ConsoleWrite($_hWnd_OnPos & @TAB & WinGetTitle($_hWnd_OnPos) & @CRLF)
        While _IsPressed("01")
            Sleep(10)
        WEnd
    EndIf
WEnd

Func _hWnd_Visible_AtPos($x, $y)
    Local $aWinlist = WinList()
    Local $aWinlist_Final[100][6], $iEnum, $aPos

    For $i = 1 To $aWinlist[0][0]
        If BitAND(WinGetState($aWinlist[$i][1]), 2) Then ; is visible
            $aWinlist_Final[$iEnum][0] = $aWinlist[$i][0]
            $aWinlist_Final[$iEnum][1] = $aWinlist[$i][1]
            $aPos = WinGetPos($aWinlist[$i][1])
            $aWinlist_Final[$iEnum][2] = $aPos[0] ; x
            $aWinlist_Final[$iEnum][3] = $aPos[1] ; y
            $aWinlist_Final[$iEnum][4] = $aPos[2] ; w
            $aWinlist_Final[$iEnum][5] = $aPos[3] ; h
            $iEnum += 1
            If Not Mod($iEnum, 100) Then ReDim $aWinlist_Final[UBound($aWinlist_Final) + 100][6]
        EndIf
    Next

    ReDim $aWinlist_Final[$iEnum - 1][6]

    For $i = 0 To $iEnum - 1
        If $x >= $aWinlist_Final[$i][2] And $x <= ($aWinlist_Final[$i][2] + $aWinlist_Final[$i][4]) And _
                $y >= $aWinlist_Final[$i][3] And $y <= ($aWinlist_Final[$i][3] + $aWinlist_Final[$i][5]) Then Return $aWinlist_Final[$i][1]
    Next

    Return 0

EndFunc   ;==>_hWnd_Visible_AtPos

Func _Exit()
    Exit
EndFunc   ;==>_Exit

 

Edited by KaFu
1 person likes this

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

You can try this

Case $EVENT_SYSTEM_MOVESIZEEND ; to be used as drop
            If _WinAPI_GetAncestor($hWnd) = $hMainWin Then
                Local $hTop = _WinAPI_GetWindow($hMainWin, $GW_CHILD)
                Local $hNext = _WinAPI_GetWindow ($hTop,  $GW_HWNDNEXT)
               ConsoleWrite(WinGetTitle($hTop) & " dropped on " & WinGetTitle($hNext) & @CRLF)
            EndIf

 

But it will only display the next on z order!

Edited by UEZ
1 person likes this

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

Not sure if I am getting it right.

Wouldn't this be just a 

https://www.autoitscript.com/autoit3/docs/libfunctions/_WinAPI_WindowFromPoint.htm

Then define what the definition is of dropping a card on another one.

1. Its the mouse cursor position where you release the moved card

2. Its any of the boundarypoints of the moved card

3. ......

and maybe this gives another solution direction

it looks easy over here ;-) but to difficult for me

https://msdn.microsoft.com/en-us/library/windows/desktop/ms678405(v=vs.85).aspx

 

1 person likes this

Share this post


Link to post
Share on other sites

If I got what you meant I edit your code and Got this:

 

#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <APISysConstants.au3>
#include <WinAPI.au3>
#include <GUIMenu.au3>
#include <WinAPIProc.au3>
#include <WinAPISys.au3>
#include <GDIPlus.au3>
#include <WinAPIShellEx.au3>


Global Const $hOLEACC = DllOpen("oleacc.dll")
Global Const $hOleAut = DllOpen("oleaut.dll")

Global Const $stagVARIANT = "ushort vt;ushort r1;ushort r2;ushort r3;ptr data; ptr"
Global $tVar = DllStructCreate($stagVARIANT)
Global $pvarChild = DllStructGetPtr($tVar)

Global Const $sIID_IAccessible = "{618736e0-3c3d-11cf-810c-00aa00389b71}"

; https://www.autoitscript.com/forum/topic/164271-detect-when-any-and-all-windows-have-moved/?do=findComment&comment=1198129
Global $hEventProc = DllCallbackRegister(_EventProc, "none", "ptr;dword;hwnd;long;long;dword;dword")
Global $hEventHook = _WinAPI_SetWinEventHook($EVENT_MIN, $EVENT_MAX, DllCallbackGetPtr($hEventProc))

OnAutoItExitRegister(OnAutoItExit) ; clear the hook on exit
Global $oMyError = ObjEvent("AutoIt.Error", "_ErrFunc")

Global $hMainWin = GUICreate('My main GUI', 400, 250, 50, 50)
GUISetState(@SW_SHOW)

_GDIPlus_Startup()

$hGUI_Child0 = GUICreate('Notepad', 100, 100, 10, 0, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child0) ; a 2-element array containing Width and Height of window's client area (inner area excluding borders).
$hIcon0 = _WinAPI_ShellExtractIcon('notepad.exe', 0, $aHostDim[0], $aHostDim[1])
$hBitmap0 = _GDIPlus_BitmapCreateFromHICON($hIcon0)
Global $g_hGraphic0 = _GDIPlus_GraphicsCreateFromHWND($hGUI_Child0)
GUISetState(@SW_SHOW, $hGUI_Child0)
_WinAPI_SetParent($hGUI_Child0, $hMainWin) ; trap this child gui within the main gui

;
$hGUI_Child1 = GUICreate('Folder', 100, 100, 25, 15, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child1)
$hIcon1 = _WinAPI_ShellExtractIcon('explorer.exe', 0, $aHostDim[0], $aHostDim[1])
$hBitmap1 = _GDIPlus_BitmapCreateFromHICON($hIcon1)
Global $g_hGraphic1 = _GDIPlus_GraphicsCreateFromHWND($hGUI_Child1)
GUISetState(@SW_SHOW, $hGUI_Child1)
_WinAPI_SetParent($hGUI_Child1, $hMainWin)

$hGUI_Child2 = GUICreate('Calc', 100, 100, 40, 30, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$hIcon2 = _WinAPI_ShellExtractIcon('Calc.exe', 0, $aHostDim[0], $aHostDim[1])
$hBitmap2 = _GDIPlus_BitmapCreateFromHICON($hIcon2)
Global $g_hGraphic2 = _GDIPlus_GraphicsCreateFromHWND($hGUI_Child2)

GUISetState(@SW_SHOW, $hGUI_Child2)
_WinAPI_SetParent($hGUI_Child2, $hMainWin)

GUIRegisterMsg($WM_PAINT, "MY_WM_PAINT")
GUIRegisterMsg($WM_LBUTTONDOWN, "_WinMove")

;~ Paint first
_GDIPlus_GraphicsDrawImage($g_hGraphic0, $hBitmap0, 0, 0)
_GDIPlus_GraphicsDrawImage($g_hGraphic1, $hBitmap1, 0, 0)
_GDIPlus_GraphicsDrawImage($g_hGraphic2, $hBitmap2, 0, 0)

VariantInit($pvarChild)
MsgBox(0, "Pause", "Drag images on the Main GUI" & @CRLF & "Click OK to end")
_GDIPlus_GraphicsDispose($g_hGraphic0)
_GDIPlus_GraphicsDispose($g_hGraphic1)
_GDIPlus_GraphicsDispose($g_hGraphic2)
_GDIPlus_BitmapDispose($hBitmap0)
_GDIPlus_BitmapDispose($hBitmap1)
_GDIPlus_BitmapDispose($hBitmap2)
_GDIPlus_Shutdown()
DllClose($hOleAut)
DllClose($hOLEACC)



;~ Just for Move
Func _WinMove($HWnd, $Command, $wParam, $lParam)
    If BitAND(WinGetState($HWnd), 32) Then Return $GUI_RUNDEFMSG
    DllCall("user32.dll", "long", "SendMessage", "hwnd", $HWnd, "int", $WM_SYSCOMMAND, "int", 0xF009, "int", 0)
EndFunc   ;==>_WinMove

; Draw PNG image
Func MY_WM_PAINT($HWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
    _WinAPI_RedrawWindow($hMainWin, 0, 0, $RDW_UPDATENOW)
    _GDIPlus_GraphicsDrawImage($g_hGraphic0, $hBitmap0, 0, 0)
    _GDIPlus_GraphicsDrawImage($g_hGraphic1, $hBitmap1, 0, 0)
    _GDIPlus_GraphicsDrawImage($g_hGraphic2, $hBitmap2, 0, 0)
    _WinAPI_RedrawWindow($hMainWin, 0, 0, $RDW_VALIDATE)
    Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_WM_PAINT



Func _EventProc($hEventHook, $iEvent, $HWnd, $iObjectID, $iChildID, $iThreadId, $iEventTime)
    #forceref $hEventHook, $iObjectID, $iChildID, $iThreadId, $iEventTime
    ; Static $lastevent
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/dd318066%28v=vs.85%29.aspx

    Local $aWin = 0

    Switch $iEvent
        Case $EVENT_SYSTEM_MOVESIZESTART
            ; ConsoleWrite("Start:" & @TAB & $iEvent & @TAB & $hWnd & @TAB & $iObjectID & @TAB & $iChildID & @CRLF)

        Case $EVENT_SYSTEM_MOVESIZEEND ; to be used as drop

            If _WinAPI_GetAncestor($HWnd) = $hMainWin Then

                $aWin = WinGetPos($HWnd)
                If IsArray($aWin) Then
                    ConsoleWrite(WinGetTitle($HWnd) & " dropped on " & _GetWindows($aWin) & @CRLF)
                EndIf
            EndIf

        Case Else
            #cs If $iEvent <> $lastevent Then
                ConsoleWrite("event:" & @TAB & $iEvent & @CRLF)
                $lastevent = $iEvent
            #ce EndIf
    EndSwitch
EndFunc   ;==>_EventProc

Func OnAutoItExit()
    _WinAPI_UnhookWinEvent($hEventHook)
    DllCallbackFree($hEventProc)
EndFunc   ;==>OnAutoItExit


Func _GetWindows($aArray)
    Local $pIAccesible = 0
    Local $oIAccesible = 0
    Local $aRet = 0
    Local $x = 0, $y = 0
    Local $sWindows = ""
    Local $aMain = WinGetPos($hMainWin)
    Local $iBarheight = 0
    For $i = 0 To 4 - 1 ;check 4 object(Child window) corners

        Switch $i
            Case 0
                $x = $aArray[0] - 1
                $y = $aArray[1] - 1
            Case 1
                $x = $aArray[0] + $aArray[2] + 1
                $y = $aArray[1] - 1
            Case 2
                $x = $aArray[0] + $aArray[2] + 1
                $y = $aArray[1] + $aArray[3] + 1
            Case 3
                $x = $aArray[0] - 1
                $y = $aArray[1] + $aArray[3] + 1
            Case Else

        EndSwitch
        $iBarheight = _WinAPI_GetSystemMetrics($SM_CYCAPTION)

        If $x < $aMain[0] Or $y < ($aMain[1] + $iBarheight) Then ContinueLoop
        If $x > ($aMain[0] + $aMain[2]) Or $y > ($aMain[1] + $aMain[3]) Then ContinueLoop


        $aRet = DllCall($hOLEACC, "int", "AccessibleObjectFromPoint", _
                "int", $x, _
                "int", $y, _
                "ptr*", 0, _
                "ptr", $pvarChild)

        If @error Or $aRet[0] <> 0 Then ContinueLoop

        $pIAccesible = $aRet[3]
        $oIAccesible = ObjCreateInterface($pIAccesible, $sIID_IAccessible)
        If (WinGetTitle($hMainWin) <> $oIAccesible.accName) Then
            $sWindows &= (($sWindows <> "") ? " and " : "") & $oIAccesible.accName
        EndIf
        If $aRet[0] = 0 Then VariantClear($pvarChild)
        $oIAccesible = 0
        $aRet=0

    Next
    If $sWindows = "" Then $sWindows = WinGetTitle($hMainWin)
    Return $sWindows


EndFunc   ;==>_GetWindows



Func VariantClear($pvariant)
    Local $aRet = DllCall($hOleAut, "long", "VariantClear", "ptr", $pvariant)
    If @error Then Return SetError(1, 0, 1)
    Return $aRet[0]
EndFunc   ;==>VariantClear

Func VariantInit($pvariant)
    Local $aRet = DllCall($hOleAut, "long", "VariantInit", "ptr", $pvariant)
    If @error Then Return SetError(1, 0, 1)
    Return $aRet[0]
EndFunc   ;==>VariantInit


Func _ErrFunc($oError)
    ; Do anything here.
    ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _
            @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _
            @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _
            @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _
            @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _
            @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _
            @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _
            @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _
            @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _
            @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF)
EndFunc   ;==>_ErrFunc

Saludos

1 person likes this

Share this post


Link to post
Share on other sites

@Danyfirex: Nice piece of code    

@CHIMP: It depends on your definition of drop on another window, if you now select the bottom one to become in foreground its dropped on the top window whereas probably thats not the definition of a drop (suggestion if mouse moves more then n pixels from starting point its a drag/drop operation whereas n>=5 but 5 is an arbitrary choice)

1 person likes this

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Thanks all for the good suggestions and interesting solutions, very appreciated!
Sorry for the delay on answering, I'm not around on this days.
I will elaborate on this nice answers and will report here about results.
Thanks everybody (for now).

Edited by Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

I was thinking why not use collision detection so a wrote this:

#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <APISysConstants.au3>
#include <WinAPI.au3>
#include <GUIMenu.au3>
#include <WinAPIProc.au3>
#include <WinAPISys.au3>
#include <Array.au3>

; https://www.autoitscript.com/forum/topic/164271-detect-when-any-and-all-windows-have-moved/?do=findComment&comment=1198129
Global $hEventProc = DllCallbackRegister(_EventProc, "none", "ptr;dword;hwnd;long;long;dword;dword")
Global $hEventHook = _WinAPI_SetWinEventHook($EVENT_MIN, $EVENT_MAX, DllCallbackGetPtr($hEventProc))

OnAutoItExitRegister(OnAutoItExit) ; clear the hook on exit

Global $hMainWin = GUICreate('My main GUI', 400, 400, 50, 50)
GUISetState(@SW_SHOW)

$hGUI_Child0 = GUICreate('hand', 100, 100, 10, 0, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child0) ; a 2-element array containing Width and Height of window's client area (inner area excluding borders).
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG) ; this allow dragging of the "card" by click on "card" and drag.
GUICtrlCreateIcon("shell32.dll", 29, 0, 0, $aHostDim[0], $aHostDim[1]) ; put something to see on the card
GUISetState(@SW_SHOW, $hGUI_Child0)
_WinAPI_SetParent($hGUI_Child0, $hMainWin) ; trap this child gui within the main gui
;
$hGUI_Child1 = GUICreate('tree', 100, 100, 25, 15, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child1)
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlCreateIcon("shell32.dll", 42, 0, 0, $aHostDim[0], $aHostDim[1])
GUISetState(@SW_SHOW, $hGUI_Child1)
_WinAPI_SetParent($hGUI_Child1, $hMainWin)
;
$hGUI_Child2 = GUICreate('star', 100, 100, 40, 30, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlCreateIcon("shell32.dll", 44, 0, 0, $aHostDim[0], $aHostDim[1])
GUISetState(@SW_SHOW, $hGUI_Child2)
_WinAPI_SetParent($hGUI_Child2, $hMainWin)

$hGUI_Child3 = GUICreate('folder', 100, 100, 55, 45, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlCreateIcon("shell32.dll", 39, 0, 0, $aHostDim[0], $aHostDim[1])
GUISetState(@SW_SHOW, $hGUI_Child3)
_WinAPI_SetParent($hGUI_Child3, $hMainWin)

$hGUI_Child4 = GUICreate('key', 100, 100, 70, 60, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlCreateIcon("shell32.dll", 45, 0, 0, $aHostDim[0], $aHostDim[1])
GUISetState(@SW_SHOW, $hGUI_Child4)
_WinAPI_SetParent($hGUI_Child4, $hMainWin)


$hGUI_Child5 = GUICreate('locker', 100, 100, 85, 75, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlCreateIcon("shell32.dll", 48, 0, 0, $aHostDim[0], $aHostDim[1])
GUISetState(@SW_SHOW, $hGUI_Child5)
_WinAPI_SetParent($hGUI_Child5, $hMainWin)




MsgBox(0, "Pause", "Drag images on the Main GUI" & @CRLF & "Click OK to end")

Func _EventProc($hEventHook, $iEvent, $hWnd, $iObjectID, $iChildID, $iThreadId, $iEventTime)
    #forceref $hEventHook, $iObjectID, $iChildID, $iThreadId, $iEventTime
    ; Static $lastevent
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/dd318066(v=vs.85).aspx
    Local $aAllChildWindows = 0
    Local $aChildWindows = 0
    Local $sWindows = ""
    Switch $iEvent
        Case $EVENT_SYSTEM_MOVESIZESTART
            ; ConsoleWrite("Start:" & @TAB & $iEvent & @TAB & $hWnd & @TAB & $iObjectID & @TAB & $iChildID & @CRLF)

        Case $EVENT_SYSTEM_MOVESIZEEND ; to be used as drop
            If _WinAPI_GetAncestor($hWnd) = $hMainWin Then
                $aAllChildWindows = _WinAPI_EnumChildWindows($hMainWin)
                $aChildWindows = _GetJustChildWindow($aAllChildWindows, $hMainWin, $hWnd)
                If IsArray($aChildWindows) Then
                    $sWindows = _GetWindowBycollision($aChildWindows, $hWnd)
                    ConsoleWrite(WinGetTitle($hWnd) & " dropped on " & $sWindows & @CRLF)
                EndIf


            EndIf
        Case Else
            #cs If $iEvent <> $lastevent Then
                ConsoleWrite("event:" & @TAB & $iEvent & @CRLF)
                $lastevent = $iEvent
            #ce EndIf
    EndSwitch
EndFunc   ;==>_EventProc


Func _GetWindowBycollision($aWindow, $hWinMoving)
    Local $aWin1 = WinGetPos($hWinMoving)
    Local $aWin2 = 0
    Local $sWindows = ""
    For $i = 0 To UBound($aWindow) - 1
        $aWin2 = WinGetPos($aWindow[$i])
        If $aWin1[0] < $aWin2[0] + $aWin2[2] And $aWin1[0] + $aWin1[2] > $aWin2[0] And $aWin1[1] < $aWin2[1] + $aWin2[3] And $aWin1[3] + $aWin1[1] > $aWin2[1] Then
            $sWindows &= (($sWindows <> "") ? ", " : "") & WinGetTitle($aWindow[$i])
        EndIf
    Next
    If $sWindows = "" Then $sWindows = WinGetTitle($hMainWin)
    if StringInStr($sWindows,",",0,-1) Then
        $sWindows=StringReplace($sWindows,StringMid($sWindows,StringInStr($sWindows,",",0,-1))," and" & StringMid($sWindows,StringInStr($sWindows,",",0,-1)+1))
    EndIf

    Return $sWindows

EndFunc   ;==>_GetWindowBycollision


Func _GetJustChildWindow($aArray, $hParentWindow, $hWinToAvoid)
    Local $aNewArray[0]
    If IsArray($aArray) Then
        For $i = 1 To $aArray[0][0]
            If $aArray[$i][1] = _WinAPI_GetClassName($hParentWindow) And $hWinToAvoid <> $aArray[$i][0] Then
                ReDim $aNewArray[UBound($aNewArray) + 1]
                $aNewArray[UBound($aNewArray) - 1] = $aArray[$i][0]
                ConsoleWrite($i & $aNewArray[UBound($aNewArray) - 1] & @CRLF)
            EndIf
        Next
        Return $aNewArray
    EndIf
    Return 0

EndFunc   ;==>_GetJustChildWindow
Func OnAutoItExit()
    _WinAPI_UnhookWinEvent($hEventHook)
    DllCallbackFree($hEventProc)
EndFunc   ;==>OnAutoItExit

 

Saludos

Edited by Danyfirex
Edit
1 person likes this

Share this post


Link to post
Share on other sites

Hi, I'm back on this topic,
well, after done some testing, I have seen that to establish which card is below the one dropped, I have to define some criteria, as already pointed out in post #5 by @junkew, that is:
1) the target is the card below the dropped card pointed by the arrow pointer
2) the target is the first z-order card encountered by the dropping card
3) the target is the card that underlies and that has the major percentage of surface covered by the dropped card (regardless the z-order).
now:
point 1 can be essentially achieved as from post #3 by @kafu (thank you)
point 2 can be essentially achieved as from post #9 by @Danyfirex (thank you)
point 3 still not achieved... I have to think a good way to do it (suggestions are welcome)
I mainly used portion of code from post #3 and #9 (and also from other posts as well) to implement points 1 and 2, all has been concentrated in the GetBelow() function that I will try to enhance by adding feature of point 3.

Thanks a lot everybody again
here  the new draft:

#include <GUIConstants.au3>
#include <APISysConstants.au3>
#include <WinAPI.au3>
#include <WinAPISys.au3>

; https://www.autoitscript.com/forum/topic/164271-detect-when-any-and-all-windows-have-moved/?do=findComment&comment=1198129
Global $hEventProc = DllCallbackRegister(_EventProc, "none", "ptr;dword;hwnd;long;long;dword;dword")
Global $hEventHook = _WinAPI_SetWinEventHook($EVENT_MIN, $EVENT_MAX, DllCallbackGetPtr($hEventProc))
OnAutoItExitRegister(OnAutoItExit) ; clear the hook on exit
;
Global $hMainWin = GUICreate('My main GUI', 400, 400, 50, 50)
GUISetState(@SW_SHOW)
;
$hGUI_Child0 = GUICreate('hand', 100, 100, 10, 0, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child0) ; a 2-element array containing Width and Height of window's client area (inner area excluding borders).
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG) ; this allow dragging of the "card" by click on "card" and drag.
GUICtrlCreateIcon("shell32.dll", 29, 0, 0, $aHostDim[0], $aHostDim[1]) ; put something to see on the card
GUISetState(@SW_SHOW, $hGUI_Child0)
_WinAPI_SetParent($hGUI_Child0, $hMainWin) ; trap this child gui within the main gui
;
$hGUI_Child1 = GUICreate('tree', 100, 100, 25, 15, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child1)
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlCreateIcon("shell32.dll", 42, 0, 0, $aHostDim[0], $aHostDim[1])
GUISetState(@SW_SHOW, $hGUI_Child1)
_WinAPI_SetParent($hGUI_Child1, $hMainWin)
;
$hGUI_Child2 = GUICreate('star', 100, 100, 40, 30, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child2)
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlCreateIcon("shell32.dll", 44, 0, 0, $aHostDim[0], $aHostDim[1])
GUISetState(@SW_SHOW, $hGUI_Child2)
_WinAPI_SetParent($hGUI_Child2, $hMainWin)

$hGUI_Child3 = GUICreate('folder', 100, 100, 55, 45, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child3)
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlCreateIcon("shell32.dll", 39, 0, 0, $aHostDim[0], $aHostDim[1])
GUISetState(@SW_SHOW, $hGUI_Child3)
_WinAPI_SetParent($hGUI_Child3, $hMainWin)
;
$hGUI_Child4 = GUICreate('key', 100, 100, 70, 60, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child4)
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlCreateIcon("shell32.dll", 45, 0, 0, $aHostDim[0], $aHostDim[1])
GUISetState(@SW_SHOW, $hGUI_Child4)
_WinAPI_SetParent($hGUI_Child4, $hMainWin)
;
$hGUI_Child5 = GUICreate('locker', 100, 100, 85, 75, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child5)
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlCreateIcon("shell32.dll", 48, 0, 0, $aHostDim[0], $aHostDim[1])
GUISetState(@SW_SHOW, $hGUI_Child5)
_WinAPI_SetParent($hGUI_Child5, $hMainWin)
;
Local $hStaticDropArea = GUICreate("static drop area", 380, 90, 10, 290, 0x40000000, $WS_EX_CLIENTEDGE, $hMainWin) ; 0x40000000 -> $WS_CHILD
Local $Dummy = GUISetBkColor(0xFF7733, $hStaticDropArea) + GUICtrlCreateLabel("static drop area", 5, 50, 230) + GUICtrlSetFont(-1, 12, "", "", "Courier New") + GUISetState(@SW_SHOW, $hStaticDropArea)
;
; --- console window ---
Local $hConsoleGUI = GUICreate('Console', 400, 200, 50, 490, $WS_CAPTION)
GUISetBkColor(0x000000, $hConsoleGUI)
Local $hConsole = GUICtrlCreateLabel("", 5, 5, 390, 290)
$Dummy = GUICtrlSetFont(-1, 9, 0, 0, "Courier New") + GUICtrlSetBkColor(-1, 0x000000) + GUICtrlSetColor(-1, 0x00ff00) + GUISetState(@SW_SHOW)
; ----------------------

MsgBox(0, "Pause", "Drag images on the Main GUI" & @CRLF & "Click OK to end")

Func _EventProc($hEventHook, $iEvent, $hWnd, $iObjectID, $iChildID, $iThreadId, $iEventTime)
    ; https://msdn.microsoft.com/en-us/library/dd373885(v=vs.85).aspx
    #forceref $hEventHook, $iObjectID, $iChildID, $iThreadId, $iEventTime
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/dd318066(v=vs.85).aspx
    Switch $iEvent
        Case $EVENT_SYSTEM_MOVESIZESTART

        Case $EVENT_SYSTEM_MOVESIZEEND ; to be used as drop
            If $hMainWin = _WinAPI_GetAncestor($hWnd, $GA_PARENT) Then ; $GA_PARENT = 1
                $aResults = GetBelow($hWnd) ; returns 3 element array with handles of: [0]Dragged card, [1] card below pointer, [2] first z-order card below the dragged card
                If Not $aResults[1] Then ; [1] -> below pointer
                    ConsolePrint("by Arrow: " & WinGetTitle($aResults[0]) & " dropped on empty area" & @CRLF, $hConsole)
                Else
                    ConsolePrint("by Arrow: " & WinGetTitle($aResults[0]) & " dropped on " & WinGetTitle($aResults[1]) & @CRLF, $hConsole)
                EndIf
                ;
                If Not $aResults[2] Then ; [2] -> layer below
                    ConsolePrint("by Layer: " & WinGetTitle($aResults[0]) & " dropped on empty area" & @CRLF, $hConsole)
                Else
                    ConsolePrint("by Layer: " & WinGetTitle($aResults[0]) & " dropped on " & WinGetTitle($aResults[2]) & @CRLF, $hConsole)
                EndIf
            EndIf
            ;
            If $hWnd = $hMainWin Then ; if main window was moved then snap console to main win
                Local $aMainWin = WinGetPos($hMainWin)
                WinMove($hConsoleGUI, "", $aMainWin[0], $aMainWin[1] + $aMainWin[3] + 11)
            EndIf
        Case Else
            #cs If $iEvent <> $lastevent Then
                ConsoleWrite("event:" & @TAB & $iEvent & @CRLF)
                $lastevent = $iEvent
            #ce EndIf
    EndSwitch
EndFunc   ;==>_EventProc

Func GetBelow(ByRef $hDropped)
    Local $hFoundByArrow = 0, $hFoundByLayer = 0
    Local $hPullChild = _WinAPI_GetWindow($hMainWin, $GW_CHILD) ; get the first child from the child's stack (the one being dragged)
    Local $aWin1 = WinGetPos($hPullChild) ;  <-- Retrieves the position and size of the dropped "card"
    Do ; scan all the child windows (child "cards")
        $hPullChild = _WinAPI_GetWindow($hPullChild, $GW_HWNDnext) ; pull next child from the z-order stack (returns 0 if no more cards)
        If $hPullChild Then ; if there are still cards in the stack to be checked
            $aPos = WinGetPos($hPullChild) ; position and size of "card" being checked
            $aMxy = MouseGetPos() ; Mouse x and y positions
            If Not $hFoundByArrow Then ; if not already found the "card" pointed by mouse pointer
                If $aMxy[0] >= $aPos[0] And $aMxy[0] <= $aPos[0] + $aPos[2] And $aMxy[1] >= $aPos[1] And $aMxy[1] <= $aPos[1] + $aPos[3] Then $hFoundByArrow = $hPullChild
            EndIf
            ;
            If Not $hFoundByLayer Then; if not already found the "card" layered below the dropped
                If $aWin1[0] < $aPos[0] + $aPos[2] And $aWin1[0] + $aWin1[2] > $aPos[0] And $aWin1[1] < $aPos[1] + $aPos[3] And $aWin1[3] + $aWin1[1] > $aPos[1] Then $hFoundByLayer = $hPullChild
            EndIf
        EndIf
    Until Not $hPullChild Or ($hFoundByArrow And $hFoundByLayer)
    Local $aResults[3] = [$hDropped, $hFoundByArrow, $hFoundByLayer]
    Return $aResults
EndFunc   ;==>GetBelow

Func ConsolePrint($sMSG, ByRef $hConsole)
    If StringInStr(GUICtrlRead($hConsole) & $sMSG, @LF, 0, -12) Then
        GUICtrlSetData($hConsole, StringRight(GUICtrlRead($hConsole) & $sMSG, StringLen(GUICtrlRead($hConsole) & $sMSG) - StringInStr(GUICtrlRead($hConsole), @LF, 0, -12)))
    Else
        GUICtrlSetData($hConsole, GUICtrlRead($hConsole) & $sMSG)
    EndIf
EndFunc   ;==>ConsolePrint

Func OnAutoItExit()
    _WinAPI_UnhookWinEvent($hEventHook)
    DllCallbackFree($hEventProc)
EndFunc   ;==>OnAutoItExit

 


small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

For 3), how about using "IntersectRect" to calculated a cover percentage in something like this?

Currently Array is sorted by Z-Order (Col 0), cover percentage is in Col 8, resort array on that column to receive hwnds with max. cover percentage.

#include <Array.au3>
#include <Misc.au3>

Global $h_Ref_GUI = GUICreate("Ref-Gui")
GUISetState()

HotKeySet("{ESC}", "_Exit")

Local $aMousePos, $_a_hWnd_OnPos

While 1
    Sleep(10)
    If _IsPressed("7B") Then ; F12
        $aMousePos = MouseGetPos()
        $_a_hWnd_OnPos = _hWnd_AtPos($aMousePos[0], $aMousePos[1], $h_Ref_GUI)
        _ArrayDisplay($_a_hWnd_OnPos)
    EndIf
WEnd

Func _hWnd_AtPos($x, $y, $hWnd_to_Test)

    Local $aWinlist = WinList()
    Local $aWinlist_Final[100][9], $iEnum = 1, $aPos

    For $i = 1 To $aWinlist[0][0]
        If BitAND(WinGetState($aWinlist[$i][1]), 2) Then ; is visible
            $aWinlist_Final[$iEnum][0] = $iEnum ; Z-Order
            $aWinlist_Final[$iEnum][1] = $aWinlist[$i][0]
            $aWinlist_Final[$iEnum][2] = $aWinlist[$i][1]
            $aPos = WinGetPos($aWinlist[$i][1])
            $aWinlist_Final[$iEnum][3] = $aPos[0] ; x
            $aWinlist_Final[$iEnum][4] = $aPos[1] ; y
            $aWinlist_Final[$iEnum][5] = $aPos[2] ; w
            $aWinlist_Final[$iEnum][6] = $aPos[3] ; h
            $iEnum += 1
            If Not Mod($iEnum, 100) Then ReDim $aWinlist_Final[UBound($aWinlist_Final) + 100][9]
        EndIf
    Next

    ReDim $aWinlist_Final[$iEnum - 1][9]
    $aWinlist_Final[0][0] = $iEnum - 2 ; No. of Win found

    For $i = 1 To $iEnum - 1
        If $x >= $aWinlist_Final[$i][3] And $x <= ($aWinlist_Final[$i][3] + $aWinlist_Final[$i][5]) And _
                $y >= $aWinlist_Final[$i][4] And $y <= ($aWinlist_Final[$i][4] + $aWinlist_Final[$i][6]) Then
            $aWinlist_Final[0][1] = $aWinlist_Final[$i][2] ; Window under x,y
            $aWinlist_Final[0][2] = WinGetTitle($aWinlist_Final[$i][2])
            ExitLoop
        EndIf
    Next

    Local $t_RECT_Intersection = DllStructCreate("struct; long Left;long Top;long Right;long Bottom; endstruct")
    Local $t_RECT_Var = DllStructCreate("struct; long Left;long Top;long Right;long Bottom; endstruct")

    Local $t_RECT_Test = DllStructCreate("struct; long Left;long Top;long Right;long Bottom; endstruct")
    Local $a_Pos_hWnd_to_Test = WinGetPos($hWnd_to_Test)
    DllStructSetData($t_RECT_Test, 1, $a_Pos_hWnd_to_Test[0])
    DllStructSetData($t_RECT_Test, 2, $a_Pos_hWnd_to_Test[1])
    DllStructSetData($t_RECT_Test, 3, $a_Pos_hWnd_to_Test[0] + $a_Pos_hWnd_to_Test[2])
    DllStructSetData($t_RECT_Test, 4, $a_Pos_hWnd_to_Test[1] + $a_Pos_hWnd_to_Test[3])

    Local $i_Res, $i_Pixel_hWnd_to_Test = $a_Pos_hWnd_to_Test[2] * $a_Pos_hWnd_to_Test[3]

    For $i = 1 To $aWinlist_Final[0][0]

        DllStructSetData($t_RECT_Var, 1, $aWinlist_Final[$i][3])
        DllStructSetData($t_RECT_Var, 2, $aWinlist_Final[$i][4])
        DllStructSetData($t_RECT_Var, 3, $aWinlist_Final[$i][3] + $aWinlist_Final[$i][5])
        DllStructSetData($t_RECT_Var, 4, $aWinlist_Final[$i][4] + $aWinlist_Final[$i][6])

        $iRes = DllCall("user32.dll", "bool", "IntersectRect", "ptr", DllStructGetPtr($t_RECT_Intersection), "ptr", DllStructGetPtr($t_RECT_Var), "ptr", DllStructGetPtr($t_RECT_Test))

        If $iRes[0] Then
            ; Intersection
            $aWinlist_Final[$i][7] = (DllStructGetData($t_RECT_Intersection, 3) - DllStructGetData($t_RECT_Intersection, 1)) * (DllStructGetData($t_RECT_Intersection, 4) - DllStructGetData($t_RECT_Intersection, 2))

            ; Percentage of hWnd_to_Test intersecting with hWnd
            $aWinlist_Final[$i][8] = Round($aWinlist_Final[$i][7] / $i_Pixel_hWnd_to_Test, 2)
        EndIf

    Next

    Return $aWinlist_Final

EndFunc   ;==>_hWnd_AtPos

Func _Exit()
    Exit
EndFunc   ;==>_Exit

 

Share this post


Link to post
Share on other sites

Thanks @Kafu

I will make some tests on your code.
...see you later...


small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

hi KaFu, thanks again for your suggestion.
I've included your dll* stuff into my template so to be able to show what I noticed about results. (I was also on a similar way more geometric coded than relied on dll, anyway I'm testing your way now). I've also changed the dimensions of the windows (the cards) so to better view what I mean (at least I hope so)

the % of overlap related to only 2 windows is ok, but if for example 3 (or more) windows are stacked, the routine returns the % of overlap for each window not considering how they hide each other. For example, if you move the "lock" card on an empty area and then you cover it only partially with the "key" card, the "lock" will be visible now only partially, so, if now I move the "tree" card above both cards (the lock and the key), I would get the overlap percentage for the lock for only the "visible" part and not for the whole surface (that is the part visible and the part hidden).

#include <GUIConstants.au3>
#include <APISysConstants.au3>
#include <WinAPI.au3>
#include <WinAPISys.au3>
#include <Math.au3>

; https://www.autoitscript.com/forum/topic/164271-detect-when-any-and-all-windows-have-moved/?do=findComment&comment=1198129
Global $hEventProc = DllCallbackRegister(_EventProc, "none", "ptr;dword;hwnd;long;long;dword;dword")
Global $hEventHook = _WinAPI_SetWinEventHook($EVENT_MIN, $EVENT_MAX, DllCallbackGetPtr($hEventProc))
OnAutoItExitRegister(OnAutoItExit) ; clear the hook on exit
;
Global $hMainWin = GUICreate('My main GUI', 400, 400, 50, 50)
GUISetState(@SW_SHOW)
;
$hGUI_Child0 = GUICreate('hand', 110, 110, 10, 0, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child0) ; a 2-element array containing Width and Height of window's client area (inner area excluding borders).
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG) ; this allow dragging of the "card" by click on "card" and drag.
GUICtrlCreateIcon("shell32.dll", 29, 0, 0, $aHostDim[0], $aHostDim[1]) ; put something to see on the card
GUISetState(@SW_SHOW, $hGUI_Child0)
_WinAPI_SetParent($hGUI_Child0, $hMainWin) ; trap this child gui within the main gui
;
$hGUI_Child1 = GUICreate('tree', 100, 150, 25, 15, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child1)
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlCreateIcon("shell32.dll", 42, 0, 0, $aHostDim[0], $aHostDim[1])
GUISetState(@SW_SHOW, $hGUI_Child1)
_WinAPI_SetParent($hGUI_Child1, $hMainWin)
;
$hGUI_Child2 = GUICreate('star', 100, 100, 40, 30, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child2)
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlCreateIcon("shell32.dll", 44, 0, 0, $aHostDim[0], $aHostDim[1])
GUISetState(@SW_SHOW, $hGUI_Child2)
_WinAPI_SetParent($hGUI_Child2, $hMainWin)

$hGUI_Child3 = GUICreate('folder', 100, 100, 55, 45, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child3)
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlCreateIcon("shell32.dll", 39, 0, 0, $aHostDim[0], $aHostDim[1])
GUISetState(@SW_SHOW, $hGUI_Child3)
_WinAPI_SetParent($hGUI_Child3, $hMainWin)
;
$hGUI_Child4 = GUICreate('key', 100, 100, 70, 60, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child4)
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlCreateIcon("shell32.dll", 45, 0, 0, $aHostDim[0], $aHostDim[1])
GUISetState(@SW_SHOW, $hGUI_Child4)
_WinAPI_SetParent($hGUI_Child4, $hMainWin)
;
$hGUI_Child5 = GUICreate('locker', 50, 50, 85, 75, $WS_POPUPWINDOW, BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE))
$aHostDim = WinGetClientSize($hGUI_Child5)
GUICtrlCreatePic("", 0, 0, $aHostDim[0], $aHostDim[1], -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlCreateIcon("shell32.dll", 48, 0, 0, $aHostDim[0], $aHostDim[1])
GUISetState(@SW_SHOW, $hGUI_Child5)
_WinAPI_SetParent($hGUI_Child5, $hMainWin)
;
Local $hStaticDropArea = GUICreate("static drop area", 380, 130, 10, 250, 0x40000000, $WS_EX_CLIENTEDGE, $hMainWin) ; 0x40000000 -> $WS_CHILD
Local $Dummy = GUISetBkColor(0xFF7733, $hStaticDropArea) + GUICtrlCreateLabel("static drop area", 5, 50, 230) + GUICtrlSetFont(-1, 12, "", "", "Courier New") + GUISetState(@SW_SHOW, $hStaticDropArea)
;
; --- console window ---
Local $hConsoleGUI = GUICreate('Console', 400, 200, 50, 490, $WS_CAPTION)
GUISetBkColor(0x000000, $hConsoleGUI)
Local $hConsole = GUICtrlCreateLabel("", 5, 5, 390, 290)
$Dummy = GUICtrlSetFont(-1, 9, 0, 0, "Courier New") + GUICtrlSetBkColor(-1, 0x000000) + GUICtrlSetColor(-1, 0x00ff00) + GUISetState(@SW_SHOW)
; ----------------------

MsgBox(0, "Pause", "Drag images on the Main GUI" & @CRLF & "Click OK to end")

Func _EventProc($hEventHook, $iEvent, $hWnd, $iObjectID, $iChildID, $iThreadId, $iEventTime)
    ; https://msdn.microsoft.com/en-us/library/dd373885(v=vs.85).aspx
    #forceref $hEventHook, $iObjectID, $iChildID, $iThreadId, $iEventTime
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/dd318066(v=vs.85).aspx
    Switch $iEvent
        Case $EVENT_SYSTEM_MOVESIZESTART

        Case $EVENT_SYSTEM_MOVESIZEEND ; to be used as drop
            If $hMainWin = _WinAPI_GetAncestor($hWnd, $GA_PARENT) Then ; $GA_PARENT = 1
                $aResults = GetBelow($hWnd) ; returns 3 element array with handles of: [0]Dragged card, [1] card below pointer, [2] first z-order card below the dragged card
                #cs
                If Not $aResults[1] Then ; [1] -> below pointer
                    ConsolePrint("by Arrow: " & WinGetTitle($aResults[0]) & " dropped on empty area" & @CRLF, $hConsole)
                Else
                    ConsolePrint("by Arrow: " & WinGetTitle($aResults[0]) & " dropped on " & WinGetTitle($aResults[1]) & @CRLF, $hConsole)
                EndIf
                ;
                If Not $aResults[2] Then ; [2] -> layer below
                    ConsolePrint("by Layer: " & WinGetTitle($aResults[0]) & " dropped on empty area" & @CRLF, $hConsole)
                Else
                    ConsolePrint("by Layer: " & WinGetTitle($aResults[0]) & " dropped on " & WinGetTitle($aResults[2]) & @CRLF, $hConsole)
                EndIf
                #ce
            EndIf
            ;
            If $hWnd = $hMainWin Then ; if main window was moved then snap console to main win
                Local $aMainWin = WinGetPos($hMainWin)
                WinMove($hConsoleGUI, "", $aMainWin[0], $aMainWin[1] + $aMainWin[3] + 11)
            EndIf
        Case Else
            #cs If $iEvent <> $lastevent Then
                ConsoleWrite("event:" & @TAB & $iEvent & @CRLF)
                $lastevent = $iEvent
            #ce EndIf
    EndSwitch
EndFunc   ;==>_EventProc

Func GetBelow(ByRef $hDropped)
    Local $hFoundByArrow = 0, $hFoundByLayer = 0
    Local $hPullChild = _WinAPI_GetWindow($hMainWin, $GW_CHILD) ; get the first child from the child's stack (the one being dragged)
    Local $hDragged = $hPullChild
    Local $aWin1 = WinGetPos($hPullChild) ;  <-- Retrieves the position and size of the dropped "card"
    $aWin1[2] += $aWin1[0]
    $aWin1[3] += $aWin1[1]
    ;
    Local $t_RECT_Intersection = DllStructCreate("struct; long Left;long Top;long Right;long Bottom; endstruct")
    Local $t_RECT_Var = DllStructCreate("struct; long Left;long Top;long Right;long Bottom; endstruct")
    Local $t_RECT_Test = DllStructCreate("struct; long Left;long Top;long Right;long Bottom; endstruct") ; dragged window
    ;
    ; Local $a_Pos_hWnd_to_Test = WinGetPos($hWnd_to_Test) ; the dropped window (see $aWin1 above)
    DllStructSetData($t_RECT_Test, 1, $aWin1[0]) ; x1 upper left
    DllStructSetData($t_RECT_Test, 2, $aWin1[1]) ; y1 upper left
    DllStructSetData($t_RECT_Test, 3, $aWin1[2]) ; x2 lower right
    DllStructSetData($t_RECT_Test, 4, $aWin1[3]) ; y2 lower right

    Do ; scan all the child windows (child "cards")
        $hPullChild = _WinAPI_GetWindow($hPullChild, $GW_HWNDnext) ; pull next child from the z-order stack (returns 0 if no more cards)
        If $hPullChild Then ; if there are still cards in the stack to be checked
            $aPos = WinGetPos($hPullChild) ; position and size of "card" being checked
            Local $iAreaOfWinBelow = $aPos[2] * $aPos[3] ; area of the below window
            $aPos[2] += $aPos[0]
            $aPos[3] += $aPos[1]
            $aMxy = MouseGetPos() ; Mouse x and y positions
            If Not $hFoundByArrow Then ; if not already found the "card" pointed by mouse pointer
                If $aMxy[0] >= $aPos[0] And $aMxy[0] <= $aPos[2] And $aMxy[1] >= $aPos[1] And $aMxy[1] <= $aPos[3] Then $hFoundByArrow = $hPullChild
            EndIf
            ;
            If $aWin1[0] < $aPos[2] And $aWin1[2] > $aPos[0] And $aWin1[1] < $aPos[3] And $aWin1[3] > $aPos[1] Then ; overlaps
                If Not $hFoundByLayer Then; if not already found the "card" layered below the dropped
                    $hFoundByLayer = $hPullChild
                EndIf
                ;
                #cs
                    $iOverlap = _Max(0, _Min($aWin1[2], $aPos[2]) - _Max($aWin1[0], $aPos[0])) * _Max(0, _Min($aWin1[3], $aPos[3]) - _Max($aWin1[1], $aPos[1]))
                    $iUnion = (($aWin1[2] - $aWin1[0]) * ($aWin1[3] - $aWin1[1])) + (($aPos[2] - $aPos[0]) * ($aPos[3] - $aPos[1])) - $iOverlap
                    $iRatio = $iOverlap / $iUnion
                    ; $iPercent = Round($iOverlap * 100 / (($aWin1[2] - $aWin1[0]) * ($aWin1[3] - $aWin1[1])))
                    $iPercent = Round($iOverlap * 100 / (($aPos[2] - $aPos[0]) * ($aPos[3] - $aPos[1])))
                    ConsolePrint(WinGetTitle($hDragged) & " overlaps " & WinGetTitle($hPullChild) & " for the " & $iPercent & "%" & @CRLF, $hConsole)
                #ce
                Local $iRes, $iUnion, $iPercent1, $iPercent1
                Local $i_Pixel_hWnd_to_Test = (($aWin1[2] - $aWin1[0]) * ($aWin1[3] - $aWin1[1])) ; full area of dragged window

                DllStructSetData($t_RECT_Var, 1, $aPos[0])
                DllStructSetData($t_RECT_Var, 2, $aPos[1])
                DllStructSetData($t_RECT_Var, 3, $aPos[2])
                DllStructSetData($t_RECT_Var, 4, $aPos[3])
                $iRes = DllCall("user32.dll", "bool", "IntersectRect", "ptr", DllStructGetPtr($t_RECT_Intersection), "ptr", DllStructGetPtr($t_RECT_Var), "ptr", DllStructGetPtr($t_RECT_Test))
                If $iRes[0] Then ; the 2 windows overlaps
                    ; Intersection (area of the overlapping portion)
                    $iUnion = (DllStructGetData($t_RECT_Intersection, 3) - DllStructGetData($t_RECT_Intersection, 1)) * (DllStructGetData($t_RECT_Intersection, 4) - DllStructGetData($t_RECT_Intersection, 2))
                    ; Percentage of hWnd_to_Test intersecting with hWnd
                    $iPercent1 = Round($iUnion / $i_Pixel_hWnd_to_Test, 2)
                    $iPercent2 = Round($iUnion / $iAreaOfWinBelow, 2)
                    ConsolePrint(WinGetTitle($hDragged) & " overlaps " & WinGetTitle($hPullChild) & " for the " & $iPercent1 * 100 & "%" & @CRLF, $hConsole)
                    ConsolePrint(WinGetTitle($hPullChild) & " is covered by " & WinGetTitle($hDragged) & " for the " & $iPercent2 * 100 & "%" & @CRLF & @CRLF, $hConsole)
                EndIf
            EndIf
        EndIf
    Until Not $hPullChild ; Or ($hFoundByArrow And $hFoundByLayer)
    Local $aResults[3] = [$hDropped, $hFoundByArrow, $hFoundByLayer]
    Return $aResults
EndFunc   ;==>GetBelow

Func ConsolePrint($sMSG, ByRef $hConsole)
    If StringInStr(GUICtrlRead($hConsole) & $sMSG, @LF, 0, -12) Then
        GUICtrlSetData($hConsole, StringRight(GUICtrlRead($hConsole) & $sMSG, StringLen(GUICtrlRead($hConsole) & $sMSG) - StringInStr(GUICtrlRead($hConsole), @LF, 0, -12)))
    Else
        GUICtrlSetData($hConsole, GUICtrlRead($hConsole) & $sMSG)
    EndIf
EndFunc   ;==>ConsolePrint

Func OnAutoItExit()
    _WinAPI_UnhookWinEvent($hEventHook)
    DllCallbackFree($hEventProc)
EndFunc   ;==>OnAutoItExit

 


small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

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