在Windows资源管理器上获取drag-n-drop文件的文件路径

drag-n-drop是很多站点中讨论很多的话题(这也是),我也发现了很好的问题,但没有回答这个案例。

我有一个带有一些元素的listView ,我需要它们在Windows资源管理器上可以放置。 当删除时,我只需要删除它们的文件路径,我不需要复制任何东西,只需要路径。

类似的问题(以及他们为什么不适合我):

  • 拖放到桌面/资源管理器 (仅当您已经有要复制的文件并且没有提供路径时才有效)
  • http://blogs.msdn.com/b/delay/archive/2009/11/16/creating-something-from-nothing-and-knowing-it-developer-friendly-virtual-file-implementation-for-net- refined.aspx (这看起来不错,但它仍然创建一个虚拟文件并将其复制到该位置,所以我没有路径,仍然需要在我的目的地复制一些东西)

我找到的唯一解决方案:

http://www.codeproject.com/Articles/23207/Drag-and-Drop-to-Windows-Folder-C

这可以工作,但是以非常“不实际”的方式,它创建一个文件观察器,创建一个虚拟文件,让DragDrop函数复制它,观察它的创建位置,最后删除它。 在我的Windows8.1中测试它导致错误的资源管理器刷新,我仍然可以看到该文件,直到我刷新我的屏幕(F5)。

这是唯一的方法吗? 我仍然无法相信我无法以更简单的方式实现这一目标

想想它一会儿…如果你知道拖放,那么你就会知道拖动源担心将数据打包成正确的格式,拖动目标担心以正确的格式检索数据。 您的问题是您的拖动目标不在您的WPF应用程序中,因此在删除数据时您可以做的很少。

一个更好的解决方案是实现自己的基本文件浏览器,然后作为应用程序的一部分,使用拖放操作访问文件路径会更加简单。 不管怎样,你还有很多工作要做。

  1. 一旦开始从ListView拖动任何项目,就创建一个空的FileDrop项目。
  2. 由于拖动时鼠标按钮之一始终处于关闭状态,因此只要松开按下的鼠标按钮,就会启动一个触发事件的计时器。
  3. 释放按钮后,获取鼠标所在窗口的窗口句柄。 将该句柄与任何打开的Windows资源管理器窗口进
  4. 如果找到匹配的窗口,请获取该Windows资源管理器窗口的位置URL,并操纵该Windows资源管理器窗口的可用URL以获取(UNC)Windows路径。

在设计模式下创建Windows窗体并向其添加名称为lvFilesListView 。 将其AllowDrop属性设置为True 。 然后在表单中添加一个计时器并将其命名为dropTimer 。 将间隔设置为50 。 将Enabled设置为False 。 在dropTimer的事件中,双击,因此事件将是dropTimer_Tick

转到后面的代码并粘贴下面的代码。

 using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; namespace test { public partial class Form1 : Form { [DllImport("user32.dll")] static extern int GetForegroundWindow(); [DllImport("user32.dll")] static extern short GetKeyState(VirtualKeyStates nVirtKey); enum VirtualKeyStates : int { VK_LBUTTON = 0x01, VK_RBUTTON = 0x02, } bool IsKeyPressed(VirtualKeyStates testKey) { bool keyPressed = false; short result = GetKeyState(testKey); switch (result) { case 0: keyPressed = false; break; case 1: keyPressed = false; break; default: keyPressed = true; break; } return keyPressed; } int GetActiveWindowHandle() { const int nChars = 256; int handle = 0; StringBuilder Buff = new StringBuilder(nChars); handle = GetForegroundWindow(); if (GetWindowText(handle, Buff, nChars) > 0) return handle; else return 0; } private string GetWindowsExplorerPathFromWindowHandle(int handle) { // Add a project COM reference to Microsoft Internet Controls 1.1 SHDocVw.ShellWindows shellWindows = new SHDocVw.ShellWindowsClass(); string fileName; string path = ""; foreach ( SHDocVw.InternetExplorer ie in shellWindows ) { fileName = Path.GetFileNameWithoutExtension(ie.FullName).ToLower(); if (fileName.Equals("explorer") && ie.HWND == handle) { path = ie.LocationURL; path = path.ToLower(); path = path.Replace("file://", ""); if (path.StartsWith("/")) path = path.Substring(1); path = path.Replace("/", "\\"); if (!path.Contains(":")) // unc paths path = "\\\\" + path; break; } } return path; } // Replace the created event from the designer with this event: // private void lvFiles_ItemDrag(object sender, ItemDragEventArgs e) { // fake drag and drop effect (start) string dataFormat = DataFormats.FileDrop; string[] data = new string[1]; data[0] = ""; DataObject dataObject = new DataObject(dataFormat, data); // catch mouse events if (IsKeyPressed(VirtualKeyStates.VK_LBUTTON)) MouseButtonPressed = MouseButtons.Left; else if (IsKeyPressed(VirtualKeyStates.VK_RBUTTON)) MouseButtonPressed = MouseButtons.Right; else MouseButtonPressed = MouseButtons.None; if (MouseButtonPressed == MouseButtons.Left || MouseButtonPressed == MouseButtons.Right) this.dropTimer.Enabled = true; // fake drag and drop effect (launch) DoDragDrop(dataObject, DragDropEffects.Copy); } private void dropTimer_Tick(object sender, EventArgs e) { bool mouseButtonsReleased = false; if (MouseButtonPressed == MouseButtons.Left && !IsKeyPressed(VirtualKeyStates.VK_LBUTTON)) mouseButtonsReleased = true; else if (MouseButtonPressed == MouseButtons.Right && !IsKeyPressed(VirtualKeyStates.VK_RBUTTON)) mouseButtonsReleased = true; if (mouseButtonsReleased) { dropTimer.Enabled = false; int handle = GetActiveWindowHandle(); string dropPath = GetWindowsExplorerPathFromWindowHandle(handle); MessageBox.Show(dropPath); // Here is where the Windows Explorer path is shown } } } } 

以某种方式填充ListView并将任何ListView项拖动到Windows资源管理器窗口; 下降路径将显示。