WildByDesign Posted Monday at 12:37 AM Posted Monday at 12:37 AM 4 hours ago, MattyD said: I've added a crude example in the DragOver method on the droptarget. Obviously we should change the type/message based on the returned drageffect etc. This is incredible. I had no idea it was possible to customize it to that extent. MattyD 1
WildByDesign Posted Monday at 03:06 AM Posted Monday at 03:06 AM @MattyD There is a problem that I can't seem to solve and I've been trying for a couple of hours now. When you drag and drop back and forth within the Demo window, the InsertMark position is precise. If you drag and drop from File Explorer or Explorer++, the InsertMark is off position significantly. I've tried some things with _WinAPI_ScreenToClient which helped a bit. Interestingly, the positioning of the 3 parts (drag image, cursor and tooltip) are spaced apart quite differently. I completely ran out of ideas on solving this so I figured I would run it by you to see if you have some ideas.
MattyD Posted Monday at 11:28 AM Posted Monday at 11:28 AM 13 hours ago, WildByDesign said: but it seems to need DPI scaling set Its hard for me to do any meaningful testing around this sorry, occasionally I get a busted image regardless of the setting. I can't really see a pattern on my end FWIW. 8 hours ago, WildByDesign said: If you drag and drop from File Explorer or Explorer++, the InsertMark is off position significantly I think this is probably a side effect of that SetThreadDpiAwarenessContext line - does commenting it out fix things? WildByDesign 1
WildByDesign Posted Monday at 12:00 PM Posted Monday at 12:00 PM (edited) 33 minutes ago, MattyD said: I think this is probably a side effect of that SetThreadDpiAwarenessContext line - does commenting it out fix things? You just saved me some time and some sanity. Commenting out the line fixed it. So then I decided to switch from SetThreadDpiAwarenessContext to SetProcessDpiAwarenessContext and it behaves perfectly. We get the sharp DPI plus all of the coordinates match up as they should. Thank you. ; DPI awareness DllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", @AutoItX64 ? "int64" : "int", -2) This works correctly with your InsertMark code and works correctly with my DROPHILITE code in Files Au3. It solves the issue with the drag images not appearing on the first drag after GUI startup. Although, I understand that you still have some issue with drag image unfortunately. Although now that I think of it, I have seen File Explorer itself show the occasional blank drag image. So it must be a bug in Windows drag manager. By the way, I have a feeling that the custom drag image code that @jugador shared would probably alleviate this issue because it creates and manages its own drag image. It would likely fix the consistency problem. However, I found that the icons that it pulled to create the drag image would often be grainy because they have to upscale (plus maybe DPI related). Although using the built in drag images is more consistent with the OS. What about toggling the visibility of the drag image on DragEnter? Particularly, if you could only do that once to "wake it up" or something. At least to fix that first drag image blank. $oIDropTgtHelper.Show(False) $oIDropTgtHelper.Show(True) Edited Monday at 12:01 PM by WildByDesign
MattyD Posted Monday at 02:15 PM Posted Monday at 02:15 PM (edited) Yeah I'm not too concerned - It's good enough for now I think. Anyway, a bit more messing around today... We can do multi-files via relative IDLs, as @jugador's demonstrated with the GetDataObjectOf_B implementation. And this make perfect sense for our scenario where "C:\Users\[User]\Desktop" is the descendant for all files in the list. But say we wanted to add a file from a sibling directory (say the documents folder). Then we need find a common parent and recalculate all the child paths from the new shellfolder. - We cant use ".." for relative directories here. The "Desktop" folder object is essentially the root of everything though, (not to be confused with the path above!). So when using this as a parent, we can generate child IDLs by using normal file paths "C:\blah\myfile.txt". Both techniques will probably have their uses... Otherwise there's always the option to craft the HDROP manually - a la GetDataObjectOf_C ...PS Also added in some "move" logic FWIW, so items aren't duplicated all the time when being dragged around the list. _Demo2.zip Edited Monday at 02:25 PM by MattyD quick bugfix WildByDesign 1
jugador Posted Monday at 07:21 PM Posted Monday at 07:21 PM (edited) https://www.autoitscript.com/forum/topic/213423-how-to-drag-out-element-inside-a-listview-to-windows-explorer/page/3/#comment-1549526 I have updated the DragDrop.au3 code in the link above: 1) Simplified Logic for better readability. 2) Fixed an issue where the IDropSourceNotify method was not being called during file dragging. While this method isn't strictly required for the script to function, but still fixed the bug. 3) Resolved a crash that occurred when dragging an item from the ListView and dropping it back onto the same ListView. Edited Monday at 07:25 PM by jugador WildByDesign 1
WildByDesign Posted Tuesday at 01:13 AM Posted Tuesday at 01:13 AM 10 hours ago, MattyD said: ...PS Also added in some "move" logic FWIW, so items aren't duplicated all the time when being dragged around the list. I was thinking about this earlier when playing around with your latest demo. It made me start to wonder about how we are supposed to handle the actual file copying and moving the files on disk. For example, let's assume that the TreeView in your Demo is a separate directory from the ListView. Something like "C:\Users\[User]\Desktop\FolderA" and "C:\Users\[User]\Desktop\FolderB". Another thing that I don't quite understand is how we report back to the system drag manager whether it's the same drive or not. For example, dragging and dropping a file within the same drive is going to go with DROPEFFECT_MOVE, while dragging a file from one drive to another is going to go with DROPEFFECT_COPY.
MattyD Posted Tuesday at 09:19 AM Posted Tuesday at 09:19 AM (edited) We just need to sort out our logic in the drop target. If we want to move files around our options are: An "optimized" Move (original is deleted by the target). On "Drop", the target moves the file and "deletes" the original. The target then sets the dropeffect to anything but DROPEFFECT_MOVE (e.g. DROPEFFECT_NONE , or DROPEFFECT_COPY) The CFSTR_PERFORMEDDROPEFFECT entry on the dataobj is set to DROPEFFECT_NONE (we're not doing this atm) This method typically behaves more to your point, where the target wouldn't physically move the file on disk. It'd just declare that it now lives in a different directory via calling IFileOperation::MoveItem(). We could still physically copy a file, delete the original and call it a day too. But, for that method we'd traditionally perform: An "unoptimized" move (original is deleted by the source). On "Drop", the target copies the file. The target sets the dropeffect to DROPEFFECT_MOVE the CFSTR_PERFORMEDDROPEFFECT format identifier set to DROPEFFECT_MOVE (we're not doing this atm) DROPEFFECT_MOVE is in turn returned by DoDragDrop, which signals that the source should delete the original. But the shell also checks the CFSTR_PERFORMEDDROPEFFECT entry in the data object - just to ensure that we mean it! Edit: Call this from IDropTarget::Drop to set the CFSTR_PERFORMEDDROPEFFECT entry on the data object. (use with caution - you don't want to accidentally delete files!) Func __SetPerformedDropEffect($pDataObject, $iDropEffect) Local $tFormatEtc = DllStructCreate($tagFORMATETC) $tFormatEtc.cfFormat = _ClipBoard_RegisterFormat($CFSTR_PERFORMEDDROPEFFECT) $tFormatEtc.ptd = 0 $tFormatEtc.aspect = $DVASPECT_CONTENT $tFormatEtc.index = -1 $tFormatEtc.tymed = $TYMED_HGLOBAL Local $hGblMem = _MemGlobalAlloc(4, $GPTR) Local $pDropEffect = _MemGlobalLock($hGblMem) Local $tDropEffect = DllStructCreate("dword iEffect", $pDropEffect) $tDropEffect.iEffect = $iDropEffect _MemGlobalUnlock($hGblMem) Local $tStgMedium = DllStructCreate($tagSTGMEDIUM) $tStgMedium.tymed = $TYMED_HGLOBAL $tStgMedium.handle = $hGblMem $tStgMedium.pUnkForRelease = 0 Local $oDataObj = ObjCreateInterface($pDataObject, $sIID_IDataObject, $tagIDataObject) $oDataObj.AddRef() $oDataObj.SetData($tFormatEtc, $tStgMedium, 1) EndFunc Edited Tuesday at 09:46 AM by MattyD WildByDesign 1
WildByDesign Posted Tuesday at 06:41 PM Posted Tuesday at 06:41 PM 9 hours ago, MattyD said: This method typically behaves more to your point, where the target wouldn't physically move the file on disk. It'd just declare that it now lives in a different directory via calling IFileOperation::MoveItem(). I know that I've said this before, but you've got very good skills when it comes to teaching. I appreciate the way that you broke down all of that information. Thank you. I have spent some time each day over the past week reading various msdn docs but never really got myself in the right direction for this. Once you mentioned CFSTR_PERFORMEDDROPEFFECT in your comment, that has helped narrow down what I need to read on msdn. 9 hours ago, MattyD said: Edit: Call this from IDropTarget::Drop to set the CFSTR_PERFORMEDDROPEFFECT entry on the data object. (use with caution - you don't want to accidentally delete files!) Thank you for this. I have to admit, I feel quite overwhelmed and not entirely understanding everything. Your code is tidy (always) and you explain things very well. It's just (what I assume to be) some pretty complex OS stuff that I don't fully understand the inner workings of it. I feel like we are close to the finish line with this but I feel like I don't have a good enough understanding of how to proceed with the CFSTR_PERFORMEDDROPEFFECT part. If you have time, would you be willing to have a look at the latest Files Au3 sources and potentially help the project with this? If we are going in a much different direction from the OP issue here and what you want out of your Demo example, please feel free to have some of this conversation over in the Files Au3 thread if you feel it would be more appropriate there. I have updated the shell-dodragdrop branch with the very latest code from your most recent example. Everything dragged out into File Explorer is working great. It's only stuff being dragged in (or from it's own TreeView/ListView). Visually, everything is good and in place. The drag image tooltip messages and so on. It's just the CFSTR_PERFORMEDDROPEFFECT part with IFileOperation methods that is lacking.
MattyD Posted 18 hours ago Posted 18 hours ago All good. @Netol is any of this beneficial to what you're doing? We can jump into another thread if not! 14 hours ago, WildByDesign said: If you have time, would you be willing to have a look at the latest Files Au3 sources and potentially help the project with this? I probably won't work directly on the Files.au3 project sorry. Nothing personal, I'll just turn into a control freak and end up offending someone 😮. But I'm happy to keep working on this one step removed - and you'll have the freedom to pick and choose what you wish to incorporate. WildByDesign 1
WildByDesign Posted 16 hours ago Posted 16 hours ago 1 hour ago, MattyD said: I probably won't work directly on the Files.au3 project sorry. Nothing personal, I'll just turn into a control freak and end up offending someone 😮. That is completely understandable. I am just thankful for everything that you have done (and continue to do) for the AutoIt community. You are always willing to help people here even on the more difficult issues. And everything that you've created and shared with the community. So many things that weren't available here yet until you made it happen. That is all greatly appreciated. 2 hours ago, MattyD said: But I'm happy to keep working on this one step removed - and you'll have the freedom to pick and choose what you wish to incorporate. I appreciate that as well. You open up so many possibilities here for other community members to use, grow and modify into their own direction. Cheers! SOLVE-SMART 1
WildByDesign Posted 14 hours ago Posted 14 hours ago (edited) On 2/2/2026 at 9:15 AM, MattyD said: ...PS Also added in some "move" logic FWIW, so items aren't duplicated all the time when being dragged around the list. _Demo2.zip I noticed an issue with your most recent Demo. It's possible that it is intended but it's a change in behaviour from the previous demos. Drag from your ListView to a test folder in File Explorer and it always does DROPEFFECT_LINK Drag from your TreeView to a test folder in File Explorer and it will do DROPEFFECT_MOVE or whichever you have set Dragging from TreeView seems to work as it had before in previous demos. It seems to only be the ListView that always uses DROPEFFECT_LINK regardless of what is being set. I'm digging into the code a bit now. EDIT: My initial thought is that the issue must be coming from the newer GetDataObjectOfFiles() function that the ListView uses because I had just switched over to that function from @jugador's GetDataObjectOfFile_B() function this morning. That might also explain why the TreeView is not affected since it uses the GetDataObjectOfFile() function. EDIT2: Confirmed. I just switched briefly to GetDataObjectOfFile_B() and the issue is gone. So my suspicion of the issue being in the GetDataObjectOfFiles() function must be correct. I have had a look at that function but I just don't know how (or where) the effects are handled (or not). Edited 14 hours ago by WildByDesign
WildByDesign Posted 13 hours ago Posted 13 hours ago On 2/3/2026 at 4:19 AM, MattyD said: This method typically behaves more to your point, where the target wouldn't physically move the file on disk. It'd just declare that it now lives in a different directory via calling IFileOperation::MoveItem(). For reference (and so I don't forget later), @Danyfirex has a really nice implementation of IFileOperation that uses the shell to handle all of the file I/O along with the typical progress bar and all. Danyfirex 1
WildByDesign Posted 2 hours ago Posted 2 hours ago Just a quick update: IFileOperation::CopyItems and IFileOperation::MoveItems seem to work perfectly well with our IDataObject. Whether it's a single file or many. I'm just messing around with it some more but so far it is working very well.
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