快速访问和命名空间扩展:取消固定对象 [英] Quick Access and Namespace Extensions: Unpin object

查看:69
本文介绍了快速访问和命名空间扩展:取消固定对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我右键单击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 知道对象是否固定在快速访问中以及如何取消固定-我可能会必须打开自动跳转列表文件夹,然后对照我的对象displayname-检查所有跳转列表文件,我想知道是否有更简单的方法来处理此问题(最后的跳转列表是lnk文件的串联).

感谢您的帮助

解决方案

感谢Simon Mourier的提示,这是一种检查文件夹(任何类型)是否固定在快速访问中的可能方法...

 外部布尔__cdecl IsInQuickAccess(LPWSTR folderParsingName){IShellFolder * desktopFolder;HRESULT hr = SHGetDesktopFolder(& desktopFolder);bool isInQuickAccess = false;如果(成功(小时)){LPITEMIDLIST quickAccessIdList;hr = desktopFolder-> ParseDisplayName(NULL,NULL,_T("shell ::: {679f85cb-0220-4080-b29b-5540cc05aab6}"),NULL,& quickAccessIdList,NULL);如果(成功(小时)){IShellFolder * quickAccessFolder;hr = desktopFolder-> BindToObject(quickAccessIdList,NULL,IID_PPV_ARGS(& quickAccessFolder));如果(成功(小时)){IEnumIDList * currentChildren = NULL;hr = quickAccessFolder-> EnumObjects(NULL,SHCONTF_FOLDERS,& currentChildren);如果(成功(小时)){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);如果(成功(小时)){LPWSTR childDisplayNameString;hr = StrRetToStr(& childDisplayName,NULL,& childDisplayNameString);如果(成功(小时)){LPWSTR childDisplayNameStringToLower = CharLower(childDisplayNameString);如果(wPathToFolder.Compare(childDisplayNameStringToLower)== 0)isInQuickAccess = true;CoTaskMemFree(childDisplayNameString);}}}CoTaskMemFree(childPidl);currentChildren-> Release();}quickAccessFolder-> Release();}CoTaskMemFree(quickAccessIdList);}desktopFolder-> Release();}返回isInQuickAccess;} 

然后从家里取消固定(检查具有给定显示名称的文件夹是否可以快速访问).

  extern void __cdecl UnpinFromHome(LPWSTR folderParsingName){IShellFolder * desktopFolder;HRESULT hr = SHGetDesktopFolder(& desktopFolder);如果(成功(小时)){LPITEMIDLIST quickAccessIdList;hr = desktopFolder-> ParseDisplayName(NULL,NULL,_T("shell ::: {679f85cb-0220-4080-b29b-5540cc05aab6}"),NULL,& quickAccessIdList,NULL);如果(成功(小时)){IShellFolder * quickAccessFolder;hr = desktopFolder-> BindToObject(quickAccessIdList,NULL,IID_PPV_ARGS(& quickAccessFolder));如果(成功(小时)){IEnumIDList * currentChildren = NULL;hr = quickAccessFolder-> EnumObjects(NULL,SHCONTF_FOLDERS,& currentChildren);如果(成功(小时)){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);如果(成功(小时)){LPWSTR childDisplayNameString;hr = StrRetToStr(& childDisplayName,NULL,& childDisplayNameString);如果(成功(小时)){LPWSTR childDisplayNameStringToLower = CharLower(childDisplayNameString);如果(wPathToFolder.Compare(childDisplayNameStringToLower)== 0){IContextMenu * childContextMenu;LPCITEMIDLIST childCPidl = childPidl;hr = quickAccessFolder-> GetUIObjectOf(NULL,1,& childCPidl,IID_IContextMenu,NULL,(void **)& childContextMenu);如果(成功(小时)){HMENU hmenu = CreatePopupMenu();如果(hmenu){hr = childContextMenu-> QueryContextMenu(hmenu,0,1,0x7FFF,CMF_NORMAL);如果(成功(小时)){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();}} 

When I right click on an lnk file - link on a virtual folder in a namespace extension -, then the functions CreateViewObject and/or GetUiObjectOf of my IShellFolder/IShellFolder2 implementations are called. These functions are called with the IID_IContextMenu as parameter (riid). Also when QueryContextMenu is called the flag CMF_VERBSONLY (0x00000002) is set. It means that 1) I know that a menu should be shown and 2) that because of the flag CMF_VERBSONLY that this menu was queried by a .lnk file and that (source Microsoft):

0x00000002. The shortcut menu is that of a shortcut file (normally, a .lnk file). Shortcut menu handlers should ignore this value.

Most of the time I don't add menu items when this flag is present. When right-clicking on an .lnk file then windows will return a standard menu for .lnk files and the opportunity will be offered to delete this file. I had the same opportunity with the favorites folder on Windows 7. Since Windows 10 and "introduction" of quick access it is not possible anymore. No "Unpin" menu item will be shown by default.

Since it's very difficult from the namespace extension, assuming IID_IContextMenu and CMF_VERBSONLY to know if the object is pinned in quick access and also how to unpin it - I probably would have to open the automatic jump lists folder and then check all the jump list files against my object displayname - , I was wondering if there is an easier way to handle this (at the end jump list are a concatenation of lnk files).

Thanks for your help

解决方案

Thanks to Simon Mourier's hint, here a possible way to check if a folder (of any type) is pinned in quick access or not...

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, &currentChildren);

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

and here unpin from home (with check if folder with given display name is in quick access).

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, &currentChildren);

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

这篇关于快速访问和命名空间扩展:取消固定对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆