Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get selected items of folder with WinAPI

I try to get the selected files of a folder which the user is using. I have the following code which is already running, but only on desktop files:

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

I tried to get the window handle with GetForegroundWindow() and then call the SHELLDLL_DefView without success.

So how can I change the first 3 rows to get me the handle of the current folder in use?

like image 552
MUG4N Avatar asked Aug 01 '10 17:08

MUG4N


1 Answers

That's a lot of hacking to do something that is explicitly supported by the various shell objects and interfaces. Granted the documentation doesn't make it easily discoverable, but the functionality is there. Raymond Chen wrote a great article about using these interfaces. There doesn't appear to be a way to get the "current" folder, though I guess you could get the HWNDs and see if any is the foreground window.

like image 113
Luke Avatar answered Sep 30 '22 14:09

Luke