SHBrowseForFolder 和快捷方式 [英] SHBrowseForFolder and shortcuts

查看:34
本文介绍了SHBrowseForFolder 和快捷方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 C++ Windows 应用程序中,我有一个函数应该允许最终用户选择一个文件夹.我正在使用 SHBrowseForFolder,它工作正常,只是对话框中没有显示文件夹快捷方式.

In my C++ Windows application, I have a function that is supposed to allow the end-user select a folder. I'm using SHBrowseForFolder and it is working fine except that folder shortcuts are not being displayed in the dialog.

有谁知道是否可以配置 SHBrowseForFolder 以便最终用户能够导航文件夹快捷方式?

Does anyone know if it is possible to configure SHBrowseForFolder so that the end-users will be able to navigate folder shortcuts?

2010 年 5 月 24 日,美国东部时间 1:10:

好的,我将展示我目前所拥有的代码.我曾尝试使用在我的回调过程中放置​​ BFFM_IUNKNOWN 回调的建议,但一直在努力弄清楚如何提供有效的 IFolderFilter 后代.

Okay, I'm going to show the code of what I have so far. I have tried using the suggestion of putting a BFFM_IUNKNOWN callback in my callback procedure, but have been struggling to figure out how to provide a IFolderFilter descendent that works.

1.被调用的代码:

Error CFolderChooserDialog::RunDialog()  
{  
    Error runResult = kError_NotInitialized;

    if (VERIFYN(kLyndsey, m_ReferenceCount > 0)) {  
         runResult = kError_Unexpected;  

         m_AllFoldersFilter = new TAllFoldersFilter();  

         if (VERIFYN(kLyndsey, m_AllFoldersFilter))  
         {  
               char selectedDirectoryBuffer[MAX_PATH];  
               m_DirectoryPath.CopyInto(selectedDirectoryBuffer);  

               BROWSEINFO bi;  
               memset(&bi, 0, sizeof(bi));  

               bi.hwndOwner = MyGetMainHWND(m_CBP);  
               bi.pidlRoot = NULL;  
               bi.pszDisplayName = selectedDirectoryBuffer;  
               bi.lpszTitle = (const char*)m_Description;  
               bi.ulFlags |= BIF_RETURNONLYFSDIRS;  
               bi.ulFlags |= BIF_BROWSEINCLUDEFILES;  

               bi.lpfn = SHBrowseForFolderCallbackProc;  
               bi.lParam = (LPARAM)this;  
               bi.iImage = 0;  

               LPITEMIDLIST resultInfo = SHBrowseForFolder(&bi);  
               if (resultInfo) {  
                   runResult = kError_NoError;  
                   if (SHGetPathFromIDList(resultInfo, selectedDirectoryBuffer)) {  
                        m_DirectoryPath = selectedDirectoryBuffer;  
                   }  
              }  
              else {  
                   runResult = kError_Failed;  
              }  
               delete m_AllFoldersFilter;  
               m_AllFoldersFilter = nil;  
               CoTaskMemFree(resultInfo);  
          }  

    }  

    return runResult;  
}  

2.从 SHBrowseForFolder 调用的回调:

int CALLBACK CFolderChooserDialog::SHBrowseForFolderCallbackProc(HWND window, UINT message, LPARAM messageValue, LPARAM clientData)  
{  
    CFolderChooserDialog* thisPtr = (CFolderChooserDialog*)clientData;  

    if (VERIFYN(kLyndsey, thisPtr)) {  
        switch (message) {  
            case BFFM_INITIALIZED: {  
                if (!thisPtr->m_DialogTitle.IsEmpty()) {  
                    ::SetWindowText(window, (const char*) thisPtr->m_DialogTitle);  
                }  

                if (!thisPtr->m_DirectoryPath.IsEmpty()) {  
                    LPCTSTR startDirectory = thisPtr->m_DirectoryPath;  
                    ::SendMessage(window, BFFM_SETSELECTION, TRUE, (LPARAM)startDirectory);  
                }  
                break;  
            }  
            case BFFM_IUNKNOWN:  
            {  
                IUnknown* theInterface = (IUnknown*)messageValue;  
                if (VERIFYN(kLyndsey, theInterface))  
                {  
                    IFolderFilterSite* filter = NULL;  
                    theInterface->QueryInterface(IID_IFolderFilterSite, (void**)&filter);  
                    if (VERIFYN(kLyndsey, filter))  
                    {  
                        filter->SetFilter((IUnknown*)thisPtr->m_AllFoldersFilter);  
                        filter->Release();  
                    }  
                }  
                break;  
            }  
            default:  
                break;  
        }  
    }  
    return 0;  
}  

3.应该为每个项目调用 IFolderFilter 以将其过滤到对话框中或从对话框中过滤出来:

class TAllFoldersFilter : public IFolderFilter  
{  
public:  
    TAllFoldersFilter() { refCount = 0;}  

    HRESULT STDMETHODCALLTYPE QueryInterface(const IID& iid, void** obj)  
    {  
        if (!obj)  
            return E_INVALIDARG;  
        *obj = NULL;  

        if (iid == IID_IUnknown || iid == IID_IFolderFilter)  
        {  
            *obj = (void*)this;  
            AddRef();  
            return NOERROR;  
        }  
        return E_NOINTERFACE;  
    }  

    ULONG STDMETHODCALLTYPE AddRef()  
    {  
        refCount++;  
        return refCount;  
    }  
    ULONG STDMETHODCALLTYPE Release()  
    {  
        refCount--;  
        return refCount;  
    }  

    HRESULT STDMETHODCALLTYPE GetEnumFlags(IShellFolder* sf, LPCITEMIDLIST pidlFolder, HWND* window, DWORD* flags)  
    {  
        return 0;  
    }  

    HRESULT STDMETHODCALLTYPE ShouldShow(IShellFolder* sf, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST pidlItem)  
    {  
        HRESULT resultCode = S_OK;  

        ULONG attributes = 0UL;  

        if (SUCCEEDED(sf->GetAttributesOf(1, &pidlItem, &attributes)))  
        {  
            if (attributes & SFGAO_FOLDER)  
            {  
                resultCode = S_OK;  // Yes, I see the folders
            }  
            else if (attributes & SFGAO_LINK)  
            {  
                resultCode = S_OK;  // Yes, this shows the folder shortcut links, but I cannot explore them. When I "expand" them (click on the plus-sign-box), nothing happens.
            }  
        }  

        return resultCode;  
    }  
protected:  
    ULONG refCount;  
};  

那么,我在哪里?嗯,我可以显示文件夹,我可以显示文件夹链接,但我不确定以下内容:

So, where am I? Well, I can show the folders, I can show folder links, but I'm uncertain about the following:

  1. 如何轻松确定我拥有的项目是否为文件夹的快捷链接?我写的代码绝对没有看那个,而是显示了任何快捷链接.

  1. How do I easily determine if the item I have is a shortcut link to a folder? The code I wrote is definitely not looking at that and is showing any shortcut link.

如何轻松地让最终用户进入快捷链接所代表的文件夹?

How do I easily allow the end-user delve into the folder represented by the shortcut link?

这段代码是否正确且尽可能简单/干净?

Is this code correct and as simple/clean as it can be?

感谢您的帮助!

2010 年 6 月 1 日:美国东部时间 2:14:答案是技术上提供的,所以我会标记它,然后我会问另一个问题来帮助我修复此代码.

June 1st, 2010: 2:14 EST: The answer was technically provided, so I'll mark that and I'm going to ask another question to help me fix this code.

推荐答案

更好的答案是使用带有 FOS_PICKFOLDERS 的 IFileOpenDialog 作为 Windows Vista 和更高版本的选项.

The better answer is to use IFileOpenDialog with FOS_PICKFOLDERS as the option for Windows Vista and later.

这篇关于SHBrowseForFolder 和快捷方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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