/// <summary> /// Allows the drag source to prompt to save unsaved items being dropped. /// Notifies the source hierarchy that information dragged from it is about to be dropped on a target. /// This method is called immediately after the mouse button is released on a drop. /// </summary> /// <param name="o">Reference to the IDataObject interface on the item being dragged. /// This data object contains the data being transferred in the drag-and-drop operation. /// If the drop occurs, then this data object (item) is incorporated into the hierarchy window of the new hierarchy.</param> /// <param name="dwEffect">Current state of the keyboard and the mouse modifier keys.</param> /// <param name="fCancelDrop">If true, then the drop is cancelled by the source hierarchy. If false, then the drop can continue.</param> /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code. </returns> public override int OnBeforeDropNotify(IOleDataObject o, uint dwEffect, out int fCancelDrop) { // If there is nothing to be dropped just return that drop should be cancelled. if (this.ItemsDraggedOrCutOrCopied == null) { fCancelDrop = 1; return(VSConstants.S_OK); } fCancelDrop = 0; bool dirty = false; foreach (HierarchyNode node in this.ItemsDraggedOrCutOrCopied) { bool isDirty, isOpen, isOpenedByUs; uint docCookie; IVsPersistDocData ppIVsPersistDocData; DocumentManager manager = node.GetDocumentManager(); if (manager != null) { manager.GetDocInfo(out isOpen, out isDirty, out isOpenedByUs, out docCookie, out ppIVsPersistDocData); if (isDirty && isOpenedByUs) { dirty = true; break; } } } // if there are no dirty docs we are ok to proceed if (!dirty) { return(VSConstants.S_OK); } // Prompt to save if there are dirty docs string message = SR.GetString(SR.SaveModifiedDocuments, CultureInfo.CurrentUICulture); string title = string.Empty; OLEMSGICON icon = OLEMSGICON.OLEMSGICON_WARNING; OLEMSGBUTTON buttons = OLEMSGBUTTON.OLEMSGBUTTON_YESNOCANCEL; OLEMSGDEFBUTTON defaultButton = OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST; int result = VsShellUtilities.ShowMessageBox(Site, title, message, icon, buttons, defaultButton); switch (result) { case NativeMethods.IDYES: break; case NativeMethods.IDNO: return(VSConstants.S_OK); case NativeMethods.IDCANCEL: goto default; default: fCancelDrop = 1; return(VSConstants.S_OK); } // Save all dirty documents foreach (HierarchyNode node in this.ItemsDraggedOrCutOrCopied) { DocumentManager manager = node.GetDocumentManager(); if (manager != null) { manager.Save(true); } } return(VSConstants.S_OK); }