Jump to content

Drag&drop file to external non-autoit program


Recommended Posts

I have my autoit script, working just fine.

I have an external program (basically any other program), that accepts drag&drop of files - either entire windows or a particular control is the target of drop operation.

I can read, using both my autoit script and Au3Info.exe, all handles of the external program window and controls.

I need to initiate / simulate drag&drop of a file, from my autoit script to that external program.

In this particular case, only one single control will accept drag&drop operation, NOT entire window - see attached image.

Like I said, I have the handle of the control, it is a handle indeed (IsHWnd = True)

I have tried this:

It is NOT working. I get NO errors, NO warnings, no problems, but just not working.

Then I tried this:

Same thing: NOT working, but also NO errors, NO warnings, no problems, simply not working.

Then I tried to use ProgAndy's http://www.autoitscript.com/forum/topic/90831-drag-and-drop-with-explorer/ - but I cannot understand the code - parameters (ByRef $objIDataSource, ByRef $objIDropSource, $dwDropEffects, ByRef $dwPerformedEffect)

 

Manual drag&drop works perfectly. Drag&drop from autoit to notepad also works.

Image1.jpg

Link to comment
Share on other sites

Sure, no problem, this is the script for this function: _FileDragDrop.au3

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include '_FileDragDrop.au3'
#include "Array.au3"

Opt('WinTitleMatchMode', 2)

Global $control01 = -1  ; variable to hold control handle

WinActivate('xDecoder')     ; activate external window
$hwnd = WinGetHandle('xDecoder')    ; get handle of external window

$aArray = _WinGetControls('xDecoder')   ; function to get all control from external window
;~ _ArrayDisplay($aArray)

For $i = 0 to UBound($aArray)-1 ; parse all controls
    if $aArray[$i][0] = 'RichEdit20W1' Then ; extract control I need
        Global $control01 = $aArray[$i][1]  ; get handle
        ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $control01 = ' & $control01 & @CRLF & '>Error code: ' & @error & @CRLF) ; display handle value
        ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : 01 = ' & IsHWnd($control01) & @CRLF & '>Error code: ' & @error & @CRLF) ; verify handle IsHWnd
        ExitLoop
    EndIf
Next

$ret1 = ControlGetText($hwnd, '', $control01)   ; get text of control
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ret1 = ' & $ret1 & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
Sleep(333)

$ret2 = _FileDragDrop($control01, 'c:\ren.Stage1');, 520, 200, "|", True)
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ret2 = ' & $ret2 & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console

;~ ControlSend($hwnd, '', $control01, 'C:\444\tets\EDC15C3_Renault_Espace_1.9_DCI_2001_Turbodiesel___88.3KWKW_Bosch_0281011324__369847_06FC.Stage1')





;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Func _WinGetControls($Title, $Text="")
    Local $WndControls, $aControls, $sLast="", $n=1
    $WndControls = WinGetClassList($Title)
    $aControls = StringSplit($WndControls, @CRLF)
    Dim $aResult[$aControls[0]+1][2]
    For $i = 1 To $aControls[0]
        If $aControls[$i] <> "" Then
            If $sLast = $aControls[$i] Then
                $n+=1
            Else
                $n=1
            EndIf
            $aControls[$i] &= $n
            $sLast = StringTrimRight($aControls[$i],1)
        EndIf
        If $i < $aControls[0] Then
            $aResult[$i][0] = $aControls[$i]
        Else ; last item in array
            $aResult[$i][0] = WinGetTitle($Title) ; return WinTitle
        EndIf
        $aResult[$i][1] = ControlGetHandle($Title, $Text, $aControls[$i])
    Next
;~  $aResult[0][0] = "ClassnameNN"
;~  $aResult[0][1] = "Handle"
    Return $aResult
EndFunc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

This is the output:

>"C:\Program Files (x86)\AutoIt3\SciTE\..\AutoIt3.exe" "C:\Program Files (x86)\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.au3" /run /prod /ErrorStdOut /in "C:\444\_001\x-decoder_02.au3" /UserParams    
+>16:13:09 Starting AutoIt3Wrapper (21.316.1639.1) from:SciTE.exe (4.4.6.0)  Keyboard:00000409  OS:WIN_10/2009  CPU:X64 OS:X64  Environment(Language:0409)  CodePage:0  utf8.auto.check:4
+>         SciTEDir => C:\Program Files (x86)\AutoIt3\SciTE   UserDir => C:\Users\---\AppData\Local\AutoIt v3\SciTE\AutoIt3Wrapper   SCITE_USERHOME => C:\Users\---\AppData\Local\AutoIt v3\SciTE 
>Running AU3Check (3.3.16.1)  from:C:\Program Files (x86)\AutoIt3  input:C:\444\_001\x-decoder_02.au3
+>16:13:10 AU3Check ended.rc:0
>Running:(3.3.16.1):C:\Program Files (x86)\AutoIt3\autoit3_x64.exe "C:\444\_001\x-decoder_02.au3"    
+>Setting Hotkeys...--> Press Ctrl+Alt+Break to Restart or Ctrl+BREAK to Stop.
@@ Debug(21) : $control01 = 0x00000000000B08C4
>Error code: 0
@@ Debug(22) : 01 = 1
>Error code: 0
@@ Debug(28) : $ret1 = 
 Producer: CONTINENTAL
 Hardware: SID208
 Software: 9691551980

 DTC table: 8030
>Error code: 0
@@ Debug(32) : $ret2 = True
>Error code: 0
+>16:13:12 AutoIt3.exe ended.rc:0
+>16:13:12 AutoIt3Wrapper Finished.
>Exit code: 0    Time: 2.845

And this is a screenshot with proper control handles.

Results are similar for the other function.

Image2.jpg

Link to comment
Share on other sites

Have you tried to call _FileDragDrop with specific coordinates? You can get pretty easy the position of your control and calculate and drop the files in the middle of the control.

$ret2 = _FileDragDrop($control01, 'c:\ren.Stage1');, 520, 200, "|", True)

Also be aware of fNC member of DROP_FILES structure. If this member is TRUE, iX and iY specifies the screen coordinates of a point in a window's nonclient area. If it is FALSE, iX and iY specifies the client coordinates of a point in the client area.

When the words fail... music speaks.

Link to comment
Share on other sites

As is my script right now, those coordinates should be client area related, right?

X*Y pixels from top left corner - of the window / control, based on handle used.

I tried 520x200 - window / 100x100 - control handle

Then again - Parameter is often ignored ;)

I will try with calculation.

Link to comment
Share on other sites

You can check also if the structures in the _FileDragDrop() are created without any issues and if the members of $stDropFiles structure are set correctly. You can use _WinAPI_DisplayStruct() to display the entire structure.

When the words fail... music speaks.

Link to comment
Share on other sites

10 minutes ago, queensoft said:

If it works with notepad, can't we assume it's correct?!

It might be correct but these cases when it doesn't work are always a good indication that something might not work as intended.

12 minutes ago, queensoft said:

Is this correct? I think it's too advanced for me.

Passing as second parameter the definition of the structure ($tagDROP_FILES) would make it more clear.

When the words fail... music speaks.

Link to comment
Share on other sites

It looks right but in your case it's better to keep fNC as false so the coordinates would be right according to the picture previously attached. Since we excluded a misbehavior of _FileDragDrop(), I suspect the application doesn't process WM_DROPFILES message. This would be consistent with your observation that no errors appears (since the UDF works fine) but also nothing happens (since the application doesn't care about WM_DROPFILES message).

When the words fail... music speaks.

Link to comment
Share on other sites

Alrighty Then!

So what's the solution in this case ?! Manual drag&drop works fine.

Right now I'm using activate window > control click button > standard  Open dialog....

I'd like to process faster and keep window minimised / hidden (works OK for the rest of the operations).

Is there another method / UDF for drag&drop operations?

I have tried both SendMessage and _WinAPI_PostMessage.

Link to comment
Share on other sites

A few comments.

1- I never was able to make WM_DROPFILES work with control handle.  It only works with window handle (at least for me).

2- Taking source from from c:\ root directory may be a problem (it should work, but who knows in your context)

3- I simplified the drop file function to the strict minimum (using ASCII instead of Unicode)

4- Now, example 3 need to be adjusted to your situation.  

#include <WinAPIDiag.au3>
#include <WinAPI.au3>
#include <GUIConstants.au3>
#include <Array.au3>

Opt("MustDeclareVars", True)
Opt("WinTitleMatchMode", -2)

Example1() ; multiple control accepting drops
Example2() ; external program accepting content of a drop file
Example3() ; this would need to be adjusted to your situation

Func Example1()
  Local $hGUI = GUICreate("Test drop", 300, 300, -1, -1, -1, $WS_EX_ACCEPTFILES)
  Local $idEdit1 = GUICtrlCreateEdit("", 10, 10, 250, 50, $ES_WANTRETURN)
  GUICtrlSetState(-1, $GUI_DROPACCEPTED)
  Local $idEdit2 = GUICtrlCreateEdit("", 10, 100, 250, 50, $ES_WANTRETURN)
  GUICtrlSetState(-1, $GUI_DROPACCEPTED)
  GUISetState()

  Local $aPos = ControlGetPos($hGUI, "", $idEdit2)
  _ArrayDisplay($aPos)
  _FileDragDropEx($hGUI, "Test.txt|Test2.doc", $aPos[0]+ 5, $aPos[1] + 5)
  Do
  Until GUIGetMsg() = -3
EndFunc   ;==>example

Func Example2()
  FileDelete("Test.txt")
  FileWriteLine("Test.txt", "This is a test")
  Run("Notepad")
  Local $hWnd = WinWait("[CLASS:Notepad]")
  _FileDragDropEx($hWnd, "Test.txt", 5, 5)
EndFunc

Func Example3()
  Local $hWnd = WinGetHandle('xDecoder')    ; get handle of external window
  ConsoleWrite($hWnd & @CRLF)
  Local $aPos = ControlGetPos($hwnd, "", "RichEdit20W11") ; <<<<<<<<<<<<<<<<<<  Ajust to the control CLASSNN found with Au3info.exe
  _ArrayDisplay($aPos)
  _FileDragDropEx($hWnd, "Test.txt", $aPos[0]+ 5, $aPos[1] + 5) ; taking the content of Test.txt from previous example
EndFunc

Func _FileDragDropEx($hWnd, $sFile, $iXPos = 0, $iYPos = 0)
  Local $iStrLen = StringLen($sFile) + 2
  $sFile = StringReplace($sFile, "|", Chr(0))
  Local $tagDROP_FILES = "dword offset;int px;int py;bool fNC;bool fWide;int;char string[" & $iStrLen & "]"
  Local $tDROP_FILES = DllStructCreate($tagDROP_FILES)
  With $tDROP_FILES
    .offset = 24
    .px = $iXPos
    .py = $iYPos
    .fNC = False
    .fWide = 0
    .string = $sFile
  EndWith
  _WinAPI_DisplayStruct($tDROP_FILES, $tagDROP_FILES)
  _WinAPI_PostMessage($hWnd, $WM_DROPFILES, DllStructGetPtr($tDROP_FILES), 0)
EndFunc

 

Link to comment
Share on other sites

..thinking here.
In "_ArrayDisplay($aPos)" would be better for testing to use MouseMove() to see where it lands. Also, is display scaling other than 100% ?, it may need to account for that.

Edited by argumentum

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

2 hours ago, Nine said:

A few comments.

1- I never was able to make WM_DROPFILES work with control handle.  It only works with window handle (at least for me).

2- Taking source from from c:\ root directory may be a problem (it should work, but who knows in your context)

3- I simplified the drop file function to the strict minimum (using ASCII instead of Unicode)

4- Now, example 3 need to be adjusted to your situation. 

1. I think I never tried with control, only with windows. But I think I got it working.... somehow.... probably with window handle, way back some time ago.

2. Also tried with folder script.

Also added #RequireAdmin (which fixed problems in client's computer, on mine almost everything is launched elevated).

3 & 4. Will try, probably this evening.

Link to comment
Share on other sites

1 hour ago, argumentum said:

..thinking here.
In "_ArrayDisplay($aPos)" would be better for testing to use MouseMove() to see where it lands. Also, is display scaling other than 100% ?, it may need to account for that.

Is _ArrayDisplay($aPos) different than MouseMove sometimes? Isn't MouseMove good enough of a test?

Display scaling - no problems here, 100%. I'm working inside VMWare (possible virus suspicion), but I don't think that's a problem.

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...