Jump to content

Recommended Posts

Posted (edited)

How do I use this UDF (Clipboard.au3) to copy an entire file to the Clipboard?
I don't mean its contents or path.
But I want the entire file, so the user can then paste it to the target location using CTRL+V, even if they want to paste it on a remote desktop.

Edited by mLipok

Signature beginning:
Please remember: "AutoIt"..... *  Wondering who uses AutoIt and what it can be used for ? * Forum Rules *
ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * IE on Windows 11 * How to ask ChatGPT for AutoIt Codefor other useful stuff click the following button:

Spoiler

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind. 

My contribution (my own projects): * Debenu Quick PDF Library - UDF * Debenu PDF Viewer SDK - UDF * Acrobat Reader - ActiveX Viewer * UDF for PDFCreator v1.x.x * XZip - UDF * AppCompatFlags UDF * CrowdinAPI UDF * _WinMergeCompare2Files() * _JavaExceptionAdd() * _IsBeta() * Writing DPI Awareness App - workaround * _AutoIt_RequiredVersion() * Chilkatsoft.au3 UDF * TeamViewer.au3 UDF * JavaManagement UDF * VIES over SOAP * WinSCP UDF * GHAPI UDF - modest begining - comunication with GitHub REST APIErrorLog.au3 UDF - A logging Library * Include Dependency Tree (Tool for analyzing script relations) * Show_Macro_Values.au3 *

 

My contribution to others projects or UDF based on  others projects: * _sql.au3 UDF  * POP3.au3 UDF *  RTF Printer - UDF * XML.au3 UDF * ADO.au3 UDF SMTP Mailer UDF * Dual Monitor resolution detection * * 2GUI on Dual Monitor System * _SciLexer.au3 UDF * SciTE - Lexer for console pane

Useful links: * Forum Rules * Forum etiquette *  Forum Information and FAQs * How to post code on the forum * AutoIt Online Documentation * AutoIt Online Beta Documentation * SciTE4AutoIt3 getting started * Convert text blocks to AutoIt code * Games made in Autoit * Programming related sites * Polish AutoIt Tutorial * DllCall Code Generator * 

Wiki: Expand your knowledge - AutoIt Wiki * Collection of User Defined Functions * How to use HelpFile * Good coding practices in AutoIt * 

OpenOffice/LibreOffice/XLS Related: WriterDemo.au3 * XLS/MDB from scratch with ADOX

IE Related:  * How to use IE.au3  UDF with  AutoIt v3.3.14.x * Why isn't Autoit able to click a Javascript Dialog? * Clicking javascript button with no ID * IE document >> save as MHT file * IETab Switcher (by LarsJ ) * HTML Entities * _IEquerySelectorAll() (by uncommon) * IE in TaskSchedulerIE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) * PDF Related:How to get reference to PDF object embeded in IE * IE on Windows 11

I encourage you to read: * Global Vars * Best Coding Practices * Please explain code used in Help file for several File functions * OOP-like approach in AutoIt * UDF-Spec Questions *  EXAMPLE: How To Catch ConsoleWrite() output to a file or to CMD *

I also encourage you to check awesome @trancexx code:  * Create COM objects from modules without any demand on user to register anything. * Another COM object registering stuffOnHungApp handlerAvoid "AutoIt Error" message box in unknown errors  * HTML editor

winhttp.au3 related : * https://www.autoitscript.com/forum/topic/206771-winhttpau3-download-problem-youre-speaking-plain-http-to-an-ssl-enabled-server-port/

"Homo sum; humani nil a me alienum puto" - Publius Terentius Afer
"Program are meant to be read by humans and only incidentally for computers and execute" - Donald Knuth, "The Art of Computer Programming"
:naughty:  :ranting:, be  :) and       \\//_.

Anticipating Errors :  "Any program that accepts data from a user must include code to validate that data before sending it to the data store. You cannot rely on the data store, ...., or even your programming language to notify you of problems. You must check every byte entered by your users, making sure that data is the correct type for its field and that required fields are not empty."

Signature last update: 2023-04-24

Posted (edited)

I believe this is what you want :

#include <Memory.au3>
#include <Clipboard.au3>
#include <WinAPIDiag.au3>

$sFilePath = 'C:\Apps\AutoIt\AATemp\Test.txt'
_ClipPutFile($sFilePath)

Func _ClipPutFile($sFile)
  Local $iLen = StringLen($sFile) + 2
  Local $hGlobal = _MemGlobalAlloc($iLen * 2 + 20, $GMEM_MOVEABLE)
  Local $pLock = _MemGlobalLock($hGlobal)
  Local $tDROPFILES = DllStructCreate("dword pFiles;long x;long y;int fNC;int fWide;wchar File[" & $iLen & "]", $pLock)
  With $tDROPFILES
    .pFiles = 20
    .x = 0
    .y = 0
    .fNC = 0
    .fWide = 1
    .File = $sFile & ChrW(0)
  EndWith
  ;  _WinAPI_DisplayStruct($tDROPFILES, "dword pFiles;long x;long y;int fNC;int fWide;wchar File[" & $iLen & "]")

  _ClipBoard_Open(0)
  _ClipBoard_Empty()
  _ClipBoard_SetDataEx($hGlobal, $CF_HDROP)
  _MemGlobalUnlock($hGlobal)
  _ClipBoard_Close()
  _MemGlobalFree($hGlobal)
EndFunc   ;==>_ClipPutFile

Just paste it in File Explorer anywhere...

Edited by Nine
Posted (edited)
42 minutes ago, Nine said:

Just paste it in File Explorer anywhere...

I was just going to mention _ClipPutFile. But I'm curious, I was also looking into _ClipBoard_SetData to mention in this thread as well. In that case, I believe we would need to use $CF_HDROP but I'm not sure how to create the HDROP to specify the file(s). Mostly, I'm curious if this method would also work for the purpose of this thread and allow Paste (Ctrl+V) to show up in File Explorer. Do you know much about this function?

EDIT: I just realized that the _ClipBoard_SetDataEx is literally within your function. Sorry for my misunderstanding.

Edited by WildByDesign
Posted
1 hour ago, WildByDesign said:

I was just going to mention _ClipPutFile

You are right.  Misc.au3's _ClipPutFile does the same.  Forgot about this function.  I had the code in my library.

However, I took a closer look at that include function.  I noticed a couple of bugs in allocating the memory, but it does not cause any harm.  Just  a bit too much memory for nothing.

Posted

@Nine If you have a moment, would you please help with extending this further?

I feel like we need more example regarding $CF_HDROP and particularly the receiving end.

For an example (below), this creates a hidden window that listens for clipboard updates. If you go to the Desktop or File Explorer and press Ctrl+C to copy, it will run through the function. If you copy just text, it will disregard since we are only working with files.

I believe that I am failing when trying to get a handle with _ClipBoard_GetDataEx($CF_HDROP).

My initial goal is to get that handle for the HDROP and cycle through the file names contained in it with _WinAPI_DragQueryFileEx with simple ConsoleWrites. If we can get past this point, we could then use IFileOperation or even the older _WinAPI_ShellFileOperation to perform the copy.

 

#include <Clipboard.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <SendMessage.au3>
#include <WinAPISys.au3>
#include <WindowsNotifsConstants.au3>
#include <WindowsStylesConstants.au3>
#include <WinAPISysWin.au3>

OnAutoItExitRegister("_Exit")

If Number(_WinAPI_GetVersion()) < 6.0 Then
    MsgBox(($MB_ICONERROR + $MB_SYSTEMMODAL), 'Error', 'Require Windows Vista or later.')
    Exit
EndIf

Global $hForm = GUICreate('Test ' & StringReplace(@ScriptName, '.au3', '()'), 400, 400, 10, 10, BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX), $WS_EX_TOPMOST)
Global $g_idEdit = GUICtrlCreateEdit('', 0, 0, 400, 400, BitOR($GUI_SS_DEFAULT_EDIT, $ES_READONLY))
GUIRegisterMsg($WM_CLIPBOARDUPDATE, 'WM_CLIPBOARDUPDATE')
;GUISetState(@SW_SHOW)

_WinAPI_AddClipboardFormatListener($hForm)
_SendMessage($hForm, $WM_CLIPBOARDUPDATE)

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func WM_CLIPBOARDUPDATE($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam

    If _ClipBoard_IsFormatAvailable($CF_HDROP) Then
        ConsoleWrite("CF_HDROP available in clipboard." & @CRLF)
        Local $hHDROP = _ClipBoard_GetDataEx($CF_HDROP)    ; failing to get handle?
        ConsoleWrite("hdrop: " & $hHDROP & @CRLF)
        ; would like to run _WinAPI_DragQueryFileEx here to view file name(s) from HDROP
        Local $aFileList = _WinAPI_DragQueryFileEx($hHDROP)
        If Not @error Then
            For $i = 1 To $aFileList[0]
                ConsoleWrite($aFileList[$i] & @CRLF)
            Next
        EndIf
    EndIf

    Return 0
EndFunc   ;==>WM_CLIPBOARDUPDATE

Func _Exit()
    _WinAPI_RemoveClipboardFormatListener($hForm)
EndFunc

 

Posted
11 minutes ago, Nine said:

I believe it is because you are not opening the clipboard before getting the data.  Don't forget to close it...

You are 100% right. Some of those _ClipBoard_* functions automatically open/close the clipboard within the functions, so I made a bad assumption that they all must do it. My mistake. Thank you. :)

Posted

For what it's worth, this will list all files/folders contained in the Copy each time you Copy:

(this example can then certainly be extended much further) :)

#include <Clipboard.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <SendMessage.au3>
#include <WinAPISys.au3>
#include <WindowsNotifsConstants.au3>
#include <WindowsStylesConstants.au3>
#include <WinAPISysWin.au3>

OnAutoItExitRegister("_Exit")

Global $hForm = GUICreate('Test ' & StringReplace(@ScriptName, '.au3', '()'), 400, 400, 10, 10, BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX), $WS_EX_TOPMOST)
Global $g_idEdit = GUICtrlCreateEdit('', 0, 0, 400, 400, BitOR($GUI_SS_DEFAULT_EDIT, $ES_READONLY))
GUIRegisterMsg($WM_CLIPBOARDUPDATE, 'WM_CLIPBOARDUPDATE')
;GUISetState(@SW_SHOW)

_WinAPI_AddClipboardFormatListener($hForm)
;_SendMessage($hForm, $WM_CLIPBOARDUPDATE)

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func WM_CLIPBOARDUPDATE($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam

    If _ClipBoard_IsFormatAvailable($CF_HDROP) Then
        If _ClipBoard_Open($hForm) Then
            ConsoleWrite("----------------------------------------------------------" & @CRLF)
            ConsoleWrite("Files contained in Copy:" & @CRLF)
            Local $hHDROP = _ClipBoard_GetDataEx($CF_HDROP)
            Local $aFileList = _WinAPI_DragQueryFileEx($hHDROP)
            If Not @error Then
                For $i = 1 To $aFileList[0]
                    ConsoleWrite($aFileList[$i] & @CRLF)
                Next
            EndIf
            _ClipBoard_Close()
            ConsoleWrite("----------------------------------------------------------" & @CRLF)
        EndIf
    EndIf

    Return 0
EndFunc   ;==>WM_CLIPBOARDUPDATE

Func _Exit()
    _WinAPI_RemoveClipboardFormatListener($hForm)
EndFunc

 

Posted
10 hours ago, Nine said:

However, I took a closer look at that include function.  I noticed a couple of bugs in allocating the memory, but it does not cause any harm.  Just  a bit too much memory for nothing.

I was thinking about this some more. The _ClipPutFile in Misc.au3 allows adding multiple files to the clipboard but only via delimiter. And you've found some memory allocation bugs, although harmless.

Would you be willing to update that function officially in the UDFs and, if possible, allow by delimiter as it is now but also by array?

Posted
3 hours ago, WildByDesign said:

allow by delimiter as it is now but also by array

Here my take on it :

; From Nine
#include <Memory.au3>
#include <Clipboard.au3>
#include <File.au3>

Example()

Func Example()
  Local $vList = _FileListToArray(@ScriptDir, "*.au3", $FLTA_FILES, True)
  _ArrayDelete($vList, 0)
  ; $vList = _ArrayToString($vList) ; uncomment for string parameter
  _ClipPutFile($vList)
EndFunc   ;==>Example

Func _ClipPutFile(ByRef $vFile, $sDelim = "|")
  If $sDelim = Default Then $sDelim = "|"
  Local $aFile = IsArray($vFile) ? $vFile : StringSplit($vFile, $sDelim, $STR_NOCOUNT)
  If Not UBound($aFile) Then Return SetError(1)
  Local $iLen = 1
  For $sText In $aFile
    $iLen += StringLen($sText) + 1
  Next
  Local $hGlobal = _MemGlobalAlloc($iLen * 2 + 20, $GHND)
  Local $pLock = _MemGlobalLock($hGlobal)
  Local $tDROPFILES = DllStructCreate("dword pFiles;" & $tagPOINT & ";bool fNC;bool fWide;wchar File[" & $iLen & "]", $pLock)
  With $tDROPFILES
    .pFiles = 20
    .x = 0
    .y = 0
    .fNC = 0
    .fWide = 1
  EndWith

  Local $pStr = DllStructGetPtr($tDROPFILES, "File"), $tStr
  For $sText In $aFile
    $iLen = StringLen($sText) + 1
    $tStr = DllStructCreate("wchar str[" & $iLen & "]", $pStr)
    $tStr.str = $sText
    $pStr += $iLen * 2
  Next

  _ClipBoard_Open(0)
  _ClipBoard_Empty()
  _ClipBoard_SetDataEx($hGlobal, $CF_HDROP)
  _MemGlobalUnlock($hGlobal)
  _ClipBoard_Close()
  _MemGlobalFree($hGlobal)
EndFunc   ;==>_ClipPutFile

I am not checking for other errors as it is most likely impossible to have an error unless the input is wrong.

Posted
6 hours ago, Nine said:

Here my take on it :

This is perfect. This is now much more usable in comparison to the one from Misc.au3 because it makes more sense to accept arrays. Works very well. :)

6 hours ago, Nine said:

I am not checking for other errors as it is most likely impossible to have an error unless the input is wrong.

Exactly, I agree. And in my usage for it, the arrays of file names and folders will come directly from the filesystem anyway so therefore no chances for incorrect input. Thank you for this. It is very helpful.

Posted
24 minutes ago, argumentum said:

I would add $STR_ENTIRESPLIT to make sure the the whole $sDelim is used

Good thinking.  On the other end, one may wish to use any of the characters in the $sDelim.  We could of course add a new parameter to indicate $STR_ENTIRESPLIT or not...but keep in mind that the original spirit of the function was to use a single character.

 

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
×
×
  • Create New...