Dragging a shell object, part 3: Detecting an optimized move

Date:December 8, 2004 / year-entry #413
Tags:code
Orig Link:https://blogs.msdn.microsoft.com/oldnewthing/20041208-00/?p=37093
Comments:    4
Summary:We were considering how to detect that the drag/drop operation resulted in a conceptual Move even if the DROPEFFECT_MOVE was optimized away. If the drop target is the shell, you can query the data object for CFSTR_PERFORMEDDROPEFFECT to see what the performed effect was. void OnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags)...

We were considering how to detect that the drag/drop operation resulted in a conceptual Move even if the DROPEFFECT_MOVE was optimized away.

If the drop target is the shell, you can query the data object for CFSTR_PERFORMEDDROPEFFECT to see what the performed effect was.

void OnLButtonDown(HWND hwnd, BOOL fDoubleClick,
                   int x, int y, UINT keyFlags)
{
  ...
        if (dwEffect & DROPEFFECT_MOVE) {
          DeleteFileW(wszPath);
        }
        CheckPerformedEffect(hwnd, pdto);
  ...
}

Of course, we need that CheckPerformedEffect function too.

void CheckPerformedEffect(HWND hwnd, IDataObject *pdto)
{
  FORMATETC fe = {
     (CLIPFORMAT)RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT),
     NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  STGMEDIUM stgm;
  if (SUCCEEDED(pdto->GetData(&fe, &stgm))) {
    if ((stgm.tymed & TYMED_HGLOBAL) &&
        GlobalSize(stgm.hGlobal) >= sizeof(DWORD)) {
       DWORD *pdw = (DWORD*)GlobalLock(stgm.hGlobal);
       if (pdw) {
         if (*pdw == DROPEFFECT_MOVE) {
            MessageBox(hwnd, TEXT("Moved"), TEXT("Scratch"), MB_OK);
         }
         GlobalUnlock(stgm.hGlobal);
       }
    }
    ReleaseStgMedium(&stgm);
  }
}

If the item is dropped on a shell window, the drop target will set data into the data object under the clipboard format name CFSTR_PERFORMEDDROPEFFECT. The data takes the form of a DWORD in an HGLOBAL, and the value is the actual drop effect before any optimizations kicked in.

Here, we check whether it was a DROPEFFECT_MOVE and display a special message if so.


Comments (4)
  1. Jay Lauffer says:

    Ahh now this is a gem.

    However after doing some additional reading I find myself confused by MSDN documentation (and no this isn’t the first time).

    http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/programmersguide/shell_basics/shell_basics_programming/transferring/clipboard.asp?frame=true

    —————————————–

    The CFSTR_PERFORMEDDROPEFFECT format identifier was intended to allow the target to indicate to the data object what operation actually took place. However, the Shell uses optimized moves for file system objects whenever possible. In that case, the Shell normally sets the CFSTR_PERFORMEDDROPEFFECT value to DROPEFFECT_NONE, to indicate to the data object that the original data has been deleted. Thus, the source cannot use the CFSTR_PERFORMEDDROPEFFECT value to determine which operation has taken place. While most sources do not need this information, there are some exceptions. For instance, even though optimized moves eliminate the need for a source to delete any data, the source might still need to update a related database to indicate that the files have been moved or copied.

    ——————————————

    Of course that claims to be for Version 5..

    a little below we then get some more documentation which fails to clarify anything

    ——————————————-

    CFSTR_PERFORMEDDROPEFFECT

    This format identifier is used by the target to inform the data object through its IDataObject::SetData method of the outcome of a data transfer. The data is an STGMEDIUM structure that contains a global memory object. The structure’s hGlobal member points to a DWORD set to the appropriate DROPEFFECT value, normally DROPEFFECT_MOVE or DROPEFFECT_COPY.

    This format is normally used when the outcome of an operation can be either move or copy, such as in anoptimized move or delete-on-paste operation. It provides a reliable way for the target to tell the data object what actually happened. It was introduced because the value of pdwEffect returned by DoDragDrop did not reliably indicate which operation had taken place. The CFSTR_PERFORMEDDROPEFFECT format is the reliable way to indicate that an unoptimized move has taken place.

    ———————————————-

    So should I use CFSTR_LOGICALPERFORMEDDROPEFFECT or CFSTR_PERFORMEDDROPEFFECT ? After all I think it’s pretty safe to assume that people all have IE 5? Or maybe not (maybe assumptions are never safe, like assuming people will have enough sense to recognize bad coding practices as simple conveniences for demonstrative purposes)? Perhaps I should be doing DllGetVersion on the Shell dll?

  2. jemnery says:

    I can’t believe you hard-coded the strings in the MessageBox() call. This example needs a full local-language independant implementation.

    ;-)

  3. nikos says:

    i hope there’s a series #4 in drag-drop lectures that explains what happens when IAsyncOperation gets into the picture

    thanks!

  4. Jörgen Sigvardsson says:

    I can’t believe you hard-coded the strings in the MessageBox() call. This example needs a full local-language independant implementation.

    At least the grumpiest of them all won’t be able to complain about unicode correctness. ;)

Comments are closed.


*DISCLAIMER: I DO NOT OWN THIS CONTENT. If you are the owner and would like it removed, please contact me. The content herein is an archived reproduction of entries from Raymond Chen's "Old New Thing" Blog (most recent link is here). It may have slight formatting modifications for consistency and to improve readability.

WHY DID I DUPLICATE THIS CONTENT HERE? Let me first say this site has never had anything to sell and has never shown ads of any kind. I have nothing monetarily to gain by duplicating content here. Because I had made my own local copy of this content throughout the years, for ease of using tools like grep, I decided to put it online after I discovered some of the original content previously and publicly available, had disappeared approximately early to mid 2019. At the same time, I present the content in an easily accessible theme-agnostic way.

The information provided by Raymond's blog is, for all practical purposes, more authoritative on Windows Development than Microsoft's own MSDN documentation and should be considered supplemental reading to that documentation. The wealth of missing details provided by this blog that Microsoft could not or did not document about Windows over the years is vital enough, many would agree an online "backup" of these details is a necessary endeavor. Specifics include:

<-- Back to Old New Thing Archive Index