10

我正在尝试从 Windows 桌面和资源管理器 Windows 中获取选定文件的列表。要求是我应该能够从活动的资源管理器窗口或桌面检索当前选择。

在浏览了在线资源后,我设法将以下代码放在一起,但它没有提供桌面中选定项目的列表。

ArrayList selected = new ArrayList();
var shell = new Shell32.Shell();
IntPtr handle = IntPtr.Zero;
handle = GetForegroundWindow();
int intHandle = handle.ToInt32();

//For each explorer
foreach (InternetExplorer window in new ShellWindowsClass())
{

    if (window.HWND == (int)handle)
    {
        Shell32.FolderItems items = ((Shell32.IShellFolderViewDual2)window.Document).SelectedItems();
        foreach (Shell32.FolderItem item in items)
        {
            selected.Add(item.Path);
        }
    }
}

除此之外,我尝试了以下操作,但它只是给出了所有打开的资源管理器窗口中所有选定元素的列表,而忽略了桌面。

string filename; = Path.GetFileNameWithoutExtension(window.FullName).ToLower();
if (filename.ToLowerInvariant() == "explorer")
{
    Shell32.FolderItems items = ((Shell32.IShellFolderViewDual2)window.Document).SelectedItems();
    foreach (Shell32.FolderItem item in items)
    {
        //MessageBox.Show(item.Path.ToString());
        selected.Add(item.Path);
    }
}

所以我总是从资源管理器窗口中得到一个列表,即使没有打开资源管理器窗口也没有得到任何结果。当前的技术似乎完全忽略了桌面。

如果有人可以帮助我从当前活动的窗口/桌面获取选定文件的列表,我将不胜感激。

谢谢你。

4

3 回答 3

1

桌面很容易,因为它仍然是列表视图,只需找到正确的句柄即可。列表视图是桌面句柄的子视图。

Desktop
+- Progman (for backward compatibility)
   +- Shell Def View
      +- SysListView32 (even under 64 bit)

然后您可以对列表视图进行所有列表视图操作。但其他资源管理器窗口不包含列表视图。相反,他们使用带有类的窗口,DirectUIHWND这对许多人来说是个谜。我刚刚找到了一篇文章,描述了一种解开这个谜团的方法。

http://smartbear.com/forums?forumid=81&threadid=68427#68428

我希望它有所帮助。

于 2013-10-10T08:08:46.387 回答
0
    using System.Runtime.InteropServices;

    public class ShellItems
    {
        [StructLayoutAttribute(LayoutKind.Sequential)]
        private struct LVITEM
        {
            public uint mask;
            public int iItem;
            public int iSubItem;
            public uint state;
            public uint stateMask;
            public IntPtr pszText;
            public int cchTextMax;
            public int iImage;
            public IntPtr lParam;
        }

        const int LVM_FIRST = 0x1000;
        const int LVM_GETSELECTEDCOUNT = 4146;
        const int LVM_GETNEXTITEM = LVM_FIRST + 12;
        const int LVNI_SELECTED = 2;
        const int LVM_GETITEMCOUNT = LVM_FIRST + 4;
        const int LVM_GETITEM = LVM_FIRST + 75;
        const int LVIF_TEXT = 0x0001;

        [DllImport("user32.dll", EntryPoint = "GetShellWindow")]
        public static extern System.IntPtr GetShellWindow();

        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);

        [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
        public static extern int SendMessagePtr(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);

        [DllImport("User32.DLL")]
        public static extern int SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);


        public int SelectedItemCount
        {
            get
            {
                return SendMessage(ShellListViewHandle, LVM_GETSELECTEDCOUNT, IntPtr.Zero.ToInt32(), IntPtr.Zero.ToInt32());
            }
        }
        public int Count
        {
            get
            {
                return SendMessage(ShellListViewHandle, LVM_GETITEMCOUNT, IntPtr.Zero.ToInt32(), IntPtr.Zero.ToInt32());
            }
        }
        public string GetItemText(int idx)
        {
            // Declare and populate the LVITEM structure
            LVITEM lvi = new LVITEM();
            lvi.mask = LVIF_TEXT;
            lvi.cchTextMax = 512;
            lvi.iItem = idx;            // the zero-based index of the ListView item
            lvi.iSubItem = 0;         // the one-based index of the subitem, or 0 if this
            //  structure refers to an item rather than a subitem
            lvi.pszText = Marshal.AllocHGlobal(512);

            // Send the LVM_GETITEM message to fill the LVITEM structure
            IntPtr ptrLvi = Marshal.AllocHGlobal(Marshal.SizeOf(lvi));
            Marshal.StructureToPtr(lvi, ptrLvi, false);
            try
            {
                SendMessagePtr(ShellListViewHandle, LVM_GETITEM, IntPtr.Zero, ptrLvi);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }

            // Extract the text of the specified item
            string itemText = Marshal.PtrToStringAuto(lvi.pszText);
            return itemText;
        }

        IntPtr ShellListViewHandle
        {
            get
            {
                IntPtr _ProgMan = GetShellWindow();
                IntPtr _SHELLDLL_DefViewParent = _ProgMan;
                IntPtr _SHELLDLL_DefView = FindWindowEx(_ProgMan, IntPtr.Zero, "SHELLDLL_DefView", null);
                IntPtr _SysListView32 = FindWindowEx(_SHELLDLL_DefView, IntPtr.Zero, "SysListView32", "FolderView");
                return _SysListView32;
            }
        }

        public int GetSelectedItemIndex(int iPos = -1)
        {
            return SendMessage(ShellListViewHandle, LVM_GETNEXTITEM, iPos, LVNI_SELECTED);
        }
    }
于 2013-10-17T09:23:16.207 回答
0

我认为你应该在进程之间进行通信。以下主题将有所帮助。

这是从桌面检索图标的示例。获取桌面项目列表及其当前位置。 http://social.msdn.microsoft.com/Forums/windows/en-US/d7df8a4d-fc0f-4b62-80c9-7768756456e6/how-can-i-get-desktops-icons-information-?forum=winforms

这里可以在上面链接的示例代码中使用参数 LVM_GETITEMSTATE。 http://msdn.microsoft.com/en-us/library/windows/desktop/bb761053(v=vs.85).aspx

祝你好运..

于 2013-10-10T08:10:04.187 回答