Click here to Skip to main content
Email Password   helpLost your password?

Contents

Introduction

In Parts I and II of the Guide, I showed how to write context menu extensions that are invoked when the user right-clicks on certain types of files. In this part, I'll demonstrate a different type of context menu extension, the drag and drop handler, which adds items to the context menu displayed for a right-button drag and drop operation. I'll also give more examples of using MFC in an extension.

Part IV assumes that you understand the basics of shell extensions, and are familiar with MFC. This particular extension is a real utility that creates hard links on Windows 2000 and later, but you can still follow along even if you are using an older version of Windows.

As every power user knows (and few normal users know), you can drag and drop items in Explorer using the right mouse button. When you release the button, Explorer shows a context menu that lists all the available actions you can take. Normally, these are move, copy, and create shortcut:

 [Drag and drop menu - 4K]

Explorer lets us add items to this menu, by using a drag and drop handler. This type of extension is invoked when any right-drag and drop operation happens, and the extension can add menu items if it deems it should. An example of a drag and drop handler is in WinZip. Here's what WinZip adds to the context menu when you right-drag a compressed file:

 [WinZip menu - 6K]

WinZip's extension is invoked for any right-drag and drop operation, but it only adds it menu items if a compressed file is being dragged.

This article's sample extension will use an API added in Windows 2000, CreateHardLink(), to make hard links to files on NTFS volumes. We'll add an item for making links to the context menu, so the user can make hard links the same way as regular shortcuts.

Remember that VC 7 (and probably VC 8) users will need to change some settings before compiling. See the README section in Part I for the details.

Using AppWizard to Get Started

Run the AppWizard and make a new ATL COM app. We'll call it HardLink. We are going to use MFC, so check the Support MFC checkbox, and then click Finish. To add a COM object to the DLL, go to the ClassView tree, right-click the HardLink classes item, and pick New ATL Object. (In VC 7, right-click the item and pick Add|Add Class.) As before, choose Simple Object in the wizard, and use the name HardLinkShlExt for the object. This will create a C++ class CHardLinkShlExt that will implement the extension.

The Initialization Interface

As with our earlier context menu extensions, Explorer initializes us using the IShellExtInit interface. We first need to add IShellExtInit to the list of interfaces that CHardLinkShlExt implements. Open HardLinkShlExt.h, and add the lines listed here in bold:

#include <comdef.h>

#include <shlobj.h>

 
class CHardLinkShlExt :
  public CComObjectRootEx<CComSingleThreadModel>,
  public CComCoClass<CHardLinkShlExt, &CLSID_HarkLinkShlExt>,
  public IShellExtInit
{
  BEGIN_COM_MAP(CHardLinkShlExt)
    COM_INTERFACE_ENTRY(IShellExtInit)
  END_COM_MAP()
 
public:
  // IShellExtInit

  STDMETHODIMP Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY);

We'll also need some variables to hold a bitmap and the names of the files being dragged:

protected:
  CBitmap     m_bitmap;
  TCHAR       m_szFolderDroppedIn[MAX_PATH];
  CStringList m_lsDroppedFiles;

Also, we'll need to add a some #defines to stdafx.h to make the CreateHardLink() and shlwapi.dll function prototypes visible:

#define WINVER 0x0500
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0400

Defining WINVER as 0x0500 enables features specific to Win 98 and 2000, and defining _WIN32_WINNT as 0x0500 enables NT features specific to Win 2000. Defining _WIN32_IE as 0x0400 enables features introduced with IE 4.

Now, on to the Initialize() method. This time, I'll show how to use MFC to access the list of files being dragged. MFC has a class, COleDataObject, that wraps the IDataObject interface. Previously, we had to call IDataObject methods directly. But fortunately, MFC makes the job a bit easier for us. Here's the prototype for Initialize(), to refresh your memory:

HRESULT IShellExtInit::Initialize (
  LPCITEMIDLIST pidlFolder,
  LPDATAOBJECT  pDataObj,
  HKEY          hProgID );

For drag and drop extensions, pidlFolder is the PIDL of the folder where the items were dropped. (I'll have more to say about the PIDL later.) pDataObj is an IDataObject interface with which we can enumerate all of the items that were dropped. hProgID is an open HKEY on our shell extension's key under HKEY_CLASSES_ROOT.

Our first step is to load a bitmap for our menu item. Then, we attach a COleDataObject variable to the IDataObject interface.

HRESULT CHardLinkShlExt::Initialize (
  LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj,
  HKEY hProgID )
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState());  // init MFC

 
COleDataObject dataobj;
HGLOBAL        hglobal;
HDROP          hdrop;
TCHAR          szRoot[MAX_PATH];
TCHAR          szFileSystemName[256];
TCHAR          szFile[MAX_PATH];
UINT           uFile, uNumFiles;
 
  m_bitmap.LoadBitmap ( IDB_LINKBITMAP );
 
  dataobj.Attach ( pDataObj, FALSE );

Passing FALSE as the second parameter to Attach() means to not release the IDataObject interface when the dataobj variable is destructed. The next step is to get the directory where the items were dropped. We have the PIDL of this directory, but how do we get the path? Time for a little sidebar...

"PIDL" is an acronym for pointer to an ID list. A PIDL is a way of uniquely identifying any object within the hierarchy presented by Explorer. Every object in the shell, whether it's part of the file system or not, has a PIDL. The exact structure of a PIDL depends on where the object is, but unless you are writing your own namespace extension, you don't (and shouldn't) have to worry about the internal structure of a PIDL.

For our purposes, we can use the shell API SHGetPathFromIDList() to translate the PIDL into a conventional path. If the target folder isn't a directory in the file system (for example, the Control Panel), SHGetPathFromIDList() will fail and we can bail out.

  if ( !SHGetPathFromIDList(pidlFolder, m_szFolderDroppedIn) )
    return E_FAIL;

Next, we have to check if the target directory is on an NTFS volume. We get the root component of the path (for example, E:\), and get the info about that volume. If the file system is not NTFS, we can't make any links, so we can return.

  lstrcpy ( szRoot, m_szFolderDroppedIn );
  PathStripToRoot ( szRoot );
 
  if ( !GetVolumeInformation ( szRoot, NULL, 0, NULL, NULL, NULL, 
                               szFileSystemName, 256 ))
    {
    // Couldn't determine file system type.

    return E_FAIL;
    }
 
  if ( 0 != lstrcmpi ( szFileSystemName, _T("ntfs") ))
    {
    // The file system isn't NTFS, so it doesn't support hard links.

    return E_FAIL;
    }

Next, we get an HDROP handle from the data object, which we'll use to enumerate the files that were dropped. This is similar to the method in Part III, except we're using the MFC class to access the data. COleDataObject handles setting up the FORMATETC and STGMEDIUM structs for us.

  hglobal = dataobj.GetGlobalData ( CF_HDROP );
 
  if ( NULL == hglobal )
    return E_INVALIDARG;
 
  hdrop = (HDROP) GlobalLock ( hglobal );
 
  if ( NULL == hdrop )
    return E_INVALIDARG;

We then use the HDROP handle to enumerate the dropped files. For each one, we check if it is a directory. Directories cannot be linked to, so if we find a directory, we can return.

  uNumFiles = DragQueryFile ( hdrop, 0xFFFFFFFF, NULL, 0 );
 
  for ( uFile = 0; uFile < uNumFiles; uFile++ )
    {
    if ( DragQueryFile ( hdrop, uFile, szFile, MAX_PATH ) )
      {
      if ( PathIsDirectory ( szFile ) )
        {
        // We found a directory!  Bail out.

        m_lsDroppedFiles.RemoveAll();
        break;
        }

We also have to check that the dropped files reside on the same volume as the target directory. What I did was compare the root components of each file and the target directory, and return if they are different. This is not a complete solution, though, since on NTFS volumes, you can mount a volume in the middle of another. For example, you could have a C: volume, and mount another volume as C:\dev. This code will not reject an attempt to make a link from C:\dev to somewhere else on C:.

Here's the check that compares the root components:

      if ( !PathIsSameRoot(szFile, m_szFolderDroppedIn) )
        {
        // Dropped files came from a different volume - bail out.

        m_lsDroppedFiles.RemoveAll();
        break;
        }

If the file passes both checks, we add it to m_lsDroppedFiles, which is a CStringList (linked list of CStrings).

      // Add the file to our list of dropped files.

      m_lsDroppedFiles.AddTail ( szFile );
      }
    }   // end for

After the for loop, we release resources and return back to Explorer. If the string list contains any filenames, we return S_OK to indicate we need to modify the context menu. Otherwise, we return E_FAIL so that we won't be called again for this drag and drop event.

  GlobalUnlock ( hglobal );
 
  return (m_lsDroppedFiles.GetCount() > 0) ? S_OK : E_FAIL;
}

Modifying the Context Menu

Like other context menu extensions, a drag and drop handler implements the IContextMenu interface with which it interacts with the context menu. To add IContextMenu to our extension, open HardLinkShlExt.h again and add the lines listed in bold:

class CHardLinkShlExt :
  public CComObjectRootEx<CComSingleThreadModel>,
  public CComCoClass<CHardLinkShlExt, &CLSID_HardLinkShlExt>,
  public IShellExtInit,
  public IContextMenu
{
  BEGIN_COM_MAP(CHardLinkShlExt)
    COM_INTERFACE_ENTRY(IShellExtInit)
    COM_INTERFACE_ENTRY(IContextMenu)
  END_COM_MAP()
 
public:
  // IContextMenu

  STDMETHODIMP GetCommandString(UINT, UINT, UINT*, LPSTR, UINT)
                 { return E_NOTIMPL; }
  STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO);
  STDMETHODIMP QueryContextMenu(HMENU, UINT, UINT, UINT, UINT);

Note that we don't need any code in GetCommandString(), because that method is not called in drag and drop handlers.

Explorer calls our QueryContextMenu() function to let us modify the context menu. There's nothing here you haven't seen before; we just add one menu item and set its bitmap.

HRESULT CHardLinkShlExt::QueryContextMenu (
    HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd,
    UINT uidLastCmd, UINT uFlags )
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState());  // init MFC

 
  // If the flags include CMF_DEFAULTONLY then we shouldn't do anything.

  if ( uFlags & CMF_DEFAULTONLY )
    return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 0 );
 
  // Add the hard link menu item.

  InsertMenu ( hmenu, uMenuIndex, MF_STRING | MF_BYPOSITION,
               uidFirstCmd, _T("Create hard link(s) here") );
 
  if ( NULL != m_bitmap.GetSafeHandle() )
    {
    SetMenuItemBitmaps ( hmenu, uMenuIndex, MF_BYPOSITION,
                         (HBITMAP) m_bitmap.GetSafeHandle(), NULL );
    }
 
  // Return 1 to tell the shell that we added 1 top-level menu item.

  return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 1);
}

Here's what the new menu item looks like:

 [Hard link menu item - 11K]

Making the Link

Explorer calls InvokeCommand() when the user clicks our menu item. We'll create links to all the files that were dropped. The names of the links will be "Hard link to <filename>", or, if that name is already in use, "Hard link (2) to <filename>". The number will go up to 99, an arbitrary limit.

First, the locals and a check of the lpVerb parameter, which must be 0 since we only have 1 menu item.

HRESULT CHardLinkShlExt::InvokeCommand (
  LPCMINVOKECOMMANDINFO pInfo )
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState());  // init MFC

 
TCHAR    szNewFilename[MAX_PATH+32];
CString  sSrcFile;
TCHAR    szSrcFileTitle[MAX_PATH];
CString  sMessage;
UINT     uLinkNum;
POSITION pos;
 
  // Double-check that we're getting called for our own menu item - lpVerb

  // must be 0.

  if ( 0 != pInfo->lpVerb )
    return E_INVALIDARG;

Next, we get a POSITION value pointing at the beginning of the string list. A POSITION is an opaque data type which you don't use directly, but instead you pass it to other methods of the CStringList class. To get the POSITION of the head of the list, we call GetHeadPosition():

  pos = m_lsDroppedFiles.GetHeadPosition();
  ASSERT ( NULL != pos );

pos will be NULL if the list is empty, but the list shouldn't be empty, ever, so I added an ASSERT to check for that case. Next up is the beginning of the loop that will iterate through the filenames in the list and make a link to each one.

  while ( NULL != pos )
    {
    // Get the next source filename.

    sSrcFile = m_lsDroppedFiles.GetNext ( pos );
 
    // Remove the path - this reduces "C:\xyz\foo\stuff.exe" to "stuff.exe"

    lstrcpy ( szSrcFileTitle, sSrcFile );
    PathStripPath ( szSrcFileTitle );
 
    // Make the filename for the hard link - we'll first try 

    // "Hard link to stuff.exe"

    wsprintf ( szNewFilename, _T("%sHard link to %s"), m_szFolderDroppedIn,
               szSrcFileTitle );

GetNext() returns the CString at the position indicated by pos, and increments pos to point at the next string. If pos was at the end of the list, pos becomes NULL (so that's how the while loop will end).

At this point, szNewFilename holds the full path of the hard link. We check if a file with this name exists, and if so, we'll try adding numbers 2 through 99, looking for a name that's not already in use. We also make sure the length of the link name (including the terminating null) doesn't exceed MAX_PATH characters.

    for ( uLinkNum = 2;
          PathFileExists(szNewFilename) && uLinkNum < 100; 
          uLinkNum++ )
      {
      // Try another filename for the link.

      wsprintf ( szNewFilename, _T("%sHard link (%u) to %s"),
                 m_szFolderDroppedIn, uLinkNum, szSrcFileTitle );
 
      // If the resulting filename is longer than MAX_PATH, show an 

      // error message.

      if ( lstrlen(szNewFilename) >= MAX_PATH )
        {
        sMessage.Format ( _T("Failed to make a link to %s.\nDo you want to continue making links?"),
                         (LPCTSTR) sSrcFile );
 
        if (IDNO == MessageBox ( pInfo->hwnd, sMessage, _T("Create Hard Links"),
                                 MB_ICONQUESTION | MB_YESNO) )
          break;
        else
          continue;
        }
      }  // end for

The message box lets you abort the entire operation if you want. Next, we check to see if we hit the limit of 99 links. Again, we let the user abort the whole operation.

    if ( 100 == uLinkNum )
      {
      sMessage.Format ( _T("Failed to make a link to %s.\nDo you want to continue making links?"),
                       (LPCTSTR) sSrcFile );
 
      if (IDNO == MessageBox ( pInfo->hwnd, sMessage, _T("Create Hard Links"),
                               MB_ICONQUESTION | MB_YESNO) )
        break;
      else
        continue;
      }

All that's left is to make the hard link. I've omitted the error handling code for clarity.

    CreateHardLink ( szNewFilename, sSrcFile, NULL );
    }  // end while

 
  return S_OK;
}

The hard link doesn't look any different in Explorer, it just looks like any other ordinary file. But if you modify one copy, the changes will be reflected in the other copy.

 [Hard link to the file - 4K]

Registering the Shell Extension

Registering a drag and drop handler is simpler than other context menu extensions. All handlers are registered under the HKCR\Directory key, since that's where the drop happens, in a directory. However, what the docs don't say is that registering under HKCR\Directory isn't enough to handle all cases. You also need to register under HKCR\Folder to handle drops on the desktop, and HKCR\Drive to handle drops in root directories.

Here is the RGS script to handle all three of the above situations:

HKCR
{
  NoRemove Directory
  {
    NoRemove shellex
    {
      NoRemove DragDropHandlers
      {
        ForceRemove HardLinkShlExt = s '{3C06DFAE-062F-11D4-8D3B-919D46C1CE19}'
      }
    }
  }
  NoRemove Folder
  {
    NoRemove shellex
    {
      NoRemove DragDropHandlers
      {
        ForceRemove HardLinkShlExt = s '{3C06DFAE-062F-11D4-8D3B-919D46C1CE19}'
      }
    }
  }
  NoRemove Drive
  {
    NoRemove shellex
    {
      NoRemove DragDropHandlers
      {
        ForceRemove HardLinkShlExt = s '{3C06DFAE-062F-11D4-8D3B-919D46C1CE19}'
      }
    }
  }
}

As with our previous extensions, on NT-based OSes, we need to add our extension to the list of "approved" extensions. The code to do this is in the DllRegisterServer() and DllUnregisterServer() functions in the sample project.

If You Don't Have Windows 2000/NTFS

You can still build and run the sample project on earlier versions of Windows, or if you don't have an NTFS volume available. Just open the stdafx.h file, and uncomment the line that reads:

// #define NOT_ON_WIN2K

That will make the extension skip the file system check (so it will run on anything, not just NTFS), and display message boxes instead of actually making links.

To Be Continued

Coming up in Part V, we'll see a new type of extension, the property sheet handler, which adds pages to the properties dialog for files.

Copyright and License

This article is copyrighted material, ©2000-2006 by Michael Dunn. I realize this isn't going to stop people from copying it all around the 'net, but I have to say it anyway. If you are interested in doing a translation of this article, please email me to let me know. I don't foresee denying anyone permission to do a translation, I would just like to be aware of the translation so I can post a link to it here.

The demo code that accompanies this article is released to the public domain. I release it this way so that the code can benefit everyone. (I don't make the article itself public domain because having the article available only on CodeProject helps both my own visibility and the CodeProject site.) If you use the demo code in your own application, an email letting me know would be appreciated (just to satisfy my curiosity about whether folks are benefitting from my code) but is not required. Attribution in your own source code is also appreciated but not required.

Revision History

April 3, 2000: Article first published.
June 6, 2000: Something updated. ;)
May 24, 2006: Updated to cover changes in VC 7.1, cleaned up code snippets.

Series Navigation: « Part III | Part V »

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
QuestionThis is possible, right?
Sebastien Mongrain
12:06 18 Jan '10  
Recently, I have been tasked with coding a small extension to prepare our code for web deployment. It's very basic, just copying files that we want. I did this by writing a small C# prog that I binded to the right click on folders. But that implies that i use a hardcoded destination to have some place to copy the files to. This works, but it would be preferable if I could just right-click drag-and-drop to the destination folder. I suppose this could be done, but I have no clue about COM interfaces.

This is possible, right? I could use a hint or two here.
AnswerRe: This is possible, right? [edited]
Garth J Lancaster
14:18 18 Jan '10  
there's plenty of code/info out there on 'drag and drop' - I drag files onto a listbox and a particular process scans them - this (below) might be a starter, but its not hard

File Drag and Drop Encapsulated in a C++ Class[^]

does that sound like what you want ?

'g'

[edit] and one for C# Drag-and-Drop ListBox[^]
GeneralRe: This is possible, right? [edited]
Sebastien Mongrain
6:02 19 Jan '10  
Not quite, but every bit of info is useful. I'll have a look at the complete source code, maybe that'll clear some things out.
GeneralHardLink is not woking in Vista
GrantFei
15:52 1 Feb '09  
I have registed Hardlink in vista by admin account,but I found explorer has loaded it ,but it can't work,and the method "Initialize" is not invoked.Forthermore,
I have writed it in "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved",no resullt was found.How can i do ?
GeneralRe: HardLink is not woking in Vista
GrantFei
3:57 2 Feb '09  
In Vista,when implements IContextMenu,Initialize is not invoked.
GeneralHandle taskbar Contextmenu for lock/unlock toolbars.
knareshkumar
0:43 15 Dec '08  
hi All,
how can i handle the lock/unlock toolbars menu item of the taskbar context menu.
as invokecommand and querycommand of icontexmenu are not getting called in my case.

i derived my class from IContextMenu and overridden the three functions.
is their any need to derive my class from IShellExtInit interface. if yes please explain.

I am naresh kavali
intrested in formus of VC++, Com,ATL

Generalis there a way to have a shell extension not on right-drag-and-drop but on usual left-drag-and drop ?
carabutnicolae1234
3:09 15 Oct '07  
is there a way to have a shell extension not on right-drag-and-drop but on usual left-drag-and drop ? so I can catch the usual drag-and-drop operation by the user in explorer an prompt for a dialog that will show some operations to perform on the files before to copy ?

thanks.
GeneralRe: is there a way to have a shell extension not on right-drag-and-drop but on usual left-drag-and drop ?
Michael Dunn
15:01 21 Oct '07  
You can write a copy hook[^] extension to get that notification.

--Mike--
Visual C++ MVP Cool
LINKS~! Ericahist | PimpFish | CP SearchBar v3.0 | C++ Forum FAQ

I work for Keyser Söze

GeneralRe: is there a way to have a shell extension not on right-drag-and-drop but on usual left-drag-and drop ?
carabutnicolae1234
0:55 26 Oct '07  
http://msdn2.microsoft.com/en-us/library/bb776049.aspx
http://www.codeproject.com/atl/CopyHook.asp

for a while the problem was canceled, now I have it back, so I will continue asking.

From the links above I see it is works on folders only.
I need to have a way to intercept the copy for files and folders,
and when it happens to pop up a UI that will allow to do some custom things on those items.

One of the idea is to replace in the IAT for explorer.exe(all the actions happen from the explerer only) the pointer to the SHFileOperation, but in-memory patching might not work on another OS like vista where all the suspect operations can be canceled, or any antiviruses that can block this. Besides that, it is a better way to have a shell extension that will allow a more 'legal' activity of the process.

QuestionIContexMenu::InvokeCommand not called on Vista
sathink
2:48 25 Jul '07  
I am maintaining a shell namespace extension. It works fine on XP. On Windows Vista tree view, when user right clicks on any folder and selects any menu item on context menu, nothing happens. On debugging i found out that IContextMenu::QueryContextMenu() and IIContextMenu::GetCommandString() are called and return successfully. What may be the reason InvokeCommand() is not at all called?

We have a virtual folder on desktop and context menu works fine there(InvokeCommand() is called). And the problem is only in tree view of Vista explorer.

Thanks in advance,
prem
AnswerRe: IContexMenu::InvokeCommand not called on Vista
Michael Dunn
10:28 28 Jul '07  
I just checked my machine, and the WinRAR[^] and DirClean[^] extensions work in the tree pane.

--Mike--
Visual C++ MVP Cool
LINKS~! Ericahist | PimpFish | CP SearchBar v3.0 | C++ Forum FAQ

Dunder-Mifflin, this is Pam.

AnswerRe: IContexMenu::InvokeCommand not called on Vista
Hugo Caldeira
0:07 14 Apr '09  
I have exactly the same problem, looking for a solution.
QuestionAsync Transfers in a Namespace Extension
altronome
14:53 13 Apr '07  
Hello!
I realize my question does not exactly concern this article, but I've been seeking for help for more than a month... I need to implement asynchronous data transfers from my NSE to Explorer (I just want my NSE to act as a drop source). I'm using ATL to implement the NSE. I read that I need to let my IDataObject implement IAsyncOperation as well. In my implementation, GetAsyncMode always states that asynchronous data transfers are desired (I tried 'returning' both VARIANT_TRUE and TRUE). The problem is that this method is never called. I implemented the DataObject as STA, then I changed to MTA and GetAsyncMode was called, but the transfer was synchronous nonetheless! I changed one thing, found it didn't work, then rolled back to the version which let GetAsyncMode be called: this time it wasn't called!!!!
Has any of you experience in IAsyncOperation and/or asynchronous data transfers? Any help would be appreciated, I'm working on that since more than a month... luckily it doesn't concern my job!!
Here's my IDataObject implementation (btw, all actions needed by the data transfers occur in GetData):

class ATL_NO_VTABLE PPDataObject :
public CComObjectRootEx, public IDataObject, public IAsyncOperation{

...
BEGIN_COM_MAP(PPDataObject)
COM_INTERFACE_ENTRY(IDataObject)
COM_INTERFACE_ENTRY(IAsyncOperation)
END_COM_MAP()

...
STDMETHOD(EndOperation)(HRESULT hResult, IBindCtx* pbcReserved, DWORD dwEffects){
this->m_inOp=FALSE;
return S_OK;
}
STDMETHOD(GetAsyncMode)(BOOL* pfIsOpAsync){
*pfIsOpAsync=TRUE;
return S_OK;
}
STDMETHOD(InOperation)(BOOL *pfInAsyncOp){
*pfInAsyncOp=TRUE;
return S_OK;
}
STDMETHOD(SetAsyncMode)(BOOL fDoOpAsync){
return S_OK;
}
STDMETHOD(StartOperation)(IBindCtx *pbcReserved){
this->m_inOp=TRUE;
return S_OK;
}
...
}

When beginning to drag, I do:

...
CComObject* pDataObject;
...
CComObject::CreateInstance(&pDataObject);
pDataObject->AddRef();
...
if( SUCCEEDED(hr) && (pDataObject!=NULL) ) {
CComObject* pDropSource;
CComObject::CreateInstance(&pDropSource);
pDropSource->AddRef();
DWORD dwEffect = 0;
::DoDragDrop( pDataObject, pDropSource, DROPEFFECT_MOVE, &dwEffect);
pDropSource->Release();
...
}
...
pDataObject->Release();
...


Thanks in advance for your (very needed and appreciated) help!
GeneralShel Drag Drop-ICopyHook::copyCallback() Not Called
161411
2:55 13 Nov '06  
I am working on a project which is a namespace extension which supports drag and drop of file between windows folder and our namespace folders. The technique used to drag and drop a file from our namespace folder to windows folder is like this:
1. when drag is initiated,
a)details of the dragged object are stored in a global variable.
b)IDataObject(which supports 2 formats-CF_HDROP for between windows and private format for between our namespace folders) is created and drag loop is initiated by calling DoDragDrop().
2. In IDataobject::Getdata, for CF_HDROP format, a temp dir is created and the path is written to clipboard.
3. we have a copy hook handler which actually does the work of copying the file from namespace folder to windows folder.The Copycallback method of copyhookhandler gets the info from global variable and puts into windows folder and returns IDNO.

The product is working on thousands of systems correctly but on a perticular system with xp its not working.
log files show that IDataObject::GetData() is called n times with CF_HDROP , temp folder is created and folder path is written to clipboard. But ICopyHook::copyCallback() is not called.Deleting the copyhook handler registry key should create the temp folder(as we have placed this folder path on the clip board in IDataObject::Getdata() and our copyhook handler is not present) in drop target but its not happening here.


what might have gone wrong?why is ICopyHook::copyCallback() is not called?
GeneralRe: Shel Drag Drop-ICopyHook::copyCallback() Not Called
Michael Dunn
16:08 18 Nov '06  
A better way to do that is described in How to drag a virtual file from your app into Windows Explorer[^]

--Mike--
Visual C++ MVP Cool
LINKS~! Ericahist | PimpFish | CP SearchBar v3.0 | C++ Forum FAQ

Generalany body help me
syriast
3:40 31 Jul '06  
I wan thise project but in vb.net or c#.net
or make it as dll to use it in visual studio
please help me in thatCryRed facedRoll eyes
GeneralFailed to build in Visual Studio .NET
jonas.pettersson@sverige.nu
9:02 29 Aug '05  
------ Build started: Project: HardLink, Configuration: Debug Win32 ------

Compiling...
HardLinkShlExt.cpp
c:\Documents and Settings\Emma\Skrivbord\cc\HardLink\HardLinkShlExt.h(33) : error C2787: 'IContextMenu' : no GUID has been associated with this object
c:\Documents and Settings\Emma\Skrivbord\cc\HardLink\HardLinkShlExt.h(33) : error C2440: 'initializing' : cannot convert from 'DWORD_PTR' to 'const IID *'
Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
c:\Documents and Settings\Emma\Skrivbord\cc\HardLink\HardLinkShlExt.h(34) : error C2078: too many initializers
HardLink.cpp
c:\Documents and Settings\Emma\Skrivbord\cc\HardLink\HardLinkShlExt.h(33) : error C2787: 'IContextMenu' : no GUID has been associated with this object
c:\Documents and Settings\Emma\Skrivbord\cc\HardLink\HardLinkShlExt.h(33) : error C2440: 'initializing' : cannot convert from 'DWORD_PTR' to 'const IID *'
Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
c:\Documents and Settings\Emma\Skrivbord\cc\HardLink\HardLinkShlExt.h(34) : error C2078: too many initializers
Generating Code...

Build log was saved at "file://c:\Documents and Settings\Emma\Skrivbord\cc\HardLink\Debug\BuildLog.htm"
HardLink - 6 error(s), 0 warning(s)


// Jonas
GeneralRe: Failed to build in Visual Studio .NET
Michael Dunn
12:07 29 Aug '05  
This is a problem with the VC7 headers. Change your include path so that the PlatformSDK\include dir is before VC7\include

--Mike--
Visual C++ MVP Cool
LINKS~! Ericahist | 1ClickPicGrabber | NEW~! CP SearchBar v3.0 | C++ Forum FAQ
Actual sign at the laundromat I go to: "No tinting or dying."
GeneralRe: Failed to build in Visual Studio .NET
belgab
7:21 15 Jun '06  
Hi,

In VC8 changing include order does not work ( at least for me )

For this to work I has to change from

COM_INTERFACE_ENTRY(IContextMenu)

to

COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)


Other two thing I had to do in order to successefully compile the project ( I used the source provided with the article ) are:
a) Include "afxole.h" in stdfx.h for COleDataObject class
b) Adding a "\\" to "Hard Link File Path" to separate fileName and Directory


Regards,
Gabriele Beltrame


GeneralRe: Failed to build in Visual Studio .NET
rockryan
21:32 23 Jul '06  
Hi,
I use the same steps, but when I add a) Include "afxole.h" in stdfx.h
I'll encounter error like this:
Error 1 fatal error C1189: #error : WINDOWS.H already included. MFC apps must not #include C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxv_w32.h 16

Can you tell me how to solve this?
Thank you~

Ryan



GeneralFolder Files being linked from
vaughandaly
0:29 31 Jan '05  
Hi All

Is there a way to get the directory that the files are being linked from, ie where they are being dragged from?

I am sure that there must be some marker or something.

Thanks
Vaughan

"I once thought I saw the light at the end of the tunnel, but it was just the light from a torch of some bastard bringing me more work"
GeneralRe: Folder Files being linked from
Michael Dunn
12:53 1 Feb '05  
When you call DragQueryFile(), you get the full path of the file(s) being dragged. They may not all come from the same directory, since you could write an app that assembles its own list of arbitrary files into an HDROP struct (such as the sample app in this article[^]).

--Mike--
LINKS~! Ericahist | 1ClickPicGrabber | CP SearchBar v2.0.2 | C++ Forum FAQ | You Are Dumb
Strange things are afoot at the U+004B U+20DD

GeneralRe: Folder Files being linked from
vaughandaly
2:11 7 Feb '05  
Yeah you are right, and I think that I must have been asleep when I ask the question, as it was staring me right in the face all the time. You have the directory that the original file is in, as it is given to you as part of the filename.

I think that in future I should rather drink lots of coffee before asking another silly question.

Thanks for the reply, greatly appreciate it.

"I once thought I saw the light at the end of the tunnel, but it was just the light from a torch of some bastard bringing me more work"
GeneralHow to share the folder from program??
Jigar Mehta
0:42 8 Oct '04  
RoseAs a shell internal knower, I want to ask you how to share the folder from program ??

What are the interfaces that we need to implement ???



Jigar Mehta
(jigarmehta@gatescorp.com)

Software Developer
Gates Information Systems
India
GeneralFailing when a directory is dropped on a file
Lars [Large] Werner
2:32 19 Sep '04  
See the topic...


=====================
Lars [Large] Werner
lars@werner.no
http://lars.werner.no
=====================


Last Updated 24 May 2006 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010