Быстрый доступ и расширения пространства имен: открепление объекта
Когда я щелкаю правой кнопкой мыши по файлу lnk - ссылка на виртуальную папку с расширением пространства имен -, тогда функции CreateViewObject
и / или GetUiObjectOf
из моего IShellFolder/IShellFolder2
реализации называются. Эти функции вызываются с IID_IContextMenu
как параметр (riid)
, Кроме того, когда QueryContextMenu вызывается флаг CMF_VERBSONLY (0x00000002)
установлено. Это означает, что 1) я знаю, что должно быть показано меню и 2) что из-за флага CMF_VERBSONLY
что это меню было запрошено файлом.lnk и что (источник Microsoft):
0x00000002. Контекстное меню является файлом ярлыка (обычно это файл.lnk). Обработчики контекстного меню должны игнорировать это значение.
Большую часть времени я не добавляю пункты меню, когда этот флаг присутствует. Если щелкнуть правой кнопкой мыши файл.lnk, Windows вернет стандартное меню для файлов.lnk, и будет предложена возможность удалить этот файл. У меня была такая же возможность с папкой "Избранное" в Windows 7. Начиная с Windows 10 и "введения" быстрого доступа, это больше невозможно. Пункт меню "Открепить" не будет отображаться по умолчанию.
Поскольку это очень сложно из расширения пространства имен, предполагая, IID_IContextMenu
а также CMF_VERBSONLY
чтобы узнать, закреплен ли объект в быстром доступе, а также как открепить его - мне, вероятно, придется открыть папку автоматических списков переходов, а затем проверить все файлы списка переходов по отображаемому имени моего объекта - мне было интересно, есть ли более простой способ справиться с этим (в конце списка переходов конкатенация файлов LNK).
Спасибо за вашу помощь
1 ответ
Благодаря подсказке Саймона Мурье, здесь возможный способ проверить, закреплена ли папка (любого типа) в быстром доступе или нет...
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();
}
}