Что нового

Как получить событие перетаскивания файла над GUI

musicstashall

Знающий
Сообщения
322
Репутация
7
Доброго.
Требуется получить событие, когда файл из проводника перетаскивается в окно GUI, но еще не брошен в это окно. Получить также и массив перетаскиваемых файлов, подобно функции WM_DROPFILES и _WinAPI_DragQueryFileEx($wParam). Возможно ли это?
 
Сообщения
142
Репутация
-3
Ты используешь поле, которое принимает перескиваемый файл? Из нее не получилось выцепить? Покажи код.
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Я использую такую схему
Код:
#include <WindowsConstants.au3>
; Global Const $WM_DROPFILES = 0x0233 ; в AutoIt3 v3.3.6.1 эта константа не определена
Global $k = 0
Global Const $hUSER32 = DllOpen("user32.dll")
Global Const $hSHELL32 = DllOpen("shell32.dll")

$sDescription = 'Функция WM_DROPFILES выполняется при перетаскивании объектов на элементы окна' & @CRLF & _
        'В отличии от нативного механизма функция не вставляет принудительно путь в элемент Edit'

$hGui = GUICreate('WM_DROPFILES', 600, 360, -1, -1, -1, $WS_EX_ACCEPTFILES)
$iEdit = GUICtrlCreateEdit($sDescription, 5, 5, 590, 300)
GUISetState()
GUIRegisterMsg($WM_DROPFILES, "WM_DROPFILES")

Do
Until GUIGetMsg() = -3

Func WM_DROPFILES($hwnd, $msg, $wParam, $lParam)
    ; Local $tPoint = DllStructCreate('int X;int Y')
    ; DllCall("shell32.dll", "int", "DragQueryPoint", "int", $wParam, "ptr", DllStructGetPtr($tPoint))
    ; $iX = DllStructGetData($tPoint, "X")
    ; $iY = DllStructGetData($tPoint, "Y")
    $k += 1
    WinSetTitle($hGui, '', 'Вызов ' & $k)
    Local $aCursorInfo = GUIGetCursorInfo($hGui) ; определяет элемент под курсором в момент бросания
    If Not @error And $aCursorInfo[4] = $iEdit Then
        Local $aCall, $sDroppedFiles
        ; возвращает количество файлов и папок
        $aCall = DllCall($hSHELL32, "dword", "DragQueryFileW", "handle", $wParam, "dword", -1, "wstr", "", "dword", 0)
        If @error Or Not $aCall[0] Then Return SetError(1, 0, "")
        For $i = 0 To $aCall[0] - 1 ; цикл запрашивает все файлы и папки
            $aCall = DllCall($hSHELL32, "dword", "DragQueryFileW", "handle", $wParam, "dword", $i, "wstr", "", "dword", 32767)
            If @error Or Not $aCall[0] Then ; Если ошибка или каталог
                ExitLoop
            Else
                $sDroppedFiles &= $aCall[3] & @CRLF ; имя файла или папки присоединяется к результату
            EndIf
        Next
        DllCall($hSHELL32, "none", "DragFinish", "handle", $wParam)
        GUICtrlSetData($iEdit, StringTrimRight($sDroppedFiles, 2)) ; Вставлять пути не обязательно, важно событие. Если требуется длительная обработка, то сюда не вставлять
        ; WinActivate($hGUI) ; активирует окно, в которое брошены файлы
        Return 1
    EndIf
    Return 1
EndFunc   ;==>WM_DROPFILES
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
В следующем варианте тоже ничего не прилетает
Код:
#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <WinAPISys.au3>
#include <WindowsConstants.au3>

OnAutoItExitRegister('OnAutoItExit')

; Create GUI
Local $hForm = GUICreate('Test ' & StringReplace(@ScriptName, '.au3', '()'), 400, 400)
Local $idCheck = GUICtrlCreateCheckbox('Enable Drag && Drop', 10, 370, 120, 19)
Local $idLabel = GUICtrlCreateLabel('', 100, 100, 200, 200)
Global $g_hLabel = GUICtrlGetHandle($idLabel)
GUICtrlSetBkColor(-1, 0xD3D8EF)
GUICtrlCreateLabel('Drop here', 175, 193, 50, 14)
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)

; Allow WM_DROPFILES to be received from lower privileged processes (Windows Vista or later)
#cs
If IsAdmin() Then
    _WinAPI_ChangeWindowMessageFilterEx($g_hLabel, $WM_COPYGLOBALDATA, $MSGFLT_ALLOW)
    _WinAPI_ChangeWindowMessageFilterEx($g_hLabel, $WM_DROPFILES, $MSGFLT_ALLOW)
EndIf
#ce

; Register label window proc
Global $g_hDll = DllCallbackRegister('_WinProc', 'ptr', 'hwnd;uint;wparam;lparam')
Global $g_pDll = DllCallbackGetPtr($g_hDll)
Global $g_hProc = _WinAPI_SetWindowLong($g_hLabel, $GWL_WNDPROC, $g_pDll)

GUISetState(@SW_SHOW)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
        Case $idCheck
            _WinAPI_DragAcceptFiles($g_hLabel, GUICtrlRead($idCheck) = $GUI_CHECKED)
    EndSwitch
WEnd

Func _WinProc($hWnd, $iMsg, $wParam, $lParam)
    Switch $iMsg
        Case $WM_DROPFILES
            Local $aFileList = _WinAPI_DragQueryFileEx($wParam)
            If Not @error Then
                ConsoleWrite('--------------------------------------------------' & @CRLF)
                For $i = 1 To $aFileList[0]
                    ConsoleWrite($aFileList[$i] & @CRLF)
                Next
            EndIf
            _WinAPI_DragFinish($wParam)
            Return 0
        Case Else
            ConsoleWrite('CODE 0x' & Hex($iMsg,4) & @CR)
    EndSwitch
    Return _WinAPI_CallWindowProc($g_hProc, $hWnd, $iMsg, $wParam, $lParam)
EndFunc   ;==>_WinProc

Func OnAutoItExit()
    _WinAPI_SetWindowLong($g_hLabel, $GWL_WNDPROC, $g_hProc)
    DllCallbackFree($g_hDll)
EndFunc   ;==>OnAutoItExit
 
Сообщения
142
Репутация
-3
В первом варианте у тебя окно с освой ством.
Но прилетает не в окно.
Первый твой вариант мне кажется боближе крешению. У тебя окно правильно озадно.
Сообщение автоматически объединено:

$WS_EX_ACCEPTFILES0x00000010Разрешает элементам Edit, Input (и другим) в пределах окна получать путь / имена методом перетаскивания в окно (drag and drop). Также элементы управления должны иметь состояние $GUI_DROPACCEPTED, устанавливаемое функцией GUICtrlSetState.
Сообщение автоматически объединено:

Вопрос получения файлов это решит.
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Не открывается
Сообщение автоматически объединено:

Вопрос получения файлов это решит.
Я уточню вопрос: мне нужно получить событие парения над окном перетаскиваемых файлов, до того, как они будут брошены.
 
Верх