[RESOLVED] How to read source path from a cut and paste
I wish to import .txt file data into a VB6 program by copy and paste of the file name, much as one might do in windows explorer. I plan to use the File System Object to have my VB6 program then copy the user selected file from whatever was its original path to a new path specified by my VB6 program.
Having right-clicked the mouse on a source .txt file - say C:\MYFILE001.txt and then clicked "copy" , how please can I get VB6 to read that file path upon which I clicked?
Once I can extract the path of the file upon which I clicked (copy) into VB6 then the FSO will enable me to copy it to any other desired folder destination.
Simply attempting to paste into a text box does not work, since the clipboard does not contain file content information. When I attempt a paste, the paste option is greyed and not available.
Edited: Another example (same example?) found here on this forum
And here is a routine I use in most of my projects where retrieving file names from clipboard is needed. Note that the routine below handles unicode file names also
Code:
Private Declare Function lstrlenW Lib "kernel32.dll" (ByVal psString As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal length As Long)
Private Declare Function DragQueryFile Lib "shell32.dll" Alias "DragQueryFileA" (ByVal hDrop As Long, ByVal UINT As Long, ByVal lpStr As String, ByVal ch As Long) As Long
Private Declare Function CloseClipboard Lib "user32.dll" () As Long
Private Declare Function GetClipboardData Lib "user32.dll" (ByVal wFormat As Long) As Long
Private Declare Function OpenClipboard Lib "user32.dll" (ByVal hWnd As Long) As Long
Private Type DROPFILES ' Clipboard/DataObject structure
pFiles As Long
ptX As Long
ptY As Long
fNC As Long
fWide As Long
End Type
Public Function GetPastedFileData(theFiles As Collection) As Boolean
' Purpose: support function for clipboard unicode/ansi filenames.
' This function will return true if the clipboard contained file names.
' The returned collection will contain the unicode/ansi filenames as needed.
Dim hDrop As Long
Dim lLen As Long
Dim iCount As Long
Dim dFiles As DROPFILES
Dim sFile As String
' Get handle to CF_HDROP if any:
If OpenClipboard(0&) = 0 Then Exit Function
On Error GoTo ExitRoutine
hDrop = GetClipboardData(vbCFFiles)
If Not hDrop = 0 Then ' then copied/cut files exist in memory
iCount = DragQueryFile(hDrop, -1&, vbNullString, 0)
If iCount Then
' the hDrop is a pointer to a DROPFILES structure
' copy the 20-byte structure for our use
CopyMemory dFiles, ByVal hDrop, 20&
' use the pFiles member to track offsets for file names
dFiles.pFiles = dFiles.pFiles + hDrop
Set theFiles = New Collection
For iCount = 1 To iCount
If dFiles.fWide = 0 Then ' ANSI text, use API to get file name
lLen = DragQueryFile(hDrop, iCount - 1, vbNullString, 0&) ' query length
sFile = String$(lLen, vbNullChar) ' set up buffer
DragQueryFile hDrop, iCount - 1, sFile, lLen + 1 ' populate buffer
Else
' get the length of the current file & multiply by 2 because it is unicode
' lstrLenW is supported in Win9x
lLen = lstrlenW(ByVal dFiles.pFiles) * 2
sFile = String$(lLen \ 2, vbNullChar) ' build a buffer to hold the file name
CopyMemory ByVal StrPtr(sFile), ByVal dFiles.pFiles, lLen ' populate the buffer
' move the pointer to location for next file, adding 2 because of a double null separator/delimiter btwn file names
dFiles.pFiles = dFiles.pFiles + lLen + 2
End If
theFiles.Add sFile
Next
GetPastedFileData = True
End If
End If
ExitRoutine:
CloseClipboard
End Function
Sample call to the function might look like:
Code:
Dim colFiles As Collection, v As Variant
If GetPastedFileData(colFiles) = True Then
Debug.Print "File count: ";colFiles.Count
For Each v in colFiles
Debug.Print v
Next
End If
Last edited by LaVolpe; Sep 16th, 2011 at 12:38 PM.
Insomnia is just a byproduct of, "It can't be done"
I find that if I'm going to support copy/paste from Explorer then drag/drop belongs there too. While VB6 supports (ANSI) file drag/drop it needs help for copy/paste clipboard operations with files.
I'm sure most of us have our pet routines for this kind of thing.
I prefer to wrap similar API calls in a global predeclared object I call PasteFiles that provides a neat way to handle the issue with an object model more compatible with drag/drop in VB6. There is no need for those CopyMemory calls, I think somebody used a bad example to work from. This object has a separate method to test the clipboard for files so your program can avoid false hits by not displaying a right-click paste menu when there aren't any files in the clipboard to paste.
This one handles Paste for Unicode file names as well.
The attachment uses PasteFiles.cls in a stand-alone demo application. It uses a Unicode MessageBox call which helps illustrate Unicode support if you paste some Unicode filenames into it. Drag/drop is still ANSI however. But in reality this is almost never a problem for real applications and real users.
In answer to Hack, I was assuming that the user would identify the file he wanted by right click / copy in Windows Explorer.
I was hoping that there might be a very simple method in VB6 whereby the file path of a file placed thus on the clipboard might be determined.
The methods which LaVolpe and dilettante have kindly described, and the other threads/examples to which LaVolpe has pointed me (which I should have found myself using the search facility!) are, at my level of programming, complicated. I will take the next few days to read them all in detail and to try writing some code in a stand-alone little program.
However I feel that the simplest solution to what I want to do is to insert a new form with a Drive List box, a Directory List box and a File List box and in effect write a mini explorer package by means of which the user can navigate to and select the source file he wants (a bit like the browse option which is so often provided in program installation packages etc.).
Thank you all for your rapid replies. I will make a further post when I have digested them all, and the other LaVolpe references.
As dilettante pointed out, shame VB didn't include a nice easy way to get that info from the clipboard. But since they didn't, use of APIs is a solution even if it does feel a bit advanced for you. The more you code, you will eventually start to use APIs -- just a matter of time. APIs expand VB's capabilities immensely.
Insomnia is just a byproduct of, "It can't be done"
I have written and trial-tested my own little windows explorer look-alike. A few aspects of this were tricky for me - perhaps because my VB textbooks were less than explicit - but I got there.
A user can select a drive, a directory, any sub-directories and then any files in that directory or sub-directory(ies) and call them for incorporation into a VB6 program - in my case using the FileSystemObject to have VB copy the selected file into a VB specified location from which VB then acts upon the file content from its now known location. If need be, the type(s) of files listed for selection can be filtered using the FileN.Pattern property.
Doubtless such a program is fundamental to those using VB, so I do not think it worth attaching the code here.
As mentioned, I will in the next few days look in such detail as I am capable of at the codes and suggestions kindly sent to me, and will make a final post to close this thread.
I am going to mark this thread as resolved, and send thanks to those who kindly replied. It does seem a shame that it is so complicated to extract path information from a file or folder copied to the clipboard.
Hence I took what for me was a simpler path of using a Drive List, a Directory List and a File List and had the user navigate to the desired file through these. That enabled me to ascertain the precise path to the file.
A problem arose when this was used on computers having had their hard drives named other than plain c:,d:,e:, etc. It was necessary to parse out the C: from the full name which appeared in the Drive List Box (eg. C: (abcd) before using it to provide the path to the Dir List. Doubtless trivial stuff to you gurus, but a learning curve for me.
Perhaps I should have used a Common Dialog Box. but I found a solution and have learnt just a tad more about VB6.