2010-08-01 3 views
5

Hé les gars, j'essaie d'obtenir les fichiers sélectionnés d'un dossier que l'utilisateur utilise. J'ai le code suivant qui est en cours d'exécution, mais uniquement sur les fichiers de bureau:Récupère les éléments sélectionnés du dossier avec WinAPI

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

J'ai essayé de la poignée de fenêtre avec GetForegroundWindow(), puis appeler le SHELLDLL_DefView sans succès.

Alors, comment puis-je changer les 3 premières lignes pour obtenir le handle du dossier en cours d'utilisation?

+0

Avez-vous une idée de la raison pour laquelle vText est toujours vide? retourne "\ 0 \ 0 \ 0 \ 0 \ 0" – Leila

+0

@abatishchev savez-vous pourquoi les noms de fichiers sont retournés comme \ 0 \ 0 \ 0 – Leila

Répondre

4

Cela fait beaucoup de piratage de faire quelque chose qui est explicitement supporté par les différents objets et interfaces shell. Certes, la documentation ne la rend pas facilement détectable, mais la fonctionnalité est là. Raymond Chen wrote a great article sur l'utilisation de ces interfaces. Il ne semble pas y avoir un moyen d'obtenir le dossier "en cours", bien que je suppose que vous pourriez obtenir les HWND et voir si la première est la fenêtre de premier plan.

+0

Thx pour le lien Je vais vérifier cela! – MUG4N

2

merci beaucoup. Tu m'as donné la bonne direction. Il est possible d'obtenir les fichiers sélectionnés d'un dossier:

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

Vous devrez ajouter l'objet COM SHDocVw (Microsoft Internet Controls) en tant que référence à votre projet. – boulaycote

+0

pouvez-vous s'il vous plaît montrer le code pour obtenir le handle variable et dire comment la fonction getSelectedFileOfActiveWindow doit être appelée dans main() – akki

+0

@ MUG4N J'ai un problème avec la création d'un handle, peut-être parce que je suis très nouveau sur C#. Pouvez-vous s'il vous plaît me pointer dans une certaine direction. Toute aide est grandement appréciée. Merci – akki

Questions connexes