Get file path for drag-n-drop file on Windows Explorer

后端 未结 2 612
执念已碎
执念已碎 2021-01-14 10:13

drag-n-drop is a pretty discussed topic in a lot sites (this too) and i found nice questions too, but no answer to this case.

I have a listView

2条回答
  •  隐瞒了意图╮
    2021-01-14 11:06

    1. Create an empty FileDrop item as soon as you start dragging any item from your ListView.
    2. As one of your mouse buttons is always down while dragging, start a timer which fires an event as soon as you release the pressed mouse button.
    3. When the button is released, get the window handle of the window where the mouse is located. Match that handle against any opened Windows Explorer window.
    4. If a matched window was found, get the location URL of that Windows Explorer Window and manipulate the available URL of that Windows Explorer window to get the (UNC) Windows path.

    Create a Windows Form in design mode and add a ListView to it with name lvFiles. Set its AllowDrop property to True. Then add a timer to the form and name it dropTimer. Set the interval to 50. Set Enabled to False. In the events of dropTimer, double click, so the event will be dropTimer_Tick.

    Go to code behind and paste code below.

    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
                }
            }
    
        }
    }
    

    Fill your ListView some way and drag any of the ListView item(s) to a Windows Explorer window; The drop path will show up.

提交回复
热议问题