|
-
Aug 29th, 2022, 04:24 AM
#1
[twinBASIC] Explorer-style Drag-Drop Images with tB-defined x86+x64 interfaces
A while back I posted this project:
[VB6] Register any control as a drop target that shows the Explorer drag image

Dragging from Explorer |

Dragging from Firefox |
I wanted to try my hand at using these interfaces in x64 apps. A 64-bit version of oleexp doesn't seem likely; there's seemingly insurmountable barriers to using midl with a project that needs to redefine things in the force-included headers, and the original types weren't preserved so every single interface would have to be manually reviewed and updated if it uses pointer types. But, twinBASIC lets you define interfaces as a native language feature. So I set about re-implementing all the necessary ones for this project:
Code:
[ InterfaceId ("4657278B-411B-11D2-839A-00C04FD918D0") ]
Interface IDropTargetHelper Extends stdole.IUnknown
Sub DragEnter(ByVal hwndTarget As LongPtr, ByVal pDataObject As DragDropDemo.IDataObject, ppt As POINT, ByVal dwEffect As DROPEFFECTS)
Sub DragLeave()
Sub DragOver(ppt As POINT, ByVal dwEffect As DROPEFFECTS)
Sub Drop(ByVal pDataObject As DragDropDemo.IDataObject, ppt As POINT, ByVal dwEffect As DROPEFFECTS)
Sub Show(ByVal fShow As Long)
End Interface
[ InterfaceId ("DE5BF786-477A-11D2-839D-00C04FD918D0") ]
Interface IDragSourceHelper Extends stdole.IUnknown
Sub InitializeFromBitmap(pshdi As SHDRAGIMAGE, pDataObject As DragDropDemo.IDataObject)
Sub InitializeFromWindow(ByVal hwnd As LongPtr, ppt As POINT, pDataObject As DragDropDemo.IDataObject)
End Interface
[ InterfaceId ("83E07D0D-0C5F-4163-BF1A-60B274051E40") ]
Interface IDragSourceHelper2 Extends IDragSourceHelper
Sub SetFlags(ByVal dwFlags As DSH_FLAGS)
End Interface
[ InterfaceId ("00000122-0000-0000-C000-000000000046") ]
Interface IDropTarget Extends stdole.IUnknown
Sub DragEnter(ByVal pDataObject As DragDropDemo.IDataObject, ByVal grfKeyState As Long, ByVal pt As LongLong, dwEffect As DROPEFFECTS)
Sub DragOver(ByVal grfKeyState As Long, ByVal pt As LongLong, pdwEffect As DROPEFFECTS)
Sub DragLeave()
Sub Drop(ByVal pDataObj As DragDropDemo.IDataObject, ByVal grfKeyState As Long, ByVal pt As LongLong, pdwEffect As DROPEFFECTS)
End Interface
[ InterfaceId ("00000121-0000-0000-C000-000000000046") ]
Interface IDropSource Extends stdole.IUnknown
Sub QueryContinueDrag(ByVal fEscape As Long)
Sub GiveFeedback(ByVal grfKeyState As Long)
End Interface
[ InterfaceId ("0000010f-0000-0000-C000-000000000046") ]
Interface IAdviseSink Extends stdole.IUnknown
Sub OnDataChange(pFormatEtc As FORMATETC, pStgMed As STGMEDIUM)
Sub OnViewChange(dwAspect As DVASPECT, ByVal lindex As Long)
Sub OnRename(ByVal pmk As LongPtr) 'As IMoniker
Sub OnSave()
Sub OnClose()
End Interface
[ InterfaceId ("00000103-0000-0000-C000-000000000046") ]
Interface IEnumFormatETC Extends stdole.IUnknown
Sub Next(ByVal celt As Long, rgelt As FORMATETC, pceltFetched As Long)
Sub Skip(ByVal celt As Long)
Sub Reset()
Sub Clone(ppEnum As DragDropDemo.IEnumFormatETC)
End Interface
[ InterfaceId ("00000105-0000-0000-C000-000000000046") ]
Interface IEnumSTATDATA Extends stdole.IUnknown
Sub Next(ByVal celt As Long, rgelt As STATDATA, pceltFetched As Long)
Sub Skip(ByVal celt As Long)
Sub Reset()
Sub Clone(ppEnum As DragDropDemo.IEnumSTATDATA)
End Interface
[ InterfaceId ("0000010E-0000-0000-C000-000000000046") ]
Interface IDataObject Extends stdole.IUnknown
Sub GetData(pFormatEtcIn As FORMATETC, pMedium As STGMEDIUM)
Sub GetDataHere(pFormatEtc As FORMATETC, pMedium As STGMEDIUM)
Sub QueryGetData(pFormatEtc As FORMATETC)
Sub GetCanonicalFormatEtc(pFormatEtcIn As FORMATETC, pFormatEtcOut As FORMATETC)
Sub SetData(pFormatEtc As FORMATETC, pMedium As STGMEDIUM, ByVal fRelease As Long)
Function EnumFormatEtc(ByVal dwDirection As DATADIR) As DragDropDemo.IEnumFormatETC
Sub DAdvise(pFormatEtc As FORMATETC, ByVal advf As ADVF, pAdvSink As DragDropDemo.IAdviseSink)
Sub DUnadvise(ByVal dwConnection As Long)
Function EnumDAdvise() As DragDropDemo.IEnumSTATDATA
End Interface
'CLSID_DragDropHelper
[ CoClassId ("4657278A-411B-11D2-839A-00C04FD918D0") ]
CoClass DragDropHelper
[ Default ] Interface IDropTargetHelper
Interface IDragSourceHelper
Interface IDragSourceHelper2
End CoClass
I used functions for some to preserve as much compatibility as possible with oleexp-using code.
There were a couple tricky things here... it's always been an odd interface. Normally, UDTs as [in] are ByRef; MSDN lists the x,y coords as POINT, and we had to expand that to 2 ByVal Long's in x86. It's even weirder in x64; we have to use a single member, but it's also ByVal... so it's 8 bytes but not *actually* a pointer, so it's handled like this:
Code:
Private Sub IDropTarget_DragEnter(ByVal pDataObj As DragDropDemo.IDataObject, ByVal grfKeyState As Long, ByVal pt As LongLong, pdwEffect As DragDropDemo.DROPEFFECTS)
Dim ptt As DragDropDemo.POINT
CopyMemory ptt, pt, LenB(ptt)
Since LongLong is available on x86 too, we can still use one definition, if a slightly more complicated CopyMemory call is used for both.
Also, lots of things are fully qualified as there's currently an issue with conflicting types in the WinNativeForms package that are exposed to users.
But besides those quirks, the code works on x64 without major change, just updating to LongPtr where needed, and replacing the PictureBox with a Frame until that's available.
Et voilà:

Requirements
Windows Vista or newer
twinBASIC Beta 167 or newer
Thanks to twinBASIC developer Wayne Phillips for his help getting this working, and of course for the continuing great work on twinBASIC itself 
Update: I've added DragDropDemoWDL.twinproj that uses WinDevLib for interfaces/APIs. WDL uses proper ByVal UDTs instead of hacks and has minor API signature differences due to stricter standards for SDK compatibility. The original project is left up as an intro to defining interfaces yourself in tB.
(Project update: v5 adds force registration option to Attach to unregister an existing drop target. Primarily to sync with the VB6 version, as tB doesn't currently have the bug where it registers dragdrop for a form with windowless UC where neither enable dragdrop.
(Project update: v4 suppresses errors from TotalCommander and others in the DragDropHelper object since file names can usually still be retrieved.
(Project update: V2.1 updates to use Coclass syntax, requires twinBASIC Beta 167 or newer)
Project update: V2 unifies the declarations to use LongLong for the POINT on both x86 and x64, and corrects the definition of IEnumSTATDATA.Next.
Project update: Updated to use new Coclass syntax
Download latest version on GitHub.
Last edited by fafalone; May 2nd, 2026 at 11:10 PM.
-
Nov 4th, 2022, 11:18 AM
#2
Re: [twinBASIC] Explorer-style Drag-Drop Images with tB-defined x86+x64 interfaces
twinBASIC now supports Coclass syntax! Project updated to use it.
Requires Beta 167 or newer.
-
May 2nd, 2026, 07:07 PM
#3
Re: [twinBASIC] Explorer-style Drag-Drop Images with tB-defined x86+x64 interfaces
oleexp.tlb,Its handle defines a length of 4 bytes long. In fact, the best way is to change it to longptr, but VB6 can't recognize it.
One way is to write a plugin in VB6 that automatically converts longptr to long when Tr P loads.
Another way is. Recompile an oleexp-x64.tlb
The IDL source code is basically the same, but the handle type attribute and the parameter will be changed to the long long type.
-
May 2nd, 2026, 11:12 PM
#4
Re: [twinBASIC] Explorer-style Drag-Drop Images with tB-defined x86+x64 interfaces
It's not a simple task to compile oleexp.tlb as 64bit; even beyond the fact you'd need to use midl instead of mktyplib and I couldn't get it to work after many hours due to technical issues, there's hundreds if not thousands of places I hard coded long instead of a type alias. Every interface would have to be rechecked and hundreds fixed.
This is why I say everywhere to switch oleexp.tlb projects to WinDevLib in twinBASIC. The compatibility issues are minor and the tB compiler will catch 99% of them as design-time errors. You can use #If TWINBASIC Then blocks to support code shared between VB6/oleexp and tB/WDL where it's not compatible. WDL includes 100% of what's in oleexp.tlb plus hundreds more interfaces and over 10,000 more APIs.
oleexp.tlb is not suitable for 64bit conversion, the project is deprecated, and I will not be making a 64bit version.
PS- This project predates WDL and was originally intended to demonstrate how to define COM interfaces in tB. It doesn't use WDL and has better oleexp.tlb compatibility. I've added DragDropDemoWDL.twinproj to the repo which uses WDL for the interface/API defs.
Last edited by fafalone; May 2nd, 2026 at 11:54 PM.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|