我希望这属于该论坛的范围:

我想使用Windows Shell(?)允许用户选择一些文件,然后再允许我的程序对它们执行一些操作。为此,我找到了MSDN示例“ CommonFileDialogModes”-http://msdn.microsoft.com/en-us/library/windows/desktop/dd940350%28v=vs.85%29.aspx

在该类下的示例中:
CFileOpenBasketPickerCallback类:公共IFileDialogEvents,公共IFileDialogControlEvents

他们具有以下功能:

// IFileDialogEvents
IFACEMETHODIMP OnFileOk(IFileDialog *pfd)
{
    // if this button is in the "Add" mode then do this, otherwise return S_OK
    IFileOpenDialog *pfod;
    HRESULT hr = pfd->QueryInterface(IID_PPV_ARGS(&pfod));
    if (SUCCEEDED(hr))
    {
        IShellItemArray *psia;
        hr = pfod->GetSelectedItems(&psia);
        if (SUCCEEDED(hr))
        {
            ReportSelectedItems(pfd, psia);
            psia->Release();
        }
        pfod->Release();
    }
    return S_FALSE; // S_FALSE keeps the dialog up; return S_OK to allow it to dismiss.
}


哪个调用:

void ReportSelectedItems(IUnknown *punkSite, IShellItemArray *psia)
{
    DWORD cItems;
    HRESULT hr = psia->GetCount(&cItems);
    for (DWORD i = 0; SUCCEEDED(hr) && (i < cItems); i++)
    {
        IShellItem *psi;
        hr = psia->GetItemAt(i, &psi);
        if (SUCCEEDED(hr))
        {
            PWSTR pszName;
            hr = GetIDListName(psi, &pszName);

        // .. I've cut some of this out for the example

                CoTaskMemFree(pszName);
            }
            psi->Release();
        }
    }
}


现在,我知道pszName包含所选文件的名称。因此,我可以添加一些额外的代码以将其写入磁盘。很好但我不想将其写入磁盘。我想将其传递回调用此函数的原始函数。可以更改ReportSelectedItems的参数,但是IFACEMETHODIMP OnFileOk(IFileDialog * pfd)无法继承,因为它是继承的。将vector&file_names添加到参数将停止编译。

那么我该如何处理呢?我可以对文件名使用全局变量,但是我所学到的关于编程的一切都告诉我不要这样做。这将是一个快速解决方案,但我担心这会鼓励我将来变得懒惰。我发现很难阅读Windows代码,并且我真的不想过多地研究它的细节。即使我知道它来自两个基类之一,我什至找不到所谓的OnFileOk函数。

我真的需要了解所有库代码,只是为了使这一功能实现我想要的工作吗?有更快的方法吗?

因此,总而言之,如何在不使用全局变量或不向磁盘写入的情况下从此继承的函数中获取信息?如前所述,我对正在使用的代码不太了解。为了将来参考,我应该如何处理这种情况?我使用c ++,并希望尽可能避免使用c#和c。

一如既往的感谢。

最佳答案

对于Microsoft而言,遗漏与IFileDialog回调关联的任何类型的用户数据似乎都是一个很大的疏忽,但事实确实如此。

我假设一旦对话框返回,仅调用GetSelectedItems()就是出于某种原因您不想执行的操作-因为这显然是最简单的解决方案。

快速浏览文档,您可能能够从事件回调传递回数据的一种方法是使用传递给IFileDialog::Show()(实际上是IModalWindow::Show())的所有者窗口。

在事件处理程序中,您将获得IFileDialog*指针。由此,您可以QI IOleWindow接口的地址,这将为您提供对话框的窗口:

IFACEMETHODIMP OnFileOk(IFileDialog *pfd)
{
    CComPtr<IOleWindow> pWindow;
    if (SUCCEEDED(pfd->QueryInterface(IID_IOleWindow, reinterpret_cast<void**>(&pWindow))))
    {
        HWND hwndDlg;
        if (SUCCEEDED(pWindow->GetWindow(&hwndDlg)))
        {
            HWND hwndOwner;
            if (hwndOwner = GetWindow(hwndDlg, GW_OWNER))
            {
                // hwndOwner is the owner window of the dialog
            }
        }
    }
    // more code
}


现在假设hwndOwner是您自己的窗口,您可以使用SetProp() / GetProp()将所需的任何数据与之关联-因此您可以将其用作从回调内部传递数据的机制。

关于c++ - MSDN CommonFileDialogModes,出于我的目的进行更改,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19558966/

10-11 12:49