两种获取桌面图标的方法,以及查看几个系统图标隐藏状态的方法


通过IShellFolder获取

// 主要流程

// 初始化
OleInitialize(NULL);

// 获取IShellFolder对象
CComPtr<IShellFolder> pShellFolder;
SHGetDesktopFolder(&pShellFolder));

// 获取item集合IEnumIDList
CComPtr<IEnumIDList> pIds;
pShellFolder->EnumObjects(0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pIds);

// 遍历
ITEMIDLIST *subItem = nullptr;
ULONG cIds = 0;
while (pIds->Next(1, &subItem, &cIds) == S_OK)
{
    // 获取图标显示名称,第二个参数详情参考MSDN
    // 第二个参数改为(SHGDN_FORPARSING | SHGDN_INFOLDER)可获得图标路径,系统图标将会显示为CLSID
    // 第二个参数改为(SHGDN_FORPARSING),系统图标以及OneDrive等几个也会显示为CLSID
    STRRET strName;
    pShellFolder->GetDisplayNameOf(subItem, SHGDN_NORMAL, &strName);
    LPWSTR pName = nullptr;
    ::StrRetToStrW(&strName, subItem, &pName);

    // 获取图标所对应的icon(HICON)格式:
    SHFILEINFO stSHFileInfo;
    HIMAGELIST hImgList = (HIMAGELIST)::SHGetFileInfo((LPCWSTR)&(*subItem), 0,
                &stSHFileInfo, sizeof(SHFILEINFO), SHGFI_PIDL | SHGFI_ICON | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
    HICON hIcon = ImageList_GetIcon(hImgList , stSHFileInfo.iIcon, 0);

    // 获取图标所对应的icon(HBITMAP)格式:
    IShellItem *psia = NULL;
    IShellItemImageFactory *psiif = NULL;
    ::SHCreateShellItem(NULL, pShellFolder, subItem, &psia)) && SUCCEEDED(psia->QueryInterface(IID_PPV_ARGS(&psiif));
    const SIZE size = { 256, 256 };
    HBITMAP hBitmap = NULL;
    psiif->GetImage(size, SIIGBF_RESIZETOFIT, &hBitmap);
    psiif->Release();
}


OleUninitialize();

通过跨进程读取SysListView32获取

// 辅助函数:判断explorer进程是否未32位
BOOL IsProc32(HANDLE hProc)
{
    typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
    BOOL isProc32 = TRUE;
    LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)::GetProcAddress(::GetModuleHandleA("kernel32"), "IsWow64Process");
    if (NULL != fnIsWow64Process)
    {
        fnIsWow64Process(hProc, &isProc32);
    }
    return isProc32;
}

// 核心函数
bool GetDeskItems(std::vector<std::string>& vtItem)
{
    struct LVITEM64 // 针对64位桌面进程
    {
        UINT mask;
        int iItem;
        int iSubItem;
        UINT state;
        UINT stateMask;
        INT64 pszText;
        int cchTextMax;
        int iImage;
        INT64 lParam;
        int iIndent;
        int iGroupId;
        UINT cColumns;
        INT64 puColumns;
    };

    struct LVITEM32 // 针对32位桌面进程
    {
        UINT mask;
        int iItem;
        int iSubItem;
        UINT state;
        UINT stateMask;
        LPSTR pszText;
        int cchTextMax;
        int iImage;
        LPARAM lParam;
        int iIndent;
        int iGroupId;
        UINT cColumns;
        PUINT puColumns;
    };

    ::EnumChildWindows(GetDesktopWindow(), [](HWND hWnd, LPARAM pHandle)->BOOL {
        TCHAR szClass[256] = { 0 };
        TCHAR szName[256] = { 0 };
        if (::GetClassName(hWnd, szClass, sizeof(szClass)) && ::GetWindowText(hWnd, szName, sizeof(szName)) && lstrcmp(szClass, _T("SysListView32")) == 0 && lstrcmp(szName, _T("FolderView")) == 0)
        {
            *(HWND*)pHandle = hWnd;
            return FALSE;
        }
        return TRUE;
    }, (LPARAM)&hListWnd);


    DWORD dwPID = 0;
    ::GetWindowThreadProcessId(hListWnd, &dwPID);
    HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwPID);
    if (hListWnd != NULL && dwPID > 0 && hProcess != NULL)
    {
        int nLvRows = ListView_GetItemCount(hListWnd);

        // 经测试win10 桌面List使用的是Unicode
        wchar_t szName[512] = { 0 };
        wchar_t szType[256] = { 0 };
        ;
        BYTE* plvi = NULL;
        BYTE* plvi_name = NULL;
        BYTE* plvi_type = NULL;

        bool isProc32 = IsProc32(hProcess);
        int nLVIBytes = (isProc32? sizeof(LVITEM32) : sizeof(LVITEM64));

        plvi = (BYTE*)::VirtualAllocEx(hProcess, NULL, (nLVIBytes + sizeof(szName) + sizeof(szType)), MEM_COMMIT, PAGE_READWRITE);
        if (plvi == NULL)
        {
            return false;
        }

        plvi_name = (BYTE*)((DWORD)plvi + nLVIBytes);
        plvi_type = (BYTE*)((DWORD)plvi + nLVIBytes + sizeof(szName));

        if (isProc32)
        {
            LVITEM32 lvi32 = { 0 };
            for (int i = 0; i < nLvRows; i++)
            {
                lvi32.mask = LVIF_TEXT | LVIF_IMAGE;
                lvi32.iItem = i;
                lvi32.iSubItem = 0; // name
                lvi32.pszText = (LPSTR)plvi_name;
                lvi32.cchTextMax = sizeof(szName) / sizeof(szName[0]);
                ::WriteProcessMemory(hProcess, (LVITEM32*)plvi, &lvi32, sizeof(LVITEM32), NULL);
                ::SendMessage(hListWnd, LVM_GETITEM, 0, (LPARAM)plvi);
                ::ReadProcessMemory(hProcess, lvi32.pszText, szName, sizeof(szName), NULL);

                lvi32.iSubItem = 2; // type
                lvi32.pszText = (LPSTR)plvi_type;
                lvi32.cchTextMax = sizeof(szType) / sizeof(szType[0]);
                ::WriteProcessMemory(hProcess, (LVITEM32*)plvi, &lvi32, sizeof(LVITEM32), NULL);
                ::SendMessage(hListWnd, LVM_GETITEM, 0, (LPARAM)plvi);
                ::ReadProcessMemory(hProcess, lvi32.pszText, szType, sizeof(szType), NULL);

                vtItem.emplace_back(szName);
            }
        }
        else
        {
            LVITEM64 lvi64 = { 0 };
            for (int i = 0; i < nLvRows; i++)
            {
                lvi64.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_COLUMNS;
                lvi64.iItem = i;
                lvi64.iSubItem = 0;
                lvi64.pszText = (INT64)plvi_name;
                lvi64.cchTextMax = sizeof(szName) / sizeof(szName[0]);
                ::WriteProcessMemory(hProcess, (LVITEM64*)plvi, &lvi64, sizeof(LVITEM64), NULL);
                ::SendMessage(hListWnd, LVM_GETITEM, 0, (LPARAM)plvi);
                ::ReadProcessMemory(hProcess, (LVITEM64*)lvi64.pszText, szName, sizeof(szName), NULL);

                lvi64.iSubItem = 2; // type
                lvi64.pszText = (INT64)plvi_type;
                lvi64.cchTextMax = sizeof(szType) / sizeof(szType[0]);
                ::WriteProcessMemory(hProcess, (LVITEM64*)plvi, &lvi64, sizeof(LVITEM64), NULL);
                ::SendMessage(hListWnd, LVM_GETITEM, 0, (LPARAM)plvi);
                ::ReadProcessMemory(hProcess, (LVITEM64*)lvi64.pszText, szType, sizeof(szType), NULL);

                vtItem.emplace_back(szName);
            }
        }

        ::VirtualFreeEx(hProcess, plvi, 0, MEM_RELEASE);
        return true;
    }
    return false;
}

 

查看几个系统图标隐藏状态的方法

// win7/10在这个路径查看,xp未验证,值为1隐藏,否则显示。需要综合考虑两个注册表路径(HKEY_CURRENT_USER和HKEY_LOCAL_MACHINE)

计算机\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel

计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel

猜你喜欢

转载自blog.csdn.net/xk641018299/article/details/111033602