【问题标题】:Get file path for drag-n-drop file on Windows Explorer在 Windows 资源管理器上获取拖放文件的文件路径
【发布时间】:2014-01-07 12:02:36
【问题描述】:

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

我有一个包含一些元素的 listView,我需要将它们放在 Windows Explorer 上。删除时,我只需要删除文件的路径,我不需要复制任何内容,只需要路径。

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

我找到的唯一解决方案:

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

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

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

【问题讨论】:

    标签: c# wpf drag-and-drop


    【解决方案1】:

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

    更好的解决方案是实现您自己的基本文件浏览器,然后作为应用程序的一部分,通过拖放操作访问文件路径会简单得多。无论哪种方式,你都有很多工作要做。

    【讨论】:

    • 嗨,谢谢你的回答 :) 我的应用程序已经有一个文件资源管理器,但它在远程路径上,并且下载文件的过程已经实现,我需要目标路径来开始我的下载程序。我的程序会生成一个从不同路径下载和上传到不同路径的队列,所以我只需要目标路径就可以使所有这些工作:)
    • 我知道没有干净的方法来获取文件被删除的文件路径。由于以下问题,我对此感兴趣:当使用移动(而不是复制)从我的应用程序中拖动文件并且该文件已存在于目标目录中时,我无法检测用户是否在 Windows 中选择了取消“替换文件对话框”(miksovsky.blogs.com/flowstate/WindowsLiveWriter/…),因此如果我将它从我的应用程序中删除(因为它应该被移动,而不是复制),文件将会丢失。或者有没有办法检测到?
    【解决方案2】:
    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 资源管理器窗口;将显示放置路径。

    【讨论】:

    • 谢谢,但我找不到 ExplorerHelper.GetActiveWindowHandle();我用了这个但不起作用,总是给 0:[DllImport("user32.dll", EntryPoint = "GetActiveWindow", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 静态extern IntPtr GetActiveWindowHandle();
    • 好的,我使用 GetForegroundWindow() 让它工作了,但是我无法获得用户丢弃的正确文件夹! GetActiveWindow() 不能解决这个问题,它指的是调用线程使用的活动窗口,而不是 explorer.exe。所以.. ExplorerHelper 在这里可以派上用场:D
    • 抱歉,再次从上面获取代码,我从 ExplorerHelper 类中添加了 GetActiveWindow,还添加了 GetForeGroundWindow()。我很好奇你现在能不能让它工作!
    • 感谢您的帮助 :) 可悲的是,GetForegroundWindow() 函数没有获得正确的放置目标 :( 如果你放在桌面上它会失败(返回 0),如果你放在一个文件夹,你没有得到那个文件夹路径。这是一个部分解决方案,很酷,很方便,但部分:(还是谢谢你!
    猜你喜欢
    • 1970-01-01
    • 2017-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-01
    • 2016-09-26
    相关资源
    最近更新 更多