| Index: experimental/visual_studio_plugin/third_party/Microsoft.VisualStudio.Project/ProjectNode.CopyPaste.cs
|
| diff --git a/experimental/visual_studio_plugin/third_party/Microsoft.VisualStudio.Project/ProjectNode.CopyPaste.cs b/experimental/visual_studio_plugin/third_party/Microsoft.VisualStudio.Project/ProjectNode.CopyPaste.cs
|
| deleted file mode 100644
|
| index f7e18342dd5ecf23c7b0ec65bccb314a507f46a2..0000000000000000000000000000000000000000
|
| --- a/experimental/visual_studio_plugin/third_party/Microsoft.VisualStudio.Project/ProjectNode.CopyPaste.cs
|
| +++ /dev/null
|
| @@ -1,1140 +0,0 @@
|
| -/// Copyright (c) Microsoft Corporation. All rights reserved.
|
| -
|
| -using System;
|
| -using System.Collections;
|
| -using System.Collections.Generic;
|
| -using System.Diagnostics;
|
| -using System.Globalization;
|
| -using System.IO;
|
| -using System.Runtime.InteropServices;
|
| -using System.Security.Permissions;
|
| -using System.Text;
|
| -using Microsoft.VisualStudio;
|
| -using Microsoft.VisualStudio.OLE.Interop;
|
| -using Microsoft.VisualStudio.Shell;
|
| -using Microsoft.VisualStudio.Shell.Interop;
|
| -using IOleDataObject = Microsoft.VisualStudio.OLE.Interop.IDataObject;
|
| -using OleConstants = Microsoft.VisualStudio.OLE.Interop.Constants;
|
| -
|
| -namespace Microsoft.VisualStudio.Project
|
| -{
|
| - /// <summary>
|
| - /// Manages the CopyPaste and Drag and Drop scenarios for a Project.
|
| - /// </summary>
|
| - /// <remarks>This is a partial class.</remarks>
|
| - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
|
| - public partial class ProjectNode : IVsUIHierWinClipboardHelperEvents
|
| - {
|
| - #region fields
|
| - private uint copyPasteCookie;
|
| - private DropDataType dropDataType;
|
| - #endregion
|
| -
|
| - #region override of IVsHierarchyDropDataTarget methods
|
| - /// <summary>
|
| - /// Called as soon as the mouse drags an item over a new hierarchy or hierarchy window
|
| - /// </summary>
|
| - /// <param name="pDataObject">reference to interface IDataObject of the item being dragged</param>
|
| - /// <param name="grfKeyState">Current state of the keyboard and the mouse modifier keys. See docs for a list of possible values</param>
|
| - /// <param name="itemid">Item identifier for the item currently being dragged</param>
|
| - /// <param name="pdwEffect">On entry, a pointer to the current DropEffect. On return, must contain the new valid DropEffect</param>
|
| - /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code.</returns>
|
| - public override int DragEnter(IOleDataObject pDataObject, uint grfKeyState, uint itemid, ref uint pdwEffect)
|
| - {
|
| - pdwEffect = (uint)DropEffect.None;
|
| -
|
| - if(this.SourceDraggedOrCutOrCopied)
|
| - {
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - this.dropDataType = QueryDropDataType(pDataObject);
|
| - if(this.dropDataType != DropDataType.None)
|
| - {
|
| - pdwEffect = (uint)this.QueryDropEffect(this.dropDataType, grfKeyState);
|
| - }
|
| -
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Called when one or more items are dragged out of the hierarchy or hierarchy window, or when the drag-and-drop operation is cancelled or completed.
|
| - /// </summary>
|
| - /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code.</returns>
|
| - public override int DragLeave()
|
| - {
|
| - this.dropDataType = DropDataType.None;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Called when one or more items are dragged over the target hierarchy or hierarchy window.
|
| - /// </summary>
|
| - /// <param name="grfKeyState">Current state of the keyboard keys and the mouse modifier buttons. See <seealso cref="IVsHierarchyDropDataTarget"/></param>
|
| - /// <param name="itemid">Item identifier of the drop data target over which the item is being dragged</param>
|
| - /// <param name="pdwEffect"> On entry, reference to the value of the pdwEffect parameter of the IVsHierarchy object, identifying all effects that the hierarchy supports.
|
| - /// On return, the pdwEffect parameter must contain one of the effect flags that indicate the result of the drop operation. For a list of pwdEffects values, see <seealso cref="DragEnter"/></param>
|
| - /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code.</returns>
|
| - public override int DragOver(uint grfKeyState, uint itemid, ref uint pdwEffect)
|
| - {
|
| - pdwEffect = (uint)DropEffect.None;
|
| -
|
| - // Dragging items to a project that is being debugged is not supported
|
| - // (see VSWhidbey 144785)
|
| - DBGMODE dbgMode = VsShellUtilities.GetDebugMode(this.Site) & ~DBGMODE.DBGMODE_EncMask;
|
| - if(dbgMode == DBGMODE.DBGMODE_Run || dbgMode == DBGMODE.DBGMODE_Break)
|
| - {
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - if(this.isClosed || this.site == null)
|
| - {
|
| - return VSConstants.E_UNEXPECTED;
|
| - }
|
| -
|
| - // We should also analyze if the node being dragged over can accept the drop.
|
| - if(!this.CanTargetNodeAcceptDrop(itemid))
|
| - {
|
| - return VSConstants.E_NOTIMPL;
|
| - }
|
| -
|
| - if(this.dropDataType != DropDataType.None)
|
| - {
|
| - pdwEffect = (uint)this.QueryDropEffect(this.dropDataType, grfKeyState);
|
| - }
|
| -
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Called when one or more items are dropped into the target hierarchy or hierarchy window when the mouse button is released.
|
| - /// </summary>
|
| - /// <param name="pDataObject">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 target hierarchy or hierarchy window.</param>
|
| - /// <param name="grfKeyState">Current state of the keyboard and the mouse modifier keys. See <seealso cref="IVsHierarchyDropDataTarget"/></param>
|
| - /// <param name="itemid">Item identifier of the drop data target over which the item is being dragged</param>
|
| - /// <param name="pdwEffect">Visual effects associated with the drag-and drop-operation, such as a cursor, bitmap, and so on.
|
| - /// The value of dwEffects passed to the source object via the OnDropNotify method is the value of pdwEffects returned by the Drop method</param>
|
| - /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code. </returns>
|
| - public override int Drop(IOleDataObject pDataObject, uint grfKeyState, uint itemid, ref uint pdwEffect)
|
| - {
|
| - if(pDataObject == null)
|
| - {
|
| - return VSConstants.E_INVALIDARG;
|
| - }
|
| -
|
| - pdwEffect = (uint)DropEffect.None;
|
| -
|
| - // Get the node that is being dragged over and ask it which node should handle this call
|
| - HierarchyNode targetNode = NodeFromItemId(itemid);
|
| - if(targetNode != null)
|
| - {
|
| - targetNode = targetNode.GetDragTargetHandlerNode();
|
| - }
|
| - else
|
| - {
|
| - // There is no target node. The drop can not be completed.
|
| - return VSConstants.S_FALSE;
|
| - }
|
| -
|
| - int returnValue;
|
| - try
|
| - {
|
| - DropDataType dropDataType = DropDataType.None;
|
| - dropDataType = ProcessSelectionDataObject(pDataObject, targetNode);
|
| - pdwEffect = (uint)this.QueryDropEffect(dropDataType, grfKeyState);
|
| -
|
| - // If it is a drop from windows and we get any kind of error we return S_FALSE and dropeffect none. This
|
| - // prevents bogus messages from the shell from being displayed
|
| - returnValue = (dropDataType != DropDataType.Shell) ? VSConstants.E_FAIL : VSConstants.S_OK;
|
| - }
|
| - catch(System.IO.FileNotFoundException e)
|
| - {
|
| - Trace.WriteLine("Exception : " + e.Message);
|
| -
|
| - if(!Utilities.IsInAutomationFunction(this.Site))
|
| - {
|
| - string message = e.Message;
|
| - string title = string.Empty;
|
| - OLEMSGICON icon = OLEMSGICON.OLEMSGICON_CRITICAL;
|
| - OLEMSGBUTTON buttons = OLEMSGBUTTON.OLEMSGBUTTON_OK;
|
| - OLEMSGDEFBUTTON defaultButton = OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST;
|
| - VsShellUtilities.ShowMessageBox(this.Site, title, message, icon, buttons, defaultButton);
|
| - }
|
| -
|
| - returnValue = VSConstants.E_FAIL;
|
| - }
|
| -
|
| - return returnValue;
|
| - }
|
| - #endregion
|
| -
|
| - #region override of IVsHierarchyDropDataSource2 methods
|
| - /// <summary>
|
| - /// Returns information about one or more of the items being dragged
|
| - /// </summary>
|
| - /// <param name="pdwOKEffects">Pointer to a DWORD value describing the effects displayed while the item is being dragged,
|
| - /// such as cursor icons that change during the drag-and-drop operation.
|
| - /// For example, if the item is dragged over an invalid target point
|
| - /// (such as the item's original location), the cursor icon changes to a circle with a line through it.
|
| - /// Similarly, if the item is dragged over a valid target point, the cursor icon changes to a file or folder.</param>
|
| - /// <param name="ppDataObject">Pointer 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 target hierarchy or hierarchy window.</param>
|
| - /// <param name="ppDropSource">Pointer to the IDropSource interface of the item being dragged.</param>
|
| - /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code.</returns>
|
| - public override int GetDropInfo(out uint pdwOKEffects, out IOleDataObject ppDataObject, out IDropSource ppDropSource)
|
| - {
|
| - //init out params
|
| - pdwOKEffects = (uint)DropEffect.None;
|
| - ppDataObject = null;
|
| - ppDropSource = null;
|
| -
|
| - IOleDataObject dataObject = PackageSelectionDataObject(false);
|
| - if(dataObject == null)
|
| - {
|
| - return VSConstants.E_NOTIMPL;
|
| - }
|
| -
|
| - this.SourceDraggedOrCutOrCopied = true;
|
| -
|
| - pdwOKEffects = (uint)(DropEffect.Move | DropEffect.Copy);
|
| -
|
| - ppDataObject = dataObject;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Notifies clients that the dragged item was dropped.
|
| - /// </summary>
|
| - /// <param name="fDropped">If true, then the dragged item was dropped on the target. If false, then the drop did not occur.</param>
|
| - /// <param name="dwEffects">Visual effects associated with the drag-and-drop operation, such as cursors, bitmaps, and so on.
|
| - /// The value of dwEffects passed to the source object via OnDropNotify method is the value of pdwEffects returned by Drop method.</param>
|
| - /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code. </returns>
|
| - public override int OnDropNotify(int fDropped, uint dwEffects)
|
| - {
|
| - if(!this.SourceDraggedOrCutOrCopied)
|
| - {
|
| - return VSConstants.S_FALSE;
|
| - }
|
| -
|
| - this.CleanupSelectionDataObject(fDropped != 0, false, dwEffects == (uint)DropEffect.Move);
|
| -
|
| - this.SourceDraggedOrCutOrCopied = false;
|
| -
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - /// <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;
|
| - }
|
| -
|
| - #endregion
|
| -
|
| - #region IVsUIHierWinClipboardHelperEvents Members
|
| - /// <summary>
|
| - /// Called after your cut/copied items has been pasted
|
| - /// </summary>
|
| - ///<param name="wasCut">If true, then the IDataObject has been successfully pasted into a target hierarchy.
|
| - /// If false, then the cut or copy operation was cancelled.</param>
|
| - /// <param name="dropEffect">Visual effects associated with the drag and drop operation, such as cursors, bitmaps, and so on.
|
| - /// These should be the same visual effects used in OnDropNotify</param>
|
| - /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code. </returns>
|
| - public virtual int OnPaste(int wasCut, uint dropEffect)
|
| - {
|
| - if(!this.SourceDraggedOrCutOrCopied)
|
| - {
|
| - return VSConstants.S_FALSE;
|
| - }
|
| -
|
| - if(dropEffect == (uint)DropEffect.None)
|
| - {
|
| - return OnClear(wasCut);
|
| - }
|
| -
|
| - this.CleanupSelectionDataObject(false, wasCut != 0, dropEffect == (uint)DropEffect.Move);
|
| - this.SourceDraggedOrCutOrCopied = false;
|
| - return VSConstants.S_OK;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Called when your cut/copied operation is canceled
|
| - /// </summary>
|
| - /// <param name="wasCut">This flag informs the source that the Cut method was called (true),
|
| - /// rather than Copy (false), so the source knows whether to "un-cut-highlight" the items that were cut.</param>
|
| - /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code. </returns>
|
| - public virtual int OnClear(int wasCut)
|
| - {
|
| - if(!this.SourceDraggedOrCutOrCopied)
|
| - {
|
| - return VSConstants.S_FALSE;
|
| - }
|
| -
|
| - this.CleanupSelectionDataObject(false, wasCut != 0, false, true);
|
| - this.SourceDraggedOrCutOrCopied = false;
|
| - return VSConstants.S_OK;
|
| - }
|
| - #endregion
|
| -
|
| - #region virtual methods
|
| - /// <summary>
|
| - /// Determines if a node can accept drop opertaion.
|
| - /// </summary>
|
| - /// <param name="itemid">The id of the node.</param>
|
| - /// <returns>true if the node acceots drag operation.</returns>
|
| - protected internal virtual bool CanTargetNodeAcceptDrop(uint itemId)
|
| - {
|
| - HierarchyNode targetNode = NodeFromItemId(itemId);
|
| - if(targetNode is ReferenceContainerNode || targetNode is ReferenceNode)
|
| - {
|
| - return false;
|
| - }
|
| - else
|
| - {
|
| - return true;
|
| - }
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Returns a dataobject from selected nodes
|
| - /// </summary>
|
| - /// <param name="cutHighlightItems">boolean that defines if the selected items must be cut</param>
|
| - /// <returns>data object for selected items</returns>
|
| - internal virtual DataObject PackageSelectionDataObject(bool cutHighlightItems)
|
| - {
|
| - this.CleanupSelectionDataObject(false, false, false);
|
| - StringBuilder sb = new StringBuilder();
|
| -
|
| - DataObject dataObject = null;
|
| -
|
| - try
|
| - {
|
| - IList<HierarchyNode> selectedNodes = this.GetSelectedNodes();
|
| - if(selectedNodes != null)
|
| - {
|
| - this.InstantiateItemsDraggedOrCutOrCopiedList();
|
| -
|
| - StringBuilder selectionContent = null;
|
| -
|
| - // If there is a selection package the data
|
| - if(selectedNodes.Count > 1)
|
| - {
|
| - foreach(HierarchyNode node in selectedNodes)
|
| - {
|
| - selectionContent = node.PrepareSelectedNodesForClipBoard();
|
| - if(selectionContent != null)
|
| - {
|
| - sb.Append(selectionContent);
|
| - }
|
| - }
|
| - }
|
| - else if(selectedNodes.Count == 1)
|
| - {
|
| - HierarchyNode selectedNode = selectedNodes[0];
|
| - selectionContent = selectedNode.PrepareSelectedNodesForClipBoard();
|
| - if(selectionContent != null)
|
| - {
|
| - sb.Append(selectionContent);
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Add the project items first.
|
| - IntPtr ptrToItems = this.PackageSelectionData(sb, false);
|
| - if(ptrToItems == IntPtr.Zero)
|
| - {
|
| - return null;
|
| - }
|
| -
|
| - FORMATETC fmt = DragDropHelper.CreateFormatEtc(DragDropHelper.CF_VSSTGPROJECTITEMS);
|
| - dataObject = new DataObject();
|
| - dataObject.SetData(fmt, ptrToItems);
|
| -
|
| - // Now add the project path that sourced data. We just write the project file path.
|
| - IntPtr ptrToProjectPath = this.PackageSelectionData(new StringBuilder(this.GetMkDocument()), true);
|
| -
|
| - if(ptrToProjectPath != IntPtr.Zero)
|
| - {
|
| - dataObject.SetData(DragDropHelper.CreateFormatEtc(DragDropHelper.CF_VSPROJECTCLIPDESCRIPTOR), ptrToProjectPath);
|
| - }
|
| -
|
| - if(cutHighlightItems)
|
| - {
|
| - bool first = true;
|
| - IVsUIHierarchyWindow w = UIHierarchyUtilities.GetUIHierarchyWindow(this.site, HierarchyNode.SolutionExplorer);
|
| -
|
| - foreach(HierarchyNode node in this.ItemsDraggedOrCutOrCopied)
|
| - {
|
| - ErrorHandler.ThrowOnFailure(w.ExpandItem((IVsUIHierarchy)this, node.ID, first ? EXPANDFLAGS.EXPF_CutHighlightItem : EXPANDFLAGS.EXPF_AddCutHighlightItem));
|
| - first = false;
|
| - }
|
| - }
|
| - }
|
| - catch(COMException e)
|
| - {
|
| - Trace.WriteLine("Exception : " + e.Message);
|
| -
|
| - dataObject = null;
|
| - }
|
| -
|
| - return dataObject;
|
| - }
|
| -
|
| -
|
| - /// <summary>
|
| - /// This is used to recursively add a folder from an other project.
|
| - /// Note that while we copy the folder content completely, we only
|
| - /// add to the project items which are part of the source project.
|
| - /// </summary>
|
| - /// <param name="folderToAdd">Project reference (from data object) using the format: {Guid}|project|folderPath</param>
|
| - /// <param name="targetNode">Node to add the new folder to</param>
|
| - protected internal virtual void AddFolderFromOtherProject(string folderToAdd, HierarchyNode targetNode)
|
| - {
|
| - if(String.IsNullOrEmpty(folderToAdd))
|
| - throw new ArgumentNullException("folderToAdd");
|
| - if(targetNode == null)
|
| - throw new ArgumentNullException("targetNode");
|
| -
|
| - // Split the reference in its 3 parts
|
| - int index1 = Guid.Empty.ToString("B").Length;
|
| - if(index1 + 1 >= folderToAdd.Length)
|
| - throw new ArgumentOutOfRangeException("folderToAdd");
|
| -
|
| - // Get the Guid
|
| - string guidString = folderToAdd.Substring(1, index1 - 2);
|
| - Guid projectInstanceGuid = new Guid(guidString);
|
| -
|
| - // Get the project path
|
| - int index2 = folderToAdd.IndexOf('|', index1 + 1);
|
| - if(index2 < 0 || index2 + 1 >= folderToAdd.Length)
|
| - throw new ArgumentOutOfRangeException("folderToAdd");
|
| -
|
| - // Finally get the source path
|
| - string folder = folderToAdd.Substring(index2 + 1);
|
| -
|
| - // Get the target path
|
| - string folderName = Path.GetFileName(Path.GetDirectoryName(folder));
|
| - string targetPath = Path.Combine(GetBaseDirectoryForAddingFiles(targetNode), folderName);
|
| -
|
| - // Recursively copy the directory to the new location
|
| - Utilities.RecursivelyCopyDirectory(folder, targetPath);
|
| -
|
| - // Retrieve the project from which the items are being copied
|
| - IVsHierarchy sourceHierarchy;
|
| - IVsSolution solution = (IVsSolution)GetService(typeof(SVsSolution));
|
| - ErrorHandler.ThrowOnFailure(solution.GetProjectOfGuid(ref projectInstanceGuid, out sourceHierarchy));
|
| -
|
| - // Then retrieve the item ID of the item to copy
|
| - uint itemID = VSConstants.VSITEMID_ROOT;
|
| - ErrorHandler.ThrowOnFailure(sourceHierarchy.ParseCanonicalName(folder, out itemID));
|
| -
|
| - // Ensure we don't end up in an endless recursion
|
| - if(Utilities.IsSameComObject(this, sourceHierarchy))
|
| - {
|
| - HierarchyNode cursorNode = targetNode;
|
| - while(cursorNode != null)
|
| - {
|
| - if(String.Compare(folder, cursorNode.GetMkDocument(), StringComparison.OrdinalIgnoreCase) == 0)
|
| - throw new Exception();
|
| - cursorNode = cursorNode.Parent;
|
| - }
|
| - }
|
| -
|
| - // Now walk the source project hierarchy to see which node needs to be added.
|
| - WalkSourceProjectAndAdd(sourceHierarchy, itemID, targetNode, false);
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Recursive method that walk a hierarchy and add items it find to our project.
|
| - /// Note that this is meant as an helper to the Copy&Paste/Drag&Drop functionality.
|
| - /// </summary>
|
| - /// <param name="sourceHierarchy">Hierarchy to walk</param>
|
| - /// <param name="itemId">Item ID where to start walking the hierarchy</param>
|
| - /// <param name="targetNode">Node to start adding to</param>
|
| - /// <param name="addSibblings">Typically false on first call and true after that</param>
|
| - protected virtual void WalkSourceProjectAndAdd(IVsHierarchy sourceHierarchy, uint itemId, HierarchyNode targetNode, bool addSiblings)
|
| - {
|
| - // Before we start the walk, add the current node
|
| - object variant = null;
|
| - HierarchyNode newNode = targetNode;
|
| - if(itemId != VSConstants.VSITEMID_NIL)
|
| - {
|
| - // Calculate the corresponding path in our project
|
| - string source;
|
| - ErrorHandler.ThrowOnFailure(((IVsProject)sourceHierarchy).GetMkDocument(itemId, out source));
|
| - string name = Path.GetFileName(source.TrimEnd(new char[] { '/', '\\' }));
|
| - string targetPath = Path.Combine(GetBaseDirectoryForAddingFiles(targetNode), name);
|
| -
|
| - // See if this is a linked item (file can be linked, not folders)
|
| - ErrorHandler.ThrowOnFailure(sourceHierarchy.GetProperty(itemId, (int)__VSHPROPID.VSHPROPID_BrowseObject, out variant), VSConstants.E_NOTIMPL);
|
| - VSLangProj.FileProperties fileProperties = variant as VSLangProj.FileProperties;
|
| - if(fileProperties != null && fileProperties.IsLink)
|
| - {
|
| - // Since we don't support linked item, we make a copy of the file into our storage where it would have been linked
|
| - File.Copy(source, targetPath, true);
|
| - }
|
| -
|
| - newNode = AddNodeIfTargetExistInStorage(targetNode, name, targetPath);
|
| -
|
| -
|
| - // Start with child nodes (depth first)
|
| - variant = null;
|
| - ErrorHandler.ThrowOnFailure(sourceHierarchy.GetProperty(itemId, (int)__VSHPROPID.VSHPROPID_FirstVisibleChild, out variant));
|
| - uint currentItemID = (uint)(int)variant;
|
| - WalkSourceProjectAndAdd(sourceHierarchy, currentItemID, newNode, true);
|
| -
|
| - if(addSiblings)
|
| - {
|
| - // Then look at siblings
|
| - currentItemID = itemId;
|
| - while(currentItemID != VSConstants.VSITEMID_NIL)
|
| - {
|
| - variant = null;
|
| - ErrorHandler.ThrowOnFailure(sourceHierarchy.GetProperty(itemId, (int)__VSHPROPID.VSHPROPID_NextVisibleSibling, out variant));
|
| - currentItemID = (uint)(int)variant;
|
| - WalkSourceProjectAndAdd(sourceHierarchy, currentItemID, targetNode, true);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Add an existing item (file/folder) to the project if it already exist in our storage.
|
| - /// </summary>
|
| - /// <param name="parentNode">Node to that this item to</param>
|
| - /// <param name="name">Name of the item being added</param>
|
| - /// <param name="targetPath">Path of the item being added</param>
|
| - /// <returns>Node that was added</returns>
|
| - protected virtual HierarchyNode AddNodeIfTargetExistInStorage(HierarchyNode parentNode, string name, string targetPath)
|
| - {
|
| - HierarchyNode newNode = parentNode;
|
| - // If the file/directory exist, add a node for it
|
| - if(File.Exists(targetPath))
|
| - {
|
| - VSADDRESULT[] result = new VSADDRESULT[1];
|
| - ErrorHandler.ThrowOnFailure(this.AddItem(parentNode.ID, VSADDITEMOPERATION.VSADDITEMOP_OPENFILE, name, 1, new string[] { targetPath }, IntPtr.Zero, result));
|
| - if(result[0] != VSADDRESULT.ADDRESULT_Success)
|
| - throw new Exception();
|
| - newNode = this.FindChild(targetPath);
|
| - if(newNode == null)
|
| - throw new Exception();
|
| - }
|
| - else if(Directory.Exists(targetPath))
|
| - {
|
| - newNode = this.CreateFolderNodes(targetPath);
|
| - }
|
| - return newNode;
|
| - }
|
| - #endregion
|
| -
|
| - #region non-virtual methods
|
| - /// <summary>
|
| - /// Handle the Cut operation to the clipboard
|
| - /// </summary>
|
| - protected internal override int CutToClipboard()
|
| - {
|
| - int returnValue = (int)OleConstants.OLECMDERR_E_NOTSUPPORTED;
|
| - try
|
| - {
|
| - this.RegisterClipboardNotifications(true);
|
| -
|
| - // Create our data object and change the selection to show item(s) being cut
|
| - IOleDataObject dataObject = this.PackageSelectionDataObject(true);
|
| - if(dataObject != null)
|
| - {
|
| - this.SourceDraggedOrCutOrCopied = true;
|
| -
|
| - // Add our cut item(s) to the clipboard
|
| - ErrorHandler.ThrowOnFailure(UnsafeNativeMethods.OleSetClipboard(dataObject));
|
| -
|
| - // Inform VS (UiHierarchyWindow) of the cut
|
| - IVsUIHierWinClipboardHelper clipboardHelper = (IVsUIHierWinClipboardHelper)GetService(typeof(SVsUIHierWinClipboardHelper));
|
| - if(clipboardHelper == null)
|
| - {
|
| - return VSConstants.E_FAIL;
|
| - }
|
| -
|
| - returnValue = ErrorHandler.ThrowOnFailure(clipboardHelper.Cut(dataObject));
|
| - }
|
| - }
|
| - catch(COMException e)
|
| - {
|
| - Trace.WriteLine("Exception : " + e.Message);
|
| - returnValue = e.ErrorCode;
|
| - }
|
| -
|
| - return returnValue;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Handle the Copy operation to the clipboard
|
| - /// </summary>
|
| - protected internal override int CopyToClipboard()
|
| - {
|
| - int returnValue = (int)OleConstants.OLECMDERR_E_NOTSUPPORTED;
|
| - try
|
| - {
|
| - this.RegisterClipboardNotifications(true);
|
| -
|
| - // Create our data object and change the selection to show item(s) being copy
|
| - IOleDataObject dataObject = this.PackageSelectionDataObject(false);
|
| - if(dataObject != null)
|
| - {
|
| - this.SourceDraggedOrCutOrCopied = true;
|
| -
|
| - // Add our copy item(s) to the clipboard
|
| - ErrorHandler.ThrowOnFailure(UnsafeNativeMethods.OleSetClipboard(dataObject));
|
| -
|
| - // Inform VS (UiHierarchyWindow) of the copy
|
| - IVsUIHierWinClipboardHelper clipboardHelper = (IVsUIHierWinClipboardHelper)GetService(typeof(SVsUIHierWinClipboardHelper));
|
| - if(clipboardHelper == null)
|
| - {
|
| - return VSConstants.E_FAIL;
|
| - }
|
| - returnValue = ErrorHandler.ThrowOnFailure(clipboardHelper.Copy(dataObject));
|
| - }
|
| - }
|
| - catch(COMException e)
|
| - {
|
| - Trace.WriteLine("Exception : " + e.Message);
|
| - returnValue = e.ErrorCode;
|
| - }
|
| - catch(ArgumentException e)
|
| - {
|
| - Trace.WriteLine("Exception : " + e.Message);
|
| - returnValue = Marshal.GetHRForException(e);
|
| - }
|
| -
|
| - return returnValue;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Handle the Paste operation to a targetNode
|
| - /// </summary>
|
| - protected internal override int PasteFromClipboard(HierarchyNode targetNode)
|
| - {
|
| - int returnValue = (int)OleConstants.OLECMDERR_E_NOTSUPPORTED;
|
| -
|
| - //Get the clipboardhelper service and use it after processing dataobject
|
| - IVsUIHierWinClipboardHelper clipboardHelper = (IVsUIHierWinClipboardHelper)GetService(typeof(SVsUIHierWinClipboardHelper));
|
| - if(clipboardHelper == null)
|
| - {
|
| - return VSConstants.E_FAIL;
|
| - }
|
| -
|
| - try
|
| - {
|
| - //Get dataobject from clipboard
|
| - IOleDataObject dataObject = null;
|
| - ErrorHandler.ThrowOnFailure(UnsafeNativeMethods.OleGetClipboard(out dataObject));
|
| - if(dataObject == null)
|
| - {
|
| - return VSConstants.E_UNEXPECTED;
|
| - }
|
| -
|
| - DropEffect dropEffect = DropEffect.None;
|
| - DropDataType dropDataType = DropDataType.None;
|
| - try
|
| - {
|
| - dropDataType = this.ProcessSelectionDataObject(dataObject, targetNode.GetDragTargetHandlerNode());
|
| - dropEffect = this.QueryDropEffect(dropDataType, 0);
|
| - }
|
| - catch(ExternalException e)
|
| - {
|
| - Trace.WriteLine("Exception : " + e.Message);
|
| -
|
| - // If it is a drop from windows and we get any kind of error ignore it. This
|
| - // prevents bogus messages from the shell from being displayed
|
| - if(dropDataType != DropDataType.Shell)
|
| - {
|
| - throw;
|
| - }
|
| - }
|
| - finally
|
| - {
|
| - // Inform VS (UiHierarchyWindow) of the paste
|
| - returnValue = clipboardHelper.Paste(dataObject, (uint)dropEffect);
|
| - }
|
| - }
|
| - catch(COMException e)
|
| - {
|
| - Trace.WriteLine("Exception : " + e.Message);
|
| -
|
| - returnValue = e.ErrorCode;
|
| - }
|
| -
|
| - return returnValue;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Determines if the paste command should be allowed.
|
| - /// </summary>
|
| - /// <returns></returns>
|
| - protected internal override bool AllowPasteCommand()
|
| - {
|
| - IOleDataObject dataObject = null;
|
| - try
|
| - {
|
| - ErrorHandler.ThrowOnFailure(UnsafeNativeMethods.OleGetClipboard(out dataObject));
|
| - if(dataObject == null)
|
| - {
|
| - return false;
|
| - }
|
| -
|
| - // First see if this is a set of storage based items
|
| - FORMATETC format = DragDropHelper.CreateFormatEtc((ushort)DragDropHelper.CF_VSSTGPROJECTITEMS);
|
| - if(dataObject.QueryGetData(new FORMATETC[] { format }) == VSConstants.S_OK)
|
| - return true;
|
| - // Try reference based items
|
| - format = DragDropHelper.CreateFormatEtc((ushort)DragDropHelper.CF_VSREFPROJECTITEMS);
|
| - if(dataObject.QueryGetData(new FORMATETC[] { format }) == VSConstants.S_OK)
|
| - return true;
|
| - // Try windows explorer files format
|
| - format = DragDropHelper.CreateFormatEtc((ushort)NativeMethods.CF_HDROP);
|
| - return (dataObject.QueryGetData(new FORMATETC[] { format }) == VSConstants.S_OK);
|
| - }
|
| - // We catch External exceptions since it might be that it is not our data on the clipboard.
|
| - catch(ExternalException e)
|
| - {
|
| - Trace.WriteLine("Exception :" + e.Message);
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Register/Unregister for Clipboard events for the UiHierarchyWindow (solution explorer)
|
| - /// </summary>
|
| - /// <param name="register">true for register, false for unregister</param>
|
| - protected internal override void RegisterClipboardNotifications(bool register)
|
| - {
|
| - // Get the UiHierarchy window clipboard helper service
|
| - IVsUIHierWinClipboardHelper clipboardHelper = (IVsUIHierWinClipboardHelper)GetService(typeof(SVsUIHierWinClipboardHelper));
|
| - if(clipboardHelper == null)
|
| - {
|
| - return;
|
| - }
|
| -
|
| - if(register && this.copyPasteCookie == 0)
|
| - {
|
| - // Register
|
| - ErrorHandler.ThrowOnFailure(clipboardHelper.AdviseClipboardHelperEvents(this, out this.copyPasteCookie));
|
| - Debug.Assert(this.copyPasteCookie != 0, "AdviseClipboardHelperEvents returned an invalid cookie");
|
| - }
|
| - else if(!register && this.copyPasteCookie != 0)
|
| - {
|
| - // Unregister
|
| - ErrorHandler.ThrowOnFailure(clipboardHelper.UnadviseClipboardHelperEvents(this.copyPasteCookie));
|
| - this.copyPasteCookie = 0;
|
| - }
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Process dataobject from Drag/Drop/Cut/Copy/Paste operation
|
| - /// </summary>
|
| - /// <remarks>The targetNode is set if the method is called from a drop operation, otherwise it is null</remarks>
|
| - internal DropDataType ProcessSelectionDataObject(IOleDataObject dataObject, HierarchyNode targetNode)
|
| - {
|
| - DropDataType dropDataType = DropDataType.None;
|
| - bool isWindowsFormat = false;
|
| -
|
| - // Try to get it as a directory based project.
|
| - List<string> filesDropped = DragDropHelper.GetDroppedFiles(DragDropHelper.CF_VSSTGPROJECTITEMS, dataObject, out dropDataType);
|
| - if(filesDropped.Count == 0)
|
| - {
|
| - filesDropped = DragDropHelper.GetDroppedFiles(DragDropHelper.CF_VSREFPROJECTITEMS, dataObject, out dropDataType);
|
| - }
|
| - if(filesDropped.Count == 0)
|
| - {
|
| - filesDropped = DragDropHelper.GetDroppedFiles(NativeMethods.CF_HDROP, dataObject, out dropDataType);
|
| - isWindowsFormat = (filesDropped.Count > 0);
|
| - }
|
| -
|
| - if(dropDataType != DropDataType.None && filesDropped.Count > 0)
|
| - {
|
| - string[] filesDroppedAsArray = filesDropped.ToArray();
|
| -
|
| - HierarchyNode node = (targetNode == null) ? this : targetNode;
|
| -
|
| - // For directory based projects the content of the clipboard is a double-NULL terminated list of Projref strings.
|
| - if(isWindowsFormat)
|
| - {
|
| - // This is the code path when source is windows explorer
|
| - VSADDRESULT[] vsaddresults = new VSADDRESULT[1];
|
| - vsaddresults[0] = VSADDRESULT.ADDRESULT_Failure;
|
| - int addResult = AddItem(node.ID, VSADDITEMOPERATION.VSADDITEMOP_OPENFILE, null, (uint)filesDropped.Count, filesDroppedAsArray, IntPtr.Zero, vsaddresults);
|
| - if(addResult != VSConstants.S_OK && addResult != VSConstants.S_FALSE && addResult != (int)OleConstants.OLECMDERR_E_CANCELED
|
| - && vsaddresults[0] != VSADDRESULT.ADDRESULT_Success)
|
| - {
|
| - ErrorHandler.ThrowOnFailure(addResult);
|
| - }
|
| -
|
| - return dropDataType;
|
| - }
|
| - else
|
| - {
|
| - if(AddFilesFromProjectReferences(node, filesDroppedAsArray))
|
| - {
|
| - return dropDataType;
|
| - }
|
| - }
|
| - }
|
| -
|
| - // If we reached this point then the drop data must be set to None.
|
| - // Otherwise the OnPaste will be called with a valid DropData and that would actually delete the item.
|
| - return DropDataType.None;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Get the dropdatatype from the dataobject
|
| - /// </summary>
|
| - /// <param name="pDataObject">The dataobject to be analysed for its format</param>
|
| - /// <returns>dropdatatype or none if dataobject does not contain known format</returns>
|
| - internal static DropDataType QueryDropDataType(IOleDataObject pDataObject)
|
| - {
|
| - if(pDataObject == null)
|
| - {
|
| - return DropDataType.None;
|
| - }
|
| -
|
| - // known formats include File Drops (as from WindowsExplorer),
|
| - // VSProject Reference Items and VSProject Storage Items.
|
| - FORMATETC fmt = DragDropHelper.CreateFormatEtc(NativeMethods.CF_HDROP);
|
| -
|
| - if(DragDropHelper.QueryGetData(pDataObject, ref fmt) == VSConstants.S_OK)
|
| - {
|
| - return DropDataType.Shell;
|
| - }
|
| -
|
| - fmt.cfFormat = DragDropHelper.CF_VSREFPROJECTITEMS;
|
| - if(DragDropHelper.QueryGetData(pDataObject, ref fmt) == VSConstants.S_OK)
|
| - {
|
| - // Data is from a Ref-based project.
|
| - return DropDataType.VsRef;
|
| - }
|
| -
|
| - fmt.cfFormat = DragDropHelper.CF_VSSTGPROJECTITEMS;
|
| - if(DragDropHelper.QueryGetData(pDataObject, ref fmt) == VSConstants.S_OK)
|
| - {
|
| - return DropDataType.VsStg;
|
| - }
|
| -
|
| - return DropDataType.None;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Returns the drop effect.
|
| - /// </summary>
|
| - /// <remarks>
|
| - /// // A directory based project should perform as follow:
|
| - /// NO MODIFIER
|
| - /// - COPY if not from current hierarchy,
|
| - /// - MOVE if from current hierarchy
|
| - /// SHIFT DRAG - MOVE
|
| - /// CTRL DRAG - COPY
|
| - /// CTRL-SHIFT DRAG - NO DROP (used for reference based projects only)
|
| - /// </remarks>
|
| - internal DropEffect QueryDropEffect(DropDataType dropDataType, uint grfKeyState)
|
| - {
|
| - //Validate the dropdatatype
|
| - if((dropDataType != DropDataType.Shell) && (dropDataType != DropDataType.VsRef) && (dropDataType != DropDataType.VsStg))
|
| - {
|
| - return DropEffect.None;
|
| - }
|
| -
|
| - // CTRL-SHIFT
|
| - if((grfKeyState & NativeMethods.MK_CONTROL) != 0 && (grfKeyState & NativeMethods.MK_SHIFT) != 0)
|
| - {
|
| - // Because we are not referenced base, we don't support link
|
| - return DropEffect.None;
|
| - }
|
| -
|
| - // CTRL
|
| - if((grfKeyState & NativeMethods.MK_CONTROL) != 0)
|
| - return DropEffect.Copy;
|
| -
|
| - // SHIFT
|
| - if((grfKeyState & NativeMethods.MK_SHIFT) != 0)
|
| - return DropEffect.Move;
|
| -
|
| - // no modifier
|
| - if(this.SourceDraggedOrCutOrCopied)
|
| - {
|
| - return DropEffect.Move;
|
| - }
|
| - else
|
| - {
|
| - return DropEffect.Copy;
|
| - }
|
| - }
|
| -
|
| - internal void CleanupSelectionDataObject(bool dropped, bool cut, bool moved)
|
| - {
|
| - this.CleanupSelectionDataObject(dropped, cut, moved, false);
|
| - }
|
| -
|
| - /// <summary>
|
| - /// After a drop or paste, will use the dwEffects
|
| - /// to determine whether we need to clean up the source nodes or not. If
|
| - /// justCleanup is set, it only does the cleanup work.
|
| - /// </summary>
|
| - internal void CleanupSelectionDataObject(bool dropped, bool cut, bool moved, bool justCleanup)
|
| - {
|
| - if(this.ItemsDraggedOrCutOrCopied == null || this.ItemsDraggedOrCutOrCopied.Count == 0)
|
| - {
|
| - return;
|
| - }
|
| -
|
| - try
|
| - {
|
| - IVsUIHierarchyWindow w = UIHierarchyUtilities.GetUIHierarchyWindow(this.site, HierarchyNode.SolutionExplorer);
|
| - foreach(HierarchyNode node in this.ItemsDraggedOrCutOrCopied)
|
| - {
|
| - if((moved && (cut || dropped) && !justCleanup))
|
| - {
|
| - // do not close it if the doc is dirty or we do not own it
|
| - 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 || (isOpen && !isOpenedByUs))
|
| - {
|
| - continue;
|
| - }
|
| -
|
| - // close it if opened
|
| - if(isOpen)
|
| - {
|
| - manager.Close(__FRAMECLOSE.FRAMECLOSE_NoSave);
|
| - }
|
| - }
|
| -
|
| - node.Remove(true);
|
| - }
|
| - else if(w != null)
|
| - {
|
| - ErrorHandler.ThrowOnFailure(w.ExpandItem((IVsUIHierarchy)this, node.ID, EXPANDFLAGS.EXPF_UnCutHighlightItem));
|
| - }
|
| - }
|
| - }
|
| - finally
|
| - {
|
| - try
|
| - {
|
| - // Now delete the memory allocated by the packaging of datasources.
|
| - // If we just did a cut, or we are told to cleanup, then we need to free the data object. Otherwise, we leave it
|
| - // alone so that you can continue to paste the data in new locations.
|
| - if(moved || cut || justCleanup)
|
| - {
|
| - this.ItemsDraggedOrCutOrCopied.Clear();
|
| - this.CleanAndFlushClipboard();
|
| - }
|
| - }
|
| - finally
|
| - {
|
| - this.dropDataType = DropDataType.None;
|
| - }
|
| - }
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Moves files from one part of our project to another.
|
| - /// </summary>
|
| - /// <param name="targetNode">the targetHandler node</param>
|
| - /// <param name="projectReferences">List of projectref string</param>
|
| - /// <returns>true if succeeded</returns>
|
| - internal bool AddFilesFromProjectReferences(HierarchyNode targetNode, string[] projectReferences)
|
| - {
|
| - //Validate input
|
| - if(projectReferences == null)
|
| - {
|
| - throw new ArgumentException(SR.GetString(SR.InvalidParameter, CultureInfo.CurrentUICulture), "projectReferences");
|
| - }
|
| - if(targetNode == null)
|
| - {
|
| - throw new InvalidOperationException();
|
| - }
|
| -
|
| - //Iteratively add files from projectref
|
| - foreach(string projectReference in projectReferences)
|
| - {
|
| - if(projectReference == null)
|
| - {
|
| - // bad projectref, bail out
|
| - return false;
|
| - }
|
| - if(projectReference.EndsWith("/", StringComparison.Ordinal) || projectReference.EndsWith("\\", StringComparison.Ordinal))
|
| - {
|
| - AddFolderFromOtherProject(projectReference, targetNode);
|
| - }
|
| - else if(!AddFileToNodeFromProjectReference(projectReference, targetNode))
|
| - {
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - return true;
|
| - }
|
| -
|
| - #endregion
|
| -
|
| - #region private helper methods
|
| - /// <summary>
|
| - /// Empties all the data structures added to the clipboard and flushes the clipboard.
|
| - /// </summary>
|
| - private void CleanAndFlushClipboard()
|
| - {
|
| - IOleDataObject oleDataObject = null;
|
| - ErrorHandler.ThrowOnFailure(UnsafeNativeMethods.OleGetClipboard(out oleDataObject));
|
| - if(oleDataObject == null)
|
| - {
|
| - return;
|
| - }
|
| -
|
| -
|
| - string sourceProjectPath = DragDropHelper.GetSourceProjectPath(oleDataObject);
|
| -
|
| - if(!String.IsNullOrEmpty(sourceProjectPath) && NativeMethods.IsSamePath(sourceProjectPath, this.GetMkDocument()))
|
| - {
|
| - ErrorHandler.ThrowOnFailure(UnsafeNativeMethods.OleFlushClipboard());
|
| - int clipboardOpened = 0;
|
| - try
|
| - {
|
| - ErrorHandler.ThrowOnFailure(clipboardOpened = UnsafeNativeMethods.OpenClipboard(IntPtr.Zero));
|
| - ErrorHandler.ThrowOnFailure(UnsafeNativeMethods.EmptyClipboard());
|
| - }
|
| - finally
|
| - {
|
| - if(clipboardOpened == 1)
|
| - {
|
| - ErrorHandler.ThrowOnFailure(UnsafeNativeMethods.CloseClipboard());
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - private IntPtr PackageSelectionData(StringBuilder sb, bool addEndFormatDelimiter)
|
| - {
|
| - if(sb == null || sb.ToString().Length == 0 || this.ItemsDraggedOrCutOrCopied.Count == 0)
|
| - {
|
| - return IntPtr.Zero;
|
| - }
|
| -
|
| - // Double null at end.
|
| - if(addEndFormatDelimiter)
|
| - {
|
| - if(sb.ToString()[sb.Length - 1] != '\0')
|
| - {
|
| - sb.Append('\0');
|
| - }
|
| - }
|
| -
|
| - // We request unmanaged permission to execute the below.
|
| - new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
|
| -
|
| - _DROPFILES df = new _DROPFILES();
|
| - int dwSize = Marshal.SizeOf(df);
|
| - Int16 wideChar = 0;
|
| - int dwChar = Marshal.SizeOf(wideChar);
|
| - int structSize = dwSize + ((sb.Length + 1) * dwChar);
|
| - IntPtr ptr = Marshal.AllocHGlobal(structSize);
|
| - df.pFiles = dwSize;
|
| - df.fWide = 1;
|
| - IntPtr data = IntPtr.Zero;
|
| - try
|
| - {
|
| - data = UnsafeNativeMethods.GlobalLock(ptr);
|
| - Marshal.StructureToPtr(df, data, false);
|
| - IntPtr strData = new IntPtr((long)data + dwSize);
|
| - DragDropHelper.CopyStringToHGlobal(sb.ToString(), strData, structSize);
|
| - }
|
| - finally
|
| - {
|
| - if(data != IntPtr.Zero)
|
| - UnsafeNativeMethods.GlobalUnLock(data);
|
| - }
|
| -
|
| - return ptr;
|
| - }
|
| -
|
| - #endregion
|
| - }
|
| -}
|
|
|