﻿
#include <WinAPIProc.au3>
#include <WinAPISys.au3>


#cs
#include <Array.au3>

$aTest = _GetSelectionFromTopMostExplorer()
_ArrayDisplay($aTest)

$aTest = _GetSelectionFromTopMostExplorer(False)
_ArrayDisplay($aTest)
#ce


; #FUNCTION# ====================================================================================================================
; Name ..........: _GetSelectionFromTopMostExplorer
; Description ...: Gets an array with selected files from the top most explorer window
; Syntax ........: _GetSelectionFromTopMostExplorer([$_bDir = True])
; Parameters ....: $_bDir	- [optional] Returns the full path (Default 'True'). With 'False' will only the filename returned.
; Return values .: Array with selected files. Counter at $ar[0]
; Requires.......: _GetTopmostHwndFromProcess()
; Author ........: BugFix
; ===============================================================================================================================
Func _GetSelectionFromTopMostExplorer($_bDir=True)
    Local $oShell = ObjCreate("Shell.Application")
	Local $oIE, $sPath = '', $oShellWindows = $oShell.Windows
	Local $oDoc, $bIE = False, $oFV
    For $i = 0 To $oShellWindows.Count -1  ; all opened explorer and internet explorer windows
        $oIE = $oShellWindows($i)
		$oDoc = $oIE.Document
		If _GetTopmostHwndFromProcess('explorer.exe', 'CabinetWClass') = $oIE.Hwnd Then
			If StringRegExp(ObjName($oDoc), "IShellFolderViewDual.") Then       ; be sure it's the explorer object
				$sPath = StringReplace(StringReplace(StringTrimLeft($oIE.LocationURL, 8), '%20', ' '), '/', '\') ; extract windows path from file-url
				$sPath = StringRegExpReplace($sPath, '(\\)$', '')  ; "C:\" --> "C:"
				$bIE = True   ; flag: found explorer
			EndIf
        EndIf
    Next
	Local $aSelection[500] = [0]
    If $bIE Then
        $oFV = $oIE.Document             ; File-Browser (ShellFolderView)
		If Not $_bDir Then $sPath = ''
        For $oFI In $oFV.SelectedItems   ; selected elements there
			$aSelection[0] += 1
			If $aSelection[0] > UBound($aSelection) Then ReDim $aSelection[UBound($aSelection) +500]
			$aSelection[$aSelection[0]] = StringFormat('%s%s%s',  $sPath, ($_bDir ? '\' : ''), $oFI.Name)
        Next
    EndIf
	If $aSelection[0] = 0 Then
		ReDim $aSelection[1]
	Else
		ReDim $aSelection[$aSelection[0]+1]
	EndIf
	Return $aSelection
EndFunc  ;==>_GetSelectionFromTopMostExplorer



; #FUNCTION# ====================================================================================================================
; Name ..........: _GetTopmostHwndFromProcess
; Description ...: Returns the handle of the top most window of a specific process
; Syntax ........: _GetTopmostHwndFromProcess($_vProcess)
; Parameters ....: $_vProcess           The Process name or PID
;                  $_sClass             The classname of windows that will created by the specific process
; Return values .: Success              The handle of the top most window
;                  Failure              0, set @error = 1 (process does not exists)
;                                              @error = 2 (there is no window for this)
; Author ........: BugFix
; ===============================================================================================================================
Func _GetTopmostHwndFromProcess($_vProcess, $_sClass)
	Local $aProc[2][2] = [[1],['',$_vProcess]]
	If IsString($_vProcess) Then
		$aProc = ProcessList($_vProcess)
		If $aProc[0][0] = 0 Then
			Return SetError(1,0,0)
		EndIf
	Else
		If Not ProcessExists($_vProcess) Then Return SetError(1,0,0)
	EndIf
	; get the highest z-order
	Local $hWnd = 0, $aWin = _WinAPI_EnumDesktopWindows(_WinAPI_GetThreadDesktop(_WinAPI_GetCurrentThreadId()), False)
	For $i = 1 To $aWin[0][0]
		If $aWin[$i][1] = $_sClass Then ; first found window of this class has the highest z-order
			$hWnd = $aWin[$i][0]
			ExitLoop
		EndIf
	Next
	If $hWnd = 0 Then Return SetError(2,0,0)
    Local $tPID = DllStructCreate("int PID")
	For $i = 1 To $aProc[0][0]
		DllCall("user32.dll", "int", "GetWindowThreadProcessId", "hwnd", $hWnd, "ptr", DllStructGetPtr($tPID))
		If $tPID.PID = $aProc[$i][1] Then Return $hWnd
	Next
    Return 0
EndFunc  ;==>_GetTopmostHwndFromProcess
