问题
I am trying to get a list of selected files from the Windows Desktop and the Explorer Windows. The requirement is that I should be able to retrieve the current selection from the active explorer window or the Desktop.
I have managed to put together the following code, after going through online resources, but it does not provide a list of selected items from the Desktop.
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);
}
}
}
Other than that, I tried the following but it just gives a list of all selected elements in all open explorer windows while ignoring the Desktop.
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);
}
}
So I just always end up with a list from the explorer windows and get no results even when no explorer windows are open. The current techniques seem to be ignoring the Desktop altogether.
I would really appreciate it if someone could help me out to get a list of selected files from the currently active window/desktop.
Thank You.
回答1:
It is easy for desktop since it is still a listview, just find the correct handle. list view is a child of the desktop handle.
Desktop
+- Progman (for backward compatibility)
+- Shell Def View
+- SysListView32 (even under 64 bit)
then you can do all listview operations on the list view. but other explorer windows does not contain a list view. Instead they use window with class DirectUIHWND
which is a mystery to many. I've just found a post that describes a way to the unravel that mystery.
http://smartbear.com/forums?forumid=81&threadid=68427#68428
I hope it helps.
回答2:
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);
}
}
回答3:
I think you should communicate between processes. Following topics will help.
This is an example of retrieving icons from desktop. List of desktop items and their current positions are fetched. http://social.msdn.microsoft.com/Forums/windows/en-US/d7df8a4d-fc0f-4b62-80c9-7768756456e6/how-can-i-get-desktops-icons-information-?forum=winforms
Here the parameter LVM_GETITEMSTATE can be used within the sample code from the link above. http://msdn.microsoft.com/en-us/library/windows/desktop/bb761053(v=vs.85).aspx
Good luck..
来源:https://stackoverflow.com/questions/19095199/get-list-of-selected-files-from-windows-desktop