| Joined: Mar 2002 Posts: 1,273 DollarDNS Owner | OP DollarDNS Owner Joined: Mar 2002 Posts: 1,273 | This article describes something pretty darn advanced. I feel like a god for getting it working, so I just had to post it here just in case anybody would like to make use of my genius. ( I'm always the most concieted after an accomplishment) How is this trick useful?Well, the project I developed this for is a MP3 player/browser. Basically I want to create a windows folder which is MP3 enabled by having a built in player and display MP3 information. So this is one of many features which must work just like a real windows folder. I want the user to be able to copy files from my "mp3 folder" and paste those files into a windows folder. Also, I want to be able to copy files from a windows folder, and paste them into the mp3 folder. To do this, I must emulate window's technique. To my surprise, there was no API's that automated things. I had to get down and dirty and do things manually. Especially when copying files. NOTE: The below code only handles copy and pasting. It does not handle cutting. If you cut a file in a windows folder, the mp3 folder treats it like it was copied. Cutting is wierd, and I've yet to master it. To get the VB syntax for each of the below API and structures, download API-Viewer from www.allapi.net. The DROPFILES structure however cannot be found there, so I had to figure out the syntax myself. I've provided it for your convenience. Also, SetClipboardData isn't correct under windows 2k. AllAPI says it's Alias is 'SetClipboardDataA' but that doesn't exist. Remove the alias clause and it'll work fine. Not sure it it would under 9x though. Required API:IsClipboardFormatAvailable OpenClipboard GetClipboardData EmptyClipboard SetClipboardData CloseClipboard DragQueryFile GlobalAlloc GlobalLock GlobalUnlock CopyMemory Required STRUCTURES:POINTAPI Type DROPFILES pFiles As Long pt As POINTAPI fNC As Long fWide As Long End Type Required CONSTANTS:GMEM_MOVEABLE = &H2 GMEM_ZEROINIT = &H40 GMEM_DDESHARE = &H2000 | | | | Joined: Mar 2002 Posts: 1,273 DollarDNS Owner | OP DollarDNS Owner Joined: Mar 2002 Posts: 1,273 | Trick #1 - Copying filesStep 1: Store the list of full file paths into a string variable in the format of null terminated paths appended after each other followed by an extra null. Yes, that means there should be a double null at the end of the list. ((PATH + NULL ...) + NULL) Step 2: Create a DROPFILES structure variable. Set the pFiles to 20. pt to the POINTAPI structure set to 0's. fNC should be set to 0. fWide will be set to 1 if your file list variable is in UNICODE format, otherwise 0. Step 3: Use GlobalAlloc to get a handle to the chunk of memory you allocate. Make sure the length of it is the length of the DROPFILES structure (20) plus the length of your file list variable. Use LenB() function to get the byte length of your file list variable. The Len() function gets the character count of the variable - which is not what we want. In UNICODE each character is 2 bytes. Then save the pointer to this memory chunk with GlobalLock. Step 4: Now use CopyMemory to copy the DROPFILES structure into the first 20 bytes of your memory block. Then copy the file list right after it. Then use GlobalUnlock to allow other processes to access the memory chunk. Step 5: Now for the easy part. open the clipboard with OpenClipboard, then Empty it with EmptyClipboard. Use SetClipboardData to place the handle to your memory chunk into the clipboard. NOTE: Usually when you allocate a chunk of memory, you must free it afterwards if you don't want a memory leak in your program. However, you don't need to do it in this case. When somebody next calls EmptyClipboard, the memory chunk you created will be freed automatically. Example Code: Public Sub mnuCopy_Click()
Dim X As Integer, Files As String
Dim dp As DROPFILES, pt As POINTAPI
Dim hMem As Long, pMem As Long
Files = "c:\test1.txt" & vbNullChar & "C:\test2.txt" & vbNullChar & vbNullChar
'Allocate a chunk of memory and retrive its handle
hMem = GlobalAlloc(GMEM_ZEROINIT Or GMEM_MOVEABLE Or GMEM_DDESHARE, 20 + LenB(Files))
'Now we store the pointer to the chunk of memory
pMem = GlobalLock(hMem)
'The file list is an offset of 20 bytes from the beginning of the structure
dp.pFiles = 20
dp.pt = pt
dp.fNC = 0
'Now we indicate whether the file list is UNICODE or ANSI
dp.fWide = Abs(LenB(Files) > Len(Files))
'Copy the structure into the memory block
CopyMemory ByVal pMem, dp, 20
'Copy the file list after the structure
CopyMemory ByVal pMem + 20, ByVal StrPtr(Files), LenB(Files)
'Unlock the memory chunk
GlobalUnlock hMem
'The block of memory is ready to copy to the clipboard
If OpenClipboard(Me.hwnd) Then
EmptyClipboard
SetClipboardData CF_HDROP, hMem
CloseClipboard
Else
Debug.Print "Unable to open clipboard"
End If
End Sub | | | | Joined: Mar 2002 Posts: 1,273 DollarDNS Owner | OP DollarDNS Owner Joined: Mar 2002 Posts: 1,273 | Trick #2 - Pasting Files...Synopsis: This code is pretty straight-forward except that the DragQueryFile API is required to access the file list. After recieving the handle to the DROPFILES structure, you can use DragQueryFile to first get the file list, then accessing each item to first get the item length, then having the item stored in your buffer variable for processing. NOTE: This code treats cut and copied files the same. If you cut files in explorer, you'll only copy the files, not knowing you're supposed to move them... Public Sub mnuPaste_Click()
Dim hDrop As Long, Cnt As Long, X As Long, Buffer As String, Length As Long
If IsClipboardFormatAvailable(CF_HDROP) Then
If OpenClipboard(Me.hwnd) Then
hDrop = GetClipboardData(CF_HDROP)
If hDrop Then
'Set INDEX to FFFFFFFF to retrieve the file count
Cnt = DragQueryFile(hDrop, &HFFFFFFFF, vbNullChar, 0&)
For X = 0 To Cnt - 1
'Set LENGTH to 0 to retrieve the item length
Length = DragQueryFile(hDrop, X, vbNullChar, 0&)
Buffer = String(Length + 1, vbNullChar)
Length = DragQueryFile(hDrop, X, Buffer, Length + 1)
File = Left(Buffer, Length)
'Paste all copied files into the root directory
FileCopy File, "C:" & Left(File, InStrRev(File, "\"))
Next
EmptyClipboard
Else
Debug.Print "Failed to retrieve handle to drop structure"
End If
CloseClipboard
Else
Debug.Print "Failed to open clipboard"
End If
Else
Debug.Print "hDrop format unavailable"
End If
End Sub | | | | Joined: Mar 2002 Posts: 185 Member | Member Joined: Mar 2002 Posts: 185 | WTF. I believe you are some sort of god. I understood about half of what you just said, and just barely enough to use that code in a project if I needed it, but how the hell did you figure that out? I'm amazed. | | | | Joined: Mar 2002 Posts: 1,273 DollarDNS Owner | OP DollarDNS Owner Joined: Mar 2002 Posts: 1,273 | Takes experience. I wouldn't have figured it all out if I didn't know C. Most help content on the net about advanced stuff is in C/C++. I had to do a bit of translation. The 3rd thing you need to have is a good solid understanding of pointers - and how VB uses pointers. The only other trick I had to pull is translating the DROPFILES structure from C to VB syntax. To do that, you not only have to know the C datatypes, but you MUST think of those datatypes in terms of number of bytes. The HDROP type and BOOL types in C are both 4 byte numbers. LONG numbers in VB.
Example: CopyMemory ByVal pMem + 20, ByVal StrPtr(Files), LenB(Files)
Now in that API, the first field is the destination pointer, the second is the source pointer, and the 3rd is the number of bytes to copy.
Now, if I just plugged Files as the second field, then I'd be giving CopyMemory a pointer to the Files VARIABLE - NOT the Files STRING. So I had to say ByVal to input a raw number - And I used the StrPtr function to retrieve the STRING pointer inside of the string variable.
Pointers man, pointers rock. I'll post another tutorial about pointers. | | | | Joined: Mar 2002 Posts: 185 Member | Member Joined: Mar 2002 Posts: 185 | Sweet, I'd like a good tutorial on pointers! | | |
Posts: 860 Joined: March 2002
| | Forums41 Topics33,840 Posts68,858 Average Daily Posts0 | Members2,176 Most Online3,253 Jan 13th, 2020 | | | | | | | | | | | Doom 3 by Cyrez - 09/11/14 08:58 PM
| | | | | | | | | | | | | | | | | | |