Techwiki:Drag source

From ReactOS Wiki
Jump to: navigation, search

Techwiki:Main

non-OLE Drag source

From https://github.com/microsoft/winfile/issues/378#issuecomment-1464841379


DragObject() is the function that implements the dragging state and sends most of the messages. It's where all of the business logic about what dragging means is implemented. Note the caller specifies the type of the object as well as a caller allocated buffer describing the object. This function accepts two window handles. The first is the window that limits the scope of the drag; any drag outside of this window's bounds will be rejected. The second is the one processing window messages and driving the operation. It looks like the first was intended for MDI applications to restrict dragging to within themselves (using the frame window), although WinFile also uses GetDesktopWindow() in one call site, which is effectively disabling any restrictions on where the drag can go. Note that the later Windows 3.1 Drag & Drop API (which is really only a Drop API) would have required no restrictions on the applications that the drag could go to.


WM_QUERYDROPOBJECT is the message that determines whether a window can accept a drop. It is sent to the childmost window, and progressively up the parent chain, until any window indicates it can accept drops. FALSE indicates not accepting drop; TRUE indicates accepting drop with a default cursor; or it can return a mouse cursor handle to use, which implies willingness to accept drops. There's an important piece of magic here, which is the list box control populates dwControlData with the item within the list box corresponding to the mouse location, before deferring to the parent to decide whether to accept the drop.


WM_DRAGSELECT is used to indicate that a drag has entered or left a window. It is sent to the window that the mouse is navigating over, with a wParam of TRUE if a drag enters a window, FALSE if a drag is leaving a window.


WM_DRAGMOVE is sent if a drag is moving within the same window, as an alternative to WM_DRAGSELECT. WinFile is able to use the dwControlData mentioned above to highlight the list item being dragged over. Note that because only one of these is sent for any mouse movement, WM_DRAGSELECT ends up needing to invoke the same logic as WM_DRAGMOVE.


WM_DRAGLOOP is sent after WM_QUERYDROPOBJECT but before WM_DRAGSELECT or WM_DRAGMOVE. It is sent to the window that initiated the drag, indicating whether the drag is over a window that is willing to accept a drop. This is used to allow the window to modify the mouse cursor, and that seems to be the sole reason it exists. Note this leaves an ambiguity because both the drop window and initiating window get a chance to set the mouse cursor - there's no clear ownership about which window is responsible.


WM_DROPOBJECT is sent at the end of a successful drop to the window that is receiving the drop.


WM_BEGINDRAG is the most interesting, and looks unused. All of the five above are sent from DragObject(), but this is sent from a list box control to its parent window when the list box detects a motion that should be interpreted as a drag. In WinFile, and in other software of the era, this is instead performed by WM_LBTRACKPOINT which is sent from the list box to its parent when the mouse is clicked on an item. WinFile implements the logic of WM_BEGINDRAG via a GetMessage() loop in response to WM_LBTRACKPOINT (and its implementation is much simpler.)

Techwiki:Main