获取Windows资源管理器上拖放文件的文件路径

时间:2014-01-07 12:02:37

标签: c# wpf drag-and-drop

drag-n-drop 是很多网站中讨论很多的主题(这也是),我也找到了不错的问题,但没有回答这个案例。

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

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

我找到的唯一解决方案:

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

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

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

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

  1. 在您开始拖动FileDrop中的任何项目后立即创建一个空ListView项。
  2. 当您的一个鼠标按钮在拖动时始终处于关闭状态时,启动一个计时器,只要您松开按下的鼠标按钮就会触发事件。
  3. 释放按钮时,获取鼠标所在窗口的窗口句柄。将该句柄与任何打开的Windows资源管理器窗口进行匹配。
  4. 如果找到匹配的窗口,请获取该Windows资源管理器窗口的位置URL,并操纵该Windows资源管理器窗口的可用URL以获取(UNC)Windows路径。
  5. 在设计模式下创建Windows窗体,并为其添加名称为ListView的{​​{1}}。将其lvFiles属性设置为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项目拖到Windows资源管理器窗口;下拉路径将显示。