Jump to content

Copy A File To The Clipboard Like Filemanagers Do


Recommended Posts

first of all i'm sorry for posting a support request into the dev forum.

but everytime i posted something like this into the support forum, i never got helped.

so i'll try my luck here today :(

I'm trying to copy a file into the clipboard that explorer can paste.

here is how far i got:

CODE
;~ ' format of CF_HDROP and CF_PRINTERS, in the HDROP case the data that follows

;~ ' is a double null terminated list of file names, for printers they are printer

;~ ' friendly names

;~ '

;~ TYPE DROPFILES

;~ pFiles AS DWORD ' offset of file list

;~ pt AS POINTAPI ' drop point (client coords)

;~ fNC AS LONG ' is it on NonClient area and pt is in screen coords

;~ fWide AS LONG ' WIDE character switch

;~ END TYPE

;~ TYPE POINTAPI

;~ x AS LONG

;~ y AS LONG

;~ END TYPE

$sFile = @ScriptFullPath

$nBuffSize = StringLen($sFile) + 2

$POINTAPI = DllStructCreate("int;int")

$DROPFILES = DllStructCreate("dword;ptr;int;int;char["&$nBuffSize&"]")

DllStructSetData($DROPFILES,2,DllStructGetPtr($POINTAPI))

DllStructSetData($DROPFILES,1,DllStructGetSize($DROPFILES) - $nBuffSize)

; uncomment the next line and comment out the last one to crash you explorer :D

;DllStructSetData($DROPFILES,1,DllStructGetPtr($DROPFILES,5))

DllStructSetData($DROPFILES,5,$sFile & "||")

For $i = 1 To $nBuffSize

; Replacing '|' with chr(0)

If DllStructGetData($DROPFILES,5,$i) = 124 Then DllStructSetData($DROPFILES,5,0,$i)

Next

$r = DllCall("user32.dll","int","OpenClipboard","hwnd",0)

If @error Or $r[0] = 0 Then ConsoleWrite("Error: " & FileReadLine(@ScriptFullPath,@ScriptLineNumber-1))

$r = DllCall("user32.dll","int","EmptyClipboard")

If @error Or $r[0] = 0 Then ConsoleWrite("Error: " & FileReadLine(@ScriptFullPath,@ScriptLineNumber-1))

;~ HGLOBAL GlobalAlloc(

;~ UINT uFlags,

;~ SIZE_T dwBytes

;~ );

$GMEM_MOVEABLE = 0x0002

$r = DllCall("kernel32.dll","long","GlobalAlloc","int",$GMEM_MOVEABLE,"int",DllStructGetSize($DROPFILES)+1)

If @error Or $r[0] < 1 Then ConsoleWrite("Error: " & FileReadLine(@ScriptFullPath,@ScriptLineNumber-1))

$hGlobal = $r[0]

;~ LPVOID GlobalLock(

;~ HGLOBAL hMem

;~ );

$r = DllCall("kernel32.dll","long","GlobalLock","long",$hGlobal)

If @error Or $r[0] < 1 Then ConsoleWrite("Error: " & FileReadLine(@ScriptFullPath,@ScriptLineNumber-1))

$hLock = $r[0]

; DECLARE SUB MoveMemory LIB "KERNEL32.DLL" ALIAS "RtlMoveMemory" (pDestination AS ANY, pSource AS ANY, BYVAL cbLength AS LONG)

$r = DllCall("kernel32.dll","none","RtlMoveMemory","long",$hLock,"long",DllStructGetPtr($DROPFILES),"int",DllStructGetSize($DROPFILES))

If @error Then ConsoleWrite("Error: " & FileReadLine(@ScriptFullPath,@ScriptLineNumber-1))

;~ HANDLE SetClipboardData(

;~ UINT uFormat,

;~ HANDLE hMem

;~ );

$CF_HDROP = 15

$r = DllCall("user32.dll","long","SetClipboardData","int",$CF_HDROP,"long",$hGlobal)

If @error Or $r[0] < 1 Then ConsoleWrite("Error: " & FileReadLine(@ScriptFullPath,@ScriptLineNumber-1))

$r = DllCall("user32.dll","int","CloseClipboard")

If @error Or $r[0] = 0 Then ConsoleWrite("Error: " & FileReadLine(@ScriptFullPath,@ScriptLineNumber-1))

;~ BOOL GlobalUnlock(

;~ HGLOBAL hMem

;~ );

$r = DllCall("kernel32.dll","int","GlobalUnlock","long",$hGlobal)

If @error Or _LastError() > 0 Then ConsoleWrite("Error: " & FileReadLine(@ScriptFullPath,@ScriptLineNumber-1))

Func _LastError()

Local $r = DllCall("kernel32.dll","int","GetLastError")

Return $r[0]

EndFunc

the only example for DROPFILES i found is here, but i dont get it :)
CODE
#include "stdafx.h"

#include "DropFiles.h"

CDropFiles::CDropFiles()

{

m_pBuff = NULL;

m_nBuffSize = 0;

}

CDropFiles::~CDropFiles()

{

delete m_pBuff;

}

void CDropFiles::AddFile(const CString &sFile)

{

m_aFiles.Add(sFile);

}

void CDropFiles::CreateBuffer()

{

// CreateBuffer must be called once, when all Files are added!!!

ASSERT(m_pBuff == NULL);

ASSERT(m_nBuffSize == 0);

for(int i=0;i<m_aFiles.GetSize();i++){

m_nBuffSize += m_aFiles.GetLength()+1;

}

m_nBuffSize += sizeof(DROPFILES)+2;

m_nBuffSize = (m_nBuffSize/32 + 1)*32;

int nBuffSize = 0;

m_pBuff = new char[m_nBuffSize];

ZeroMemory(m_pBuff, m_nBuffSize);

((DROPFILES*)m_pBuff)->pFiles = sizeof(DROPFILES);

char* pCurrent = m_pBuff + sizeof(DROPFILES);

for(i=0;i<m_aFiles.GetSize();i++){

strcpy(pCurrent,(LPCTSTR)m_aFiles);

pCurrent += m_aFiles.GetLength();

*pCurrent = 0;

pCurrent++;

}

//check buffer bound

ASSERT(pCurrent - m_nBuffSize - 1 <= m_pBuff);

}

void* CDropFiles::GetBuffer() const

{

ASSERT(m_pBuff);

return (void *)m_pBuff;

}

int CDropFiles::GetBuffSize() const

{

ASSERT(m_nBuffSize);

return m_nBuffSize;

}

CoProc Multi Process Helper libraryTrashBin.nfshost.com store your AutoIt related files here!AutoIt User Map
Link to comment
Share on other sites

finaly, success :)

Opt('MustDeclareVars',1)

; Tests
Local $fTest
If @Compiled Then
    ConsoleWrite("Tests dont work with compiled script" & @CR)
    Exit
EndIf
; Single File
$fTest = _ClipPutFile(@ScriptFullPath)
If Not $fTest Then
    ConsoleWrite("Test 1 Failed -> " & @error & @CR)
Else
    ConsoleWrite("Test 1 Result:" & @CR & ClipGet() & @CR)
EndIf

; Multiple files
$fTest = _ClipPutFile(@ScriptFullPath & "|" & @AutoItExe)
If Not $fTest Then
    ConsoleWrite("Test 2 Failed -> " & @error & @CR)
Else
    ConsoleWrite("Test 2 Result:" & @CR & ClipGet() & @CR)
EndIf

; Seperator
$fTest = _ClipPutFile(@ScriptFullPath & "$" & @AutoItExe,"$")
If Not $fTest Then
    ConsoleWrite("Test 3 Failed -> " & @error & @CR)
Else
    ConsoleWrite("Test 3 Result:" & @CR & ClipGet() & @CR)
EndIf

Func _ClipPutFile($sFile, $sSeperator = "|")
    Local $vDllCallTmp, $nGlobMemSize, $hGlobal, $DROPFILES, $i, $hLock
    Local $GMEM_MOVEABLE = 0x0002, $CF_HDROP = 15
    $sFile = $sFile & $sSeperator & $sSeperator
    $nGlobMemSize = StringLen($sFile) + 20; 20 = size of DROPFILES whitout buffer
    $vDllCallTmp = DllCall("user32.dll", "int", "OpenClipboard", "hwnd", 0)
    If @error Or $vDllCallTmp[0] = 0 Then
        SetError(1)
        Return False
    EndIf
    $vDllCallTmp = DllCall("user32.dll", "int", "EmptyClipboard")
    If @error Or $vDllCallTmp[0] = 0 Then
        SetError(2)
        Return False
    EndIf
    $vDllCallTmp = DllCall("kernel32.dll", "long", "GlobalAlloc", "int", $GMEM_MOVEABLE, "int", $nGlobMemSize)
    If @error Or $vDllCallTmp[0] < 1 Then
        SetError(3)
        Return False
    EndIf
    $hGlobal = $vDllCallTmp[0]
    $vDllCallTmp = DllCall("kernel32.dll", "long", "GlobalLock", "long", $hGlobal)
    If @error Or $vDllCallTmp[0] < 1 Then
        SetError(4)
        Return False
    EndIf
    $hLock = $vDllCallTmp[0]
    
    $DROPFILES = DllStructCreate("dword;ptr;int;int;int;char[" & StringLen($sFile) & "]", $hLock)
    If @error Then
        SetError(5)
        Return False
    EndIf
    DllStructSetData($DROPFILES, 1, DllStructGetSize($DROPFILES) - StringLen($sFile))
    DllStructSetData($DROPFILES, 2, 0)
    DllStructSetData($DROPFILES, 3, 0)
    DllStructSetData($DROPFILES, 4, 0)
    DllStructSetData($DROPFILES, 5, 0)
    DllStructSetData($DROPFILES, 6, $sFile)
    For $i = 1 To StringLen($sFile)
        If DllStructGetData($DROPFILES, 6, $i) = Asc($sSeperator) Then DllStructSetData($DROPFILES, 6, 0, $i)
    Next
    $vDllCallTmp = DllCall("user32.dll", "long", "SetClipboardData", "int", $CF_HDROP, "long", $hGlobal)
    If @error Or $vDllCallTmp[0] < 1 Then
        SetError(6)
        $DROPFILES = 0
        Return False
    EndIf
    $vDllCallTmp = DllCall("user32.dll", "int", "CloseClipboard")
    If @error Or $vDllCallTmp[0] = 0 Then
        SetError(7)
        $DROPFILES = 0
        Return False
    EndIf
    $vDllCallTmp = DllCall("kernel32.dll", "int", "GlobalUnlock", "long", $hGlobal)
    If @error Then
        SetError(8)
        $DROPFILES = 0
        Return False
    EndIf
    $vDllCallTmp = DllCall("kernel32.dll", "int", "GetLastError")
    If $vDllCallTmp = 0 Then 
        $DROPFILES = 0
        Return False
    Else
        SetError(8)
        $DROPFILES = 0
        Return True
    EndIf
EndFunc  ;==>_ClipPutFile
CoProc Multi Process Helper libraryTrashBin.nfshost.com store your AutoIt related files here!AutoIt User Map
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...