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

后端 未结 2 613
执念已碎
执念已碎 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.

    0 讨论(0)
  • 2021-01-14 11:16

    Think about it for a minute... if you know about drag and drop, then you'll know that the drag source worries about packaging up the data into the correct format and the drag target worries about retrieving the data in the correct format. Your problem is that your drag target is not in your WPF application and so there is very little that you can do as the data is dropped.

    A much better solution would be to implement your own basic file browser and then as part of your application, it would be far simpler to access the file path with the drag and drop operation. Either way, you've got a lot of work to do.

    0 讨论(0)
提交回复
热议问题