通过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