WildByDesign Posted Sunday at 02:45 PM Posted Sunday at 02:45 PM 3 hours ago, WildByDesign said: Matty, may I please have your permission to use this code in the Files Au3 file manager project? For curiosity sake, I tested it out there briefly. It allowed me to drag and drop nicely from the ListView but also the TreeView as well once I modified the code slightly. @MattyD Sorry to load you up on comments here. The wheels of thought keep on spinning. One thing that I've found to be problematic about this whole DoDragDrop functionality is that it doesn't allow AutoIt to perform any other functions until the drop is complete. I assume that this has something to do with AutoIt not having multiple thread support. For example, in Files Au3 in the previous drag and drop code, I have some code that takes care of bringing up the drop highlightiing of the TreeView items and ListView items as the cursor hovers over them to give the user a better idea of where they are dropping. But this doesn't seem to work with the DoDragDrop method. Nothing from the main While loop executes either. This drag and drop stuff is certainly complicated.
WildByDesign Posted Sunday at 02:48 PM Posted Sunday at 02:48 PM 3 minutes ago, MattyD said: Supposedly it's meant to make working with drag images easier too. (if we want more than that cursor with the little plus-in-a-box). Speaking of this, I have never had any success in creating any drag images with treeview or listview. There are only about 10-12 previous examples for this in the forum and none of them seem to work either. Nor the examples from the AutoIt help files. I wanted to create a drag image of the file type, for example, but was never successful with that unfortunately.
MattyD Posted Sunday at 03:17 PM Posted Sunday at 03:17 PM 5 minutes ago, WildByDesign said: it doesn't allow AutoIt to perform any other functions until the drop is complete Yep, we're in a loop until DoDragDrop returns. But, the GiveFeedback method is called as part of that loop - so maybe just hook into that for the short term . I think the proper way (from a very superficial look) is to setup a DropTarget object which is supposed to help with insertion marks for listviews. Not sure how that looks for a treeview, but its probably worth reading up on. 12 minutes ago, WildByDesign said: I have never had any success in creating any drag images with treeview or listview Ok, I'll add that to the list of things to investigate. WildByDesign 1
WildByDesign Posted Monday at 12:08 AM Posted Monday at 12:08 AM (edited) 8 hours ago, MattyD said: I think the proper way (from a very superficial look) is to setup a DropTarget object which is supposed to help with insertion marks for listviews. I spent some time looking into this today but I didn't fully understand how to create the DropTarget. 8 hours ago, MattyD said: But, the GiveFeedback method is called as part of that loop - so maybe just hook into that for the short term . This does work pretty good for now. You've created some great structure with the __Mthd_GiveFeedback, __Mthd_DragEnterTarget and __Mthd_DragLeaveTarget functions. I'm using a combination of those right now to determine the handle of which ListView or TreeView I am currently hovering over and making the necessary drophilite changes. It may not be the proper way to do it but it seems to be working well enough. Edited Monday at 12:09 AM by WildByDesign MattyD 1
jugador Posted Monday at 11:38 AM Posted Monday at 11:38 AM @MattyD Will this work for creating an IDataObject? I don't know, as I haven't tried it. Create a blank IDataObject using SHCreateDataObject, and then fill it using SetData. Func __SHCreateDataObject($tIID_IDataObject, $ppidlFolder = 0, $cidl = 0, $papidl = 0, $pdtInner = 0) Local $aRes = DllCall("shell32.dll", "long", "SHCreateDataObject", _ "ptr", $ppidlFolder, _ "uint", $cidl, _ "ptr", $papidl, _ "ptr", $pdtInner, _ "struct*", $tIID_IDataObject, _ "ptr*", 0) If @error Then Return SetError(1, 0, $aRes[0]) Return $aRes[6] EndFunc Local $sIID_IDataObject = "{0000010E-0000-0000-C000-000000000046}" Local $triid = _WinAPI_GUIDFromString($sIID_IDataObject) Local $pIDataObject = __SHCreateDataObject($triid, 0, 0, 0, 0) ;~ blank IDataObject Local Const $tag_IDataObject = _ "GetData hresult(ptr;ptr*);" & _ "GetDataHere hresult(ptr;ptr*);" & _ "QueryGetData hresult(ptr);" & _ "GetCanonicalFormatEtc hresult(ptr;ptr*);" & _ "SetData hresult(ptr;ptr;bool);" & _ "EnumFormatEtc hresult(dword;ptr*);" & _ "DAdvise hresult(ptr;dword;ptr;dword*);" & _ "DUnadvise hresult(dword);" & _ "EnumDAdvise hresult(ptr*);" Local $oIDataObject = ObjCreateInterface($pIDataObject, $sIID_IDataObject, $tag_IDataObject) $tFORMATETC = _Create_FORMATETC() $tSTGMEDIUM = _Create_STGMEDIUM_FileData($s_FilePath) $oIDataObject.SetData(DllStructGetPtr($tFORMATETC), DllStructGetPtr($tSTGMEDIUM), 1) ;~ fill IDataObject MattyD 1
WildByDesign Posted Monday at 01:27 PM Posted Monday at 01:27 PM (edited) On 1/23/2026 at 10:52 PM, MattyD said: There seems to be a drag-drop mechanism baked into AutoIt's message handling I noticed that you had to comment out Opt("GUICloseOnESC", 0) in your example. That baked in drag-drop mechanism is definitely problematic. You would typically want that Esc key available to cancel the operation. Since I use OnEventMode for the majority of my projects, I decided to test Opt("GUIOnEventMode", 1) with your Demo example. I was expecting it to fail anyway. As expected, it also fails which is unfortunate. I think it's safe to assume that any of the Opt("GUI...") options will not work. If you do end up thinking of a way to disable that baked in AutoIt drag-drop functionality without losing out on the Opt("GUI...") options or if you find a way to stop the built in drag-drop functionality from getting left in drag mode as Nine mentioned as well, please let me know. Obviously, your subclassing fixes all of that. But I'm not certain that losing the Opt("GUI...") options is worth it. EDIT: I think that I may have figured it out. Or at least a workaround. Case $LVN_BEGINDRAG Return 1 ; or Return 0 As we know, $LVN_BEGINDRAG is not supposed to have a return value. However, I've just tested and it does cancel the built in drag operation while the DoDragDrop operation continues. I don't fully understand all of the ramifications from this. However, in my own testing, both Return 0 and Return 1 work beautifully and solves the issue on my end. EDIT2: The best way to test this is with @MattyD's first Demo example where he had not yet subclassed the GUI. Return ; fails, Return 0 ; works Return 1 ; works Edited Monday at 01:55 PM by WildByDesign MattyD 1
WildByDesign Posted Monday at 02:06 PM Posted Monday at 02:06 PM @Nine Can you please test (above) with MattyD's first example and let me know if it fixes the "dinging" issue as well? Thanks
MattyD Posted Monday at 09:37 PM Posted Monday at 09:37 PM (edited) 10 hours ago, jugador said: Will this work for creating an IDataObject? yep, seems like that should work. Thank you - that's going to save a bunch of time! 8 hours ago, WildByDesign said: Return ; fails, Return 0 ; works Return 1 ; works Also great pickup, yes this makes more sense than subclassing: Return 0 from WM_DROPFILES Return 0 from WM_NOTIFY when its a $LVN_BEGINDRAG or $LVN_BEGINRDRAG, otherwise return $GUI_RUNDEFMSG.. Edit: 8 hours ago, WildByDesign said: I noticed that you had to comment out Opt("GUICloseOnESC", 0) in your example nah, I didn't have to - It just doesn't serve a purpose when we're bypassing all the autoIt handlers in the window proc . The esc key can't close the window if we break the mechanism! Edited Monday at 09:45 PM by MattyD
WildByDesign Posted Tuesday at 03:59 PM Posted Tuesday at 03:59 PM @MattyD I have a question for you regarding the cursor from DRAGDROP_S_USEDEFAULTCURSORS. Outside of this DoDragDrop function, do you know of any way to obtain the handle for that drag/drop cursor that is returned by DRAGDROP_S_USEDEFAULTCURSORS? I am just curious about trying some things with _WinAPI_SetSystemCursor function or other similar functions. Thanks.
WildByDesign Posted yesterday at 12:51 AM Posted yesterday at 12:51 AM After a lot of trial and error, I finally got the proper OS drag image working and it has the built-in tooltip. Part of the problem was that it doesn't work when the script runs as x86. It seems to be 64-bit only. I used the function from @ProgAndy's older script and modified it to work with your Demo example. ; Call function with: ; _SHDoDragDrop($hGUI, $pDataObj, $pDropSource, BitOR($DROPEFFECT_COPY,$DROPEFFECT_LINK)) Func _SHDoDragDrop($hWnd, ByRef $pDataObj, ByRef $pDropSource, $dwDropEffects) Local $result = DllCall("shell32.dll","lresult","SHDoDragDrop", "hwnd", Null, "ptr", $pDataObj,"ptr", Null, "dword", BitOR($DROPEFFECT_COPY,$DROPEFFECT_LINK), "dword*", 0) EndFunc The real trick that ended up making it work was the Null for hWnd and the Null for drop source. Since with SHDoDragDrop, the OS will take care of both of those. In the end, we get the same beautiful drag image (with tooltip) that File Explorer uses that shows the file type icon. The tooltip shows whether the file is being copied or moved and to which directory the cursor is hovering over. This makes everything so much easier.
Netol Posted yesterday at 04:12 AM Author Posted yesterday at 04:12 AM On 1/23/2026 at 8:23 AM, MattyD said: Ok needs a bit of a cleanup - But its kinda working __Demo.zip 7.44 kB · 13 downloads Thanls a lot. This code working fine only drag and drop element to outside but not permit drag and drop files inside of the listview
WildByDesign Posted 21 hours ago Posted 21 hours ago (edited) 9 hours ago, Netol said: This code working fine only drag and drop element to outside but not permit drag and drop files inside of the listview We can always handle the WM_DROPFILES messages for that. However from my understanding, it would be better to register the window (and specific controls?) as drop targets with the RegisterDragDrop and handle the various methods by return certain effects. The developer for Explorer++ suggests: (from source and source) Quote // The main window is registered as a drop target only so that the drag image will be // consistently shown when an item is being dragged. For the drag image to be shown, the // relevant IDropTargetHelper methods need to be called during the drag. To do that, the window // under the mouse needs to be registered as a drop target. // Rather than having to register every window, the top-level window can simply be registered // instead. That way, it will act as a fallback if there isn't a more specific child window // registered. So that explains why we cannot see the drag image on our own window. The problem where I am right now is that I don't know how to setup an IDropTarget interface. EDIT: Looks like we really need an IDropTargetHelper interface if we want to show the drag image over our own window. Edited 19 hours ago by WildByDesign
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now