快速访问和命名空间扩展:取消固定 object
Quick Access and Namespace Extensions: Unpin object
当我右键单击一个 lnk 文件 - link 在命名空间扩展中的一个虚拟文件夹上 - 然后 CreateViewObject
and/or GetUiObjectOf
的函数 CreateViewObject
and/or GetUiObjectOf
=13=] 实现被调用。这些函数使用 IID_IContextMenu
作为参数 (riid)
调用。此外,当 QueryContextMenu 被调用时,标志 CMF_VERBSONLY (0x00000002)
被设置。这意味着 1) 我知道应该显示一个菜单,并且 2) 由于标志 CMF_VERBSONLY
,该菜单被 .lnk 文件查询,并且(来源 Microsoft):
0x00000002. The shortcut menu is that of a shortcut file (normally, a
.lnk file). Shortcut menu handlers should ignore this value.
大多数情况下,出现此标志时我不会添加菜单项。当 right-clicking 处理 .lnk 文件时,windows 将 return .lnk 文件的标准菜单,并提供删除此文件的机会。我对 Windows 7 上的收藏夹文件夹有同样的机会。由于 Windows 10 和 "introduction" 的快速访问,它不再可能了。默认情况下不会显示 "Unpin" 个菜单项。
因为命名空间扩展非常困难,假设 IID_IContextMenu
和 CMF_VERBSONLY
知道 object 是否固定在快速访问中以及如何取消固定 - 我可能会必须打开自动跳转列表文件夹,然后根据我的 object displayname - 检查所有跳转列表文件,我想知道是否有更简单的方法来处理这个问题(最后跳转列表是 lnk 文件的串联).
感谢您的帮助
感谢 Simon Mourier 的提示,这里提供了一种检查文件夹(任何类型)是否固定在快速访问中的可能方法...
extern bool __cdecl IsInQuickAccess(LPWSTR folderParsingName)
{
IShellFolder* desktopFolder;
HRESULT hr = SHGetDesktopFolder(&desktopFolder);
bool isInQuickAccess = false;
if (SUCCEEDED(hr))
{
LPITEMIDLIST quickAccessIdList;
hr = desktopFolder->ParseDisplayName(NULL, NULL, _T("shell:::{679f85cb-0220-4080-b29b-5540cc05aab6}"), NULL, &quickAccessIdList, NULL);
if (SUCCEEDED(hr))
{
IShellFolder* quickAccessFolder;
hr = desktopFolder->BindToObject(quickAccessIdList, NULL, IID_PPV_ARGS(&quickAccessFolder));
if (SUCCEEDED(hr))
{
IEnumIDList* currentChildren = NULL;
hr = quickAccessFolder->EnumObjects(NULL, SHCONTF_FOLDERS, ¤tChildren);
if (SUCCEEDED(hr))
{
CString wPathToFolder = CharLower(folderParsingName);
LPITEMIDLIST childPidl = NULL;
while (!isInQuickAccess && currentChildren->Next(1, &childPidl, NULL) == S_OK)
{
STRRET childDisplayName;
hr = quickAccessFolder->GetDisplayNameOf(childPidl, SHGDN_FORPARSING, &childDisplayName);
if (SUCCEEDED(hr))
{
LPWSTR childDisplayNameString;
hr = StrRetToStr(&childDisplayName, NULL, &childDisplayNameString);
if (SUCCEEDED(hr))
{
LPWSTR childDisplayNameStringToLower = CharLower(childDisplayNameString);
if (wPathToFolder.Compare(childDisplayNameStringToLower) == 0)
isInQuickAccess = true;
CoTaskMemFree(childDisplayNameString);
}
}
}
CoTaskMemFree(childPidl);
currentChildren->Release();
}
quickAccessFolder->Release();
}
CoTaskMemFree(quickAccessIdList);
}
desktopFolder->Release();
}
return isInQuickAccess;
}
并在此处取消固定主页(检查具有给定显示名称的文件夹是否处于快速访问状态)。
extern void __cdecl UnpinFromHome(LPWSTR folderParsingName)
{
IShellFolder* desktopFolder;
HRESULT hr = SHGetDesktopFolder(&desktopFolder);
if (SUCCEEDED(hr))
{
LPITEMIDLIST quickAccessIdList;
hr = desktopFolder->ParseDisplayName(NULL, NULL, _T("shell:::{679f85cb-0220-4080-b29b-5540cc05aab6}"), NULL, &quickAccessIdList, NULL);
if (SUCCEEDED(hr))
{
IShellFolder* quickAccessFolder;
hr = desktopFolder->BindToObject(quickAccessIdList, NULL, IID_PPV_ARGS(&quickAccessFolder));
if (SUCCEEDED(hr))
{
IEnumIDList* currentChildren = NULL;
hr = quickAccessFolder->EnumObjects(NULL, SHCONTF_FOLDERS, ¤tChildren);
if (SUCCEEDED(hr))
{
CString wPathToFolder = CharLower(folderParsingName);
LPITEMIDLIST childPidl = NULL;
bool isInQuickAccess = false;
while (!isInQuickAccess && currentChildren->Next(1, &childPidl, NULL) == S_OK)
{
STRRET childDisplayName;
hr = quickAccessFolder->GetDisplayNameOf(childPidl, SHGDN_FORPARSING, &childDisplayName);
if (SUCCEEDED(hr))
{
LPWSTR childDisplayNameString;
hr = StrRetToStr(&childDisplayName, NULL, &childDisplayNameString);
if (SUCCEEDED(hr))
{
LPWSTR childDisplayNameStringToLower = CharLower(childDisplayNameString);
if (wPathToFolder.Compare(childDisplayNameStringToLower) == 0)
{
IContextMenu* childContextMenu;
LPCITEMIDLIST childCPidl = childPidl;
hr = quickAccessFolder->GetUIObjectOf(NULL, 1, &childCPidl, IID_IContextMenu, NULL, (void**)&childContextMenu);
if (SUCCEEDED(hr))
{
HMENU hmenu = CreatePopupMenu();
if (hmenu)
{
hr = childContextMenu->QueryContextMenu(hmenu, 0, 1, 0x7FFF, CMF_NORMAL);
if (SUCCEEDED(hr))
{
CMINVOKECOMMANDINFO info = { 0 };
info.cbSize = sizeof(info);
info.hwnd = NULL;
info.lpVerb = "unpinfromhome";
info.nShow = 1;
info.fMask = CMIC_MASK_ASYNCOK;
childContextMenu->InvokeCommand(&info);
}
DestroyMenu(hmenu);
}
}
isInQuickAccess = true;
}
CoTaskMemFree(childDisplayNameString);
}
}
}
CoTaskMemFree(childPidl);
currentChildren->Release();
}
quickAccessFolder->Release();
}
CoTaskMemFree(quickAccessIdList);
}
desktopFolder->Release();
}
}
当我右键单击一个 lnk 文件 - link 在命名空间扩展中的一个虚拟文件夹上 - 然后 CreateViewObject
and/or GetUiObjectOf
的函数 CreateViewObject
and/or GetUiObjectOf
=13=] 实现被调用。这些函数使用 IID_IContextMenu
作为参数 (riid)
调用。此外,当 QueryContextMenu 被调用时,标志 CMF_VERBSONLY (0x00000002)
被设置。这意味着 1) 我知道应该显示一个菜单,并且 2) 由于标志 CMF_VERBSONLY
,该菜单被 .lnk 文件查询,并且(来源 Microsoft):
0x00000002. The shortcut menu is that of a shortcut file (normally, a .lnk file). Shortcut menu handlers should ignore this value.
大多数情况下,出现此标志时我不会添加菜单项。当 right-clicking 处理 .lnk 文件时,windows 将 return .lnk 文件的标准菜单,并提供删除此文件的机会。我对 Windows 7 上的收藏夹文件夹有同样的机会。由于 Windows 10 和 "introduction" 的快速访问,它不再可能了。默认情况下不会显示 "Unpin" 个菜单项。
因为命名空间扩展非常困难,假设 IID_IContextMenu
和 CMF_VERBSONLY
知道 object 是否固定在快速访问中以及如何取消固定 - 我可能会必须打开自动跳转列表文件夹,然后根据我的 object displayname - 检查所有跳转列表文件,我想知道是否有更简单的方法来处理这个问题(最后跳转列表是 lnk 文件的串联).
感谢您的帮助
感谢 Simon Mourier 的提示,这里提供了一种检查文件夹(任何类型)是否固定在快速访问中的可能方法...
extern bool __cdecl IsInQuickAccess(LPWSTR folderParsingName)
{
IShellFolder* desktopFolder;
HRESULT hr = SHGetDesktopFolder(&desktopFolder);
bool isInQuickAccess = false;
if (SUCCEEDED(hr))
{
LPITEMIDLIST quickAccessIdList;
hr = desktopFolder->ParseDisplayName(NULL, NULL, _T("shell:::{679f85cb-0220-4080-b29b-5540cc05aab6}"), NULL, &quickAccessIdList, NULL);
if (SUCCEEDED(hr))
{
IShellFolder* quickAccessFolder;
hr = desktopFolder->BindToObject(quickAccessIdList, NULL, IID_PPV_ARGS(&quickAccessFolder));
if (SUCCEEDED(hr))
{
IEnumIDList* currentChildren = NULL;
hr = quickAccessFolder->EnumObjects(NULL, SHCONTF_FOLDERS, ¤tChildren);
if (SUCCEEDED(hr))
{
CString wPathToFolder = CharLower(folderParsingName);
LPITEMIDLIST childPidl = NULL;
while (!isInQuickAccess && currentChildren->Next(1, &childPidl, NULL) == S_OK)
{
STRRET childDisplayName;
hr = quickAccessFolder->GetDisplayNameOf(childPidl, SHGDN_FORPARSING, &childDisplayName);
if (SUCCEEDED(hr))
{
LPWSTR childDisplayNameString;
hr = StrRetToStr(&childDisplayName, NULL, &childDisplayNameString);
if (SUCCEEDED(hr))
{
LPWSTR childDisplayNameStringToLower = CharLower(childDisplayNameString);
if (wPathToFolder.Compare(childDisplayNameStringToLower) == 0)
isInQuickAccess = true;
CoTaskMemFree(childDisplayNameString);
}
}
}
CoTaskMemFree(childPidl);
currentChildren->Release();
}
quickAccessFolder->Release();
}
CoTaskMemFree(quickAccessIdList);
}
desktopFolder->Release();
}
return isInQuickAccess;
}
并在此处取消固定主页(检查具有给定显示名称的文件夹是否处于快速访问状态)。
extern void __cdecl UnpinFromHome(LPWSTR folderParsingName)
{
IShellFolder* desktopFolder;
HRESULT hr = SHGetDesktopFolder(&desktopFolder);
if (SUCCEEDED(hr))
{
LPITEMIDLIST quickAccessIdList;
hr = desktopFolder->ParseDisplayName(NULL, NULL, _T("shell:::{679f85cb-0220-4080-b29b-5540cc05aab6}"), NULL, &quickAccessIdList, NULL);
if (SUCCEEDED(hr))
{
IShellFolder* quickAccessFolder;
hr = desktopFolder->BindToObject(quickAccessIdList, NULL, IID_PPV_ARGS(&quickAccessFolder));
if (SUCCEEDED(hr))
{
IEnumIDList* currentChildren = NULL;
hr = quickAccessFolder->EnumObjects(NULL, SHCONTF_FOLDERS, ¤tChildren);
if (SUCCEEDED(hr))
{
CString wPathToFolder = CharLower(folderParsingName);
LPITEMIDLIST childPidl = NULL;
bool isInQuickAccess = false;
while (!isInQuickAccess && currentChildren->Next(1, &childPidl, NULL) == S_OK)
{
STRRET childDisplayName;
hr = quickAccessFolder->GetDisplayNameOf(childPidl, SHGDN_FORPARSING, &childDisplayName);
if (SUCCEEDED(hr))
{
LPWSTR childDisplayNameString;
hr = StrRetToStr(&childDisplayName, NULL, &childDisplayNameString);
if (SUCCEEDED(hr))
{
LPWSTR childDisplayNameStringToLower = CharLower(childDisplayNameString);
if (wPathToFolder.Compare(childDisplayNameStringToLower) == 0)
{
IContextMenu* childContextMenu;
LPCITEMIDLIST childCPidl = childPidl;
hr = quickAccessFolder->GetUIObjectOf(NULL, 1, &childCPidl, IID_IContextMenu, NULL, (void**)&childContextMenu);
if (SUCCEEDED(hr))
{
HMENU hmenu = CreatePopupMenu();
if (hmenu)
{
hr = childContextMenu->QueryContextMenu(hmenu, 0, 1, 0x7FFF, CMF_NORMAL);
if (SUCCEEDED(hr))
{
CMINVOKECOMMANDINFO info = { 0 };
info.cbSize = sizeof(info);
info.hwnd = NULL;
info.lpVerb = "unpinfromhome";
info.nShow = 1;
info.fMask = CMIC_MASK_ASYNCOK;
childContextMenu->InvokeCommand(&info);
}
DestroyMenu(hmenu);
}
}
isInQuickAccess = true;
}
CoTaskMemFree(childDisplayNameString);
}
}
}
CoTaskMemFree(childPidl);
currentChildren->Release();
}
quickAccessFolder->Release();
}
CoTaskMemFree(quickAccessIdList);
}
desktopFolder->Release();
}
}