c# windows winapi windows-explorer

c# - Obtener elementos seleccionados de la carpeta con WinAPI



windows windows-explorer (2)

Hola chicos, trato de obtener los archivos seleccionados de una carpeta que el usuario está usando. Tengo el siguiente código que ya se está ejecutando, pero solo en los archivos de escritorio:

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

Intenté obtener el identificador de ventana con GetForegroundWindow () y luego llamé a SHELLDLL_DefView sin éxito.

Entonces, ¿cómo puedo cambiar las primeras 3 filas para obtener el control de la carpeta actual en uso?


Es una gran cantidad de piratería para hacer algo que sea explícitamente compatible con los diversos objetos e interfaces de shell. De acuerdo, la documentación no lo hace fácil de detectar, pero la funcionalidad está ahí. Raymond Chen escribió un excelente artículo sobre el uso de estas interfaces. No parece haber una manera de obtener la carpeta "actual", aunque supongo que podría obtener los HWND y ver si alguno es la ventana de primer plano.


muchas gracias. Me diste la dirección correcta. Es posible obtener los archivos seleccionados de una carpeta:

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