【问题标题】:Programmatically pre-select using IFileDialog in C++在 C++ 中使用 IFileDialog 以编程方式预选
【发布时间】:2018-05-08 11:05:00
【问题描述】:

我对 IFileDialog 是否能够在没有用户选择的情况下以编程方式选择对话框内的项目感到困惑。

例如。

我希望实现打开 IFileDialog 然后在对话框中选择一个默认项目/文件夹。 前任。

顺便说一下,在上图中。我确实手动单击/选择了文件夹。 但我希望在 IFileDialog 中实现一个默认选择的项目。

【问题讨论】:

  • 也许您正在寻找IFileDialog::SetFileName?它确实设置了编辑框的内容,但它并没有在列表视图中选择项目。
  • 在显示对话框之前设置文件名。
  • 我认为这是文件夹选择 UI 的设计。
  • IFileDialog::SetFolder() - 设置在打开对话框时始终选择的文件夹,无论之前的用户操作如何。
  • 从未尝试过,但我相信您也可以调用IFileDialog::QueryInterface() 来获得IShellView 接口。然后致电IShellView::SelectItem() 选择一项或多项。 IFileDialog 很可能需要已经可见,因此您可能必须通过IFileDialog::Advise() 挂钩OnFolderChange 之类的事件之一。还可以查看Raymond Chen's blog,它已经拥有您正在寻找的东西,或者至少可以为您提供足够的思想食物,以便您自己解决。

标签: c++ windows winapi


【解决方案1】:

zett42 建议的程序有效。您需要实现自己的IFileDialogEvents 版本。与IFileDialog::Advise 挂钩后,您可以查询到IShellView 的方式,这样您就可以更改选择。

这个例子有点傻,因为我也在强制目录以确保我有一个可以选择的文件。

struct MyIFileDialogEvents : public IFileDialogEvents {
    bool forcedDir, forcedSel;
    MyIFileDialogEvents() : forcedDir(false), forcedSel(false) {}
    ...
};

STDMETHODIMP MyIFileDialogEvents::OnFolderChanging( IFileDialog *pfd, IShellItem*psiFolder)
{
    if (forcedDir) return S_OK; else forcedDir = true;
    IShellItem*psiwindir;
    HRESULT hr = SHGetKnownFolderItem(FOLDERID_Windows, KF_FLAG_DEFAULT, NULL, IID_IShellItem, (void**) &psiwindir);
    if (!hr)
    {
        hr = pfd->SetFolder(psiwindir); // MSDN says it is OK to change the folder in OnFolderChanging with SetFolder
        psiwindir->Release();
    }
    if (FAILED(hr)) forcedSel = true;
    return S_OK;
}

STDMETHODIMP MyIFileDialogEvents::OnFolderChange(IFileDialog *pfd)
{
    if (forcedSel || !forcedDir) return S_OK; else forcedSel = true;
    IShellItem*psiwindir, *psiexp;
    HRESULT hr = SHGetKnownFolderItem(FOLDERID_Windows, KF_FLAG_DEFAULT, NULL, IID_IShellItem, (void**) &psiwindir);
    if (!hr)
    {
        hr = SHCreateItemFromRelativeName(psiwindir, L"Explorer.exe", NULL, IID_IShellItem, (void**) &psiexp);
        psiwindir->Release();
        if (!hr)
        {
            IServiceProvider*pSP;
            IShellBrowser*pSB;
            IShellView*pSV;
            if (!pfd->QueryInterface(IID_IServiceProvider, (void**) &pSP))
            {
                if (!pSP->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, (void**)&pSB))
                {
                    if (!pSB->QueryActiveShellView(&pSV))
                    {
                        PIDLIST_ABSOLUTE pidl;
                        if (!SHGetIDListFromObject(psiexp, &pidl))
                        {
                            pSV->SelectItem(ILFindLastID(pidl), SVSI_SELECT|SVSI_ENSUREVISIBLE|SVSI_FOCUSED|SVSI_DESELECTOTHERS);
                            CoTaskMemFree(pidl);
                        }
                        pSV->Release();
                    }
                    pSB->Release();
                }
                pSP->Release();
            }
            psiexp->Release();
        }
    }
    return S_OK;
}

【讨论】:

  • 你确定使用 !HRESULT 是对的吗?
  • @user13947194 如果这让您感觉更好,请使用 SUCCEEDED。 QueryInterface 几乎不可能成功,它有效或无效等等。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多