Drag & Drop: Dateipfad in eine Variable bekommen, statt in Inputfeld

  • Hejo

    Ich muss euch wieder belästigen.

    Ich hätte gerne dass wenn ich eine Datei per Drag & Drop auf eine GUI ziehe, ein Ereignis ausgelöst wird. Leider schaffe ich es nur eine Datei per Drag & Drop zb in ein Textfeld zu bekommen, und dann das ganze Textfeld auszulesen. So komm ich zb sehr umständlich und unpraktisch an den Pfad zur Datei und hab in Schleifen das Problem, dass ein und derselbe Drop immerwieder gefunden wird.

    Hier habe ich eine Möglichkeit gefunden, ein ganzes Form drag & dropable zu machen. Leider wird aber der Dateipfad in die Console gepostet. $DragDrop = GUIRegisterMsg(0x233, "On_WM_DROPFILES") funktioniert nicht, die Variable bleibt leer und das Ergebnis landet weiter nur in der Console. Die AutoIt-Hilfe ist für mich zu kryptisch, ich verstehe die GUIRegisterMsg-Funktion nicht.

    Aber auch wenn ich ganz regulär eine Datei in ein Text- oder anderes Inputfeld ziehe, komme ich nicht an ihren Pfad, ohne das gesamte Feld auszulesen. Ich habe es mitdem @GUI_DRAGFILE Makro versucht (dass wird im Changelog erwähnt), aber die AutoIt scheint dieses nicht (mehr?) zu kennen oder so, ich find dazu auch nicht viel.

    Mein eigener Ansatz war folgender:

    Spoiler anzeigen
    [autoit]

    #include <EditConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $Form1 = GUICreate("Form1", 316, 139, 192, 124, -1, BitOR($WS_EX_ACCEPTFILES,$WS_EX_WINDOWEDGE))
    $Edit1 = GUICtrlCreateEdit("", 8, 24, 297, 89)
    GUICtrlSetState(-1, $GUI_ACCEPTFILES)
    GUICtrlSetData(-1, "Hallo")
    GUISetState(@SW_SHOW)

    [/autoit] [autoit][/autoit] [autoit]

    While 1

    [/autoit] [autoit][/autoit] [autoit]

    $DragDrop = GuiCtrlRead($Edit1,0)
    If StringLen($DragDrop) >= 10 Then MsgBox(0,"","Eine Datei wurde gedroppt: " & @CRLF & $DragDrop)

    [/autoit] [autoit][/autoit] [autoit]

    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    Exit

    [/autoit] [autoit][/autoit] [autoit]

    EndSwitch
    WEnd

    [/autoit]

    Dieser ist natürlich totaler Blödsinn, weil ja so unendlich ein Pfad entdeckt wird, wenn im Textfeld mehr als 10 Zeichen sind. Aber ich hab einfach keine Idee. Man könnte es mit RegEx machen (zb nach ":\\" suchen) aber auch da würd man ja bei jedem Durchlauf wieder den Pfad finden. Und das Input-Feld resetten will ich nicht, ich bin eigentlich an garkeiner Visualisierung des Drops interessiert.

    Also nochmal in kurz: Ich will am liebsten eine Datei auf die GUI an sich ziehen (notfalls tut es auch ein Input-Feld), und diese nicht anzeigen, sondern einfach nur in eine Variable speichern, die, sobald sie Inhalt halt, eine Aktion auslöst und dann wieder zurückgesetzt wird um auf den nächsten Drag & Drop zu warten.

    Sicher nix schweres aber ich bin zu doof :(

    Einmal editiert, zuletzt von klischee (26. Mai 2011 um 14:14)

  • In der Hilfe unter GUICtrlCreateInput ist ein Beispiel, das du suchst oder?

    Spoiler anzeigen
    [autoit][/autoit] [autoit][/autoit] [autoit]

    #include <GUIConstantsEx.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Opt('MustDeclareVars', 1)

    [/autoit] [autoit][/autoit] [autoit]

    Example()

    [/autoit] [autoit][/autoit] [autoit]

    Func Example()
    Local $file, $btn, $msg

    [/autoit] [autoit][/autoit] [autoit]

    GUICreate(" My GUI input acceptfile", 320, 120, @DesktopWidth / 2 - 160, @DesktopHeight / 2 - 45, -1, 0x00000018); WS_EX_ACCEPTFILES
    $file = GUICtrlCreateInput("", 10, 5, 300, 20)
    GUICtrlSetState(-1, $GUI_DROPACCEPTED)
    GUICtrlCreateInput("", 10, 35, 300, 20) ; will not accept drag&drop files
    $btn = GUICtrlCreateButton("Ok", 40, 75, 60, 20)

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    $msg = 0
    While $msg <> $GUI_EVENT_CLOSE
    $msg = GUIGetMsg()
    Select
    Case $msg = $btn
    ExitLoop
    EndSelect
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    MsgBox(4096, "drag drop file", GUICtrlRead($file))
    EndFunc ;==>Example

    [/autoit]

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Hier mal mit der angesprochenen GUIregistermsg Lösung, sollte mit den Kommentaren ja eigentlich verständlich sein:

    Spoiler anzeigen
    [autoit]


    #include <ButtonConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    #include <array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global $aTest[1]=[0] ; deklariert ein Array mit der Größe 1, dieses wird später erweitert wenn Dateien gedropt werden

    [/autoit] [autoit][/autoit] [autoit]

    $GUI = GUICreate("Drop GUI", 500, 355, -1, -1, -1, BitOR($WS_EX_ACCEPTFILES,$WS_EX_WINDOWEDGE))
    $ShowFiles = GUICtrlCreateButton("Zeige gedroppte Dateien",360,30)
    $RunFiles = GUICtrlCreateButton("Starte Aufgabe",260,30)
    $DropInfo = GUICtrlCreateLabel("Drop Files here", 10, 115, 480, 165, BitOR($SS_CENTER,$SS_CENTERIMAGE))

    [/autoit] [autoit][/autoit] [autoit]

    Const $WM_DROPFILES = 0x233;
    GUIRegisterMsg($WM_DROPFILES, "On_WM_DROPFILES") ; erkennt drop Aktionen

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState(@SW_SHOW)

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    Exit
    Case $ShowFiles
    _ArrayDisplay($aTest) ; zeigt das Array an welches die Dateiliste enthält
    Case $RunFiles
    openmyfiles() ; führt beliebige Aktion mit den gespeicherten Dateien durch
    EndSwitch
    ; folgende Zeile Einkommentieren wenn du automatisch deine Arbeitsfunktion aufrufen willst sobald Dateien gedroppt wurden:
    ;if $aTest[0] > 0 Then openmyfiles()
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func openmyfiles()
    if $aTest[0] = 0 Then
    MsgBox(0,"Fehler", "Es wurden keine Dateien gedroppt.")
    return -1 ; Keine Dateien im Array, also auch nix zu tun, somit verlassen wir die Funktion vorzeitig
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    for $i=$aTest[0] to 1 Step -1 ; öffnet alle Dateien im Array und entfernt diese im Anschluss aus dem Array
    run("notepad.exe " & '"' & $aTest[$i] & '"') ; öffnet aktuelle Datei
    _ArrayDelete($aTest,$i) ; entfernt aktuelle Datei aus dem Array
    $aTest[0] -= 1 ; erniedrigt Eintrag [0] um 1, also die Anzahl der verbleibenden Dateien
    Next ; nächste Datei
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func filter(ByRef $dFiles)
    For $i = 0 To UBound($dFiles)-1
    if StringInStr($dFiles[$i],".txt") Then ; nur txt Dateien sollen gespeichert werden
    _ArrayAdd($aTest,$dFiles[$i]) ; fügt dem Array aTest einen neuen Eintrag hinzu
    $aTest[0] += 1 ; erhöht Eintrag [0] um 1, dies ist die Anzahl der Dateien die sich aktuell im Array befinden
    Else
    MsgBox(0,"Fehler","Es werden nur TXT Dateien unterstützt.")
    EndIf
    Next
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func On_WM_DROPFILES($hWnd, $Msg, $wParam, $lParam)
    Local $tDrop, $i, $aRet, $iCount;
    ;get file count
    $aRet = DllCall("shell32.dll", "int", "DragQueryFileW", "ptr", $wParam, "uint", -1, "ptr", 0, "uint", 0 )
    $iCount = $aRet[0]
    ;get file paths
    local $aDraggedFiles[$iCount];
    For $i = 0 To $iCount-1
    $aRet = DllCall("shell32.dll", "int", "DragQueryFileW", "ptr", $wParam, "uint", $i, "ptr", 0, "uint", 0)
    Local $tDrop = DllStructCreate("wchar[" & $aRet[0]+1 & "]")
    $aRet = DllCall("shell32.dll", "int", "DragQueryFileW", "ptr", $wParam, "uint", $i, "ptr", DllStructGetPtr($tDrop), "uint", $aRet[0]+1)
    $aDraggedFiles[$i] = DllStructGetData($tDrop, 1);
    Next
    ;finalize
    DllCall("shell32.dll", "int", "DragFinish", "ptr", $wParam)

    [/autoit] [autoit][/autoit] [autoit]

    filter($aDraggedFiles) ; <-- filtert die gedroppten Dateien
    EndFunc

    [/autoit]
  • Super, danke wiedermal! Hatte mich dumm und dämlich gesucht aber auch in der Hilfe nix entdeckt.

    Die zweite Lösung hab ich nun umgesetzt :) Merci.