代码之家  ›  专栏  ›  技术社区  ›  MUG4N

使用winapi获取文件夹的选定项

  •  5
  • MUG4N  · 技术社区  · 15 年前

    嘿,伙计们,我试着从用户正在使用的文件夹中获取选定的文件。我有以下代码已在运行,但仅在桌面文件上运行:

    private string selectedFiles()
    {
        // get the handle of the desktop listview
        IntPtr vHandle = WinApiWrapper.FindWindow("Progman", "Program Manager");
        vHandle = WinApiWrapper.FindWindowEx(vHandle, IntPtr.Zero, "SHELLDLL_DefView", null);
        vHandle = WinApiWrapper.FindWindowEx(vHandle, IntPtr.Zero, "SysListView32", "FolderView");
    
        //IntPtr vHandle = WinApiWrapper.GetForegroundWindow();
    
        //Get total count of the icons on the desktop
        int vItemCount = WinApiWrapper.SendMessage(vHandle, WinApiWrapper.LVM_GETITEMCOUNT, 0, 0);
        //MessageBox.Show(vItemCount.ToString());
        uint vProcessId;
        WinApiWrapper.GetWindowThreadProcessId(vHandle, out vProcessId);
        IntPtr vProcess = WinApiWrapper.OpenProcess(WinApiWrapper.PROCESS_VM_OPERATION | WinApiWrapper.PROCESS_VM_READ |
        WinApiWrapper.PROCESS_VM_WRITE, false, vProcessId);
        IntPtr vPointer = WinApiWrapper.VirtualAllocEx(vProcess, IntPtr.Zero, 4096,
        WinApiWrapper.MEM_RESERVE | WinApiWrapper.MEM_COMMIT, WinApiWrapper.PAGE_READWRITE);
        try
        {
            for (int j = 0; j < vItemCount; j++)
            {
                byte[] vBuffer = new byte[256];
                WinApiWrapper.LVITEM[] vItem = new WinApiWrapper.LVITEM[1];
                vItem[0].mask = WinApiWrapper.LVIF_TEXT;
                vItem[0].iItem = j;
                vItem[0].iSubItem = 0;
                vItem[0].cchTextMax = vBuffer.Length;
                vItem[0].pszText = (IntPtr)((int)vPointer + Marshal.SizeOf(typeof(WinApiWrapper.LVITEM)));
                uint vNumberOfBytesRead = 0;
                WinApiWrapper.WriteProcessMemory(vProcess, vPointer,
                Marshal.UnsafeAddrOfPinnedArrayElement(vItem, 0),
                Marshal.SizeOf(typeof(WinApiWrapper.LVITEM)), ref vNumberOfBytesRead);
                WinApiWrapper.SendMessage(vHandle, WinApiWrapper.LVM_GETITEMW, j, vPointer.ToInt32());
                WinApiWrapper.ReadProcessMemory(vProcess,
                (IntPtr)((int)vPointer + Marshal.SizeOf(typeof(WinApiWrapper.LVITEM))),
                Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0),
                vBuffer.Length, ref vNumberOfBytesRead);
                string vText = Encoding.Unicode.GetString(vBuffer, 0,
                (int)vNumberOfBytesRead);
                string IconName = vText;
    
                //Check if item is selected
                var result = WinApiWrapper.SendMessage(vHandle, WinApiWrapper.LVM_GETITEMSTATE, j, (int)WinApiWrapper.LVIS_SELECTED);
                if (result == WinApiWrapper.LVIS_SELECTED)
                {
                    return vText;
                }
            }
        }
        finally
        {
            WinApiWrapper.VirtualFreeEx(vProcess, vPointer, 0, WinApiWrapper.MEM_RELEASE);
            WinApiWrapper.CloseHandle(vProcess);
        }
        return String.Empty;
    }
    

    我尝试使用getForegroundWindow()获取窗口句柄,然后调用shelldll_defview,但没有成功。

    那么,如何更改前3行以获得当前使用的文件夹的句柄呢?

    2 回复  |  直到 13 年前
        1
  •  4
  •   Luke    15 年前

    要做一些由各种shell对象和接口显式支持的事情,需要进行大量的黑客攻击。当然,文档并不容易被发现,但是功能就在那里。雷蒙德陈 wrote a great article 关于使用这些接口。似乎没有一种方法可以获得“当前”文件夹,不过我想您可以获取hwnd并查看前台窗口是否有。

        2
  •  2
  •   Firo    13 年前

    非常感谢你。你给了我正确的方向。可以获取文件夹的选定文件:

    /// <summary>
    /// Get the selected file of the active window
    /// </summary>
    /// <param name="handle">Handle of active window</param>
    /// <returns></returns>
    public String getSelectedFileOfActiveWindow(Int32 handle)
    {
        try
        {
            // Required ref: SHDocVw (Microsoft Internet Controls COM Object)
            ShellWindows shellWindows = new SHDocVw.ShellWindows();
    
            foreach (InternetExplorer window in shellWindows)
            {
                if (window.HWND == handle)
                    return ((Shell32.IShellFolderViewDual2)window.Document).FocusedItem.Path;
            }                
        }
        catch (Exception)
        {
            return null;
        }
        return null;
    }