我希望這屬於這個論壇的範疇:MSDN CommonFileDialogModes,改變我的目的
我想使用Windows外殼程序,以允許用戶選擇多個文件讓我的程序做之前(?)給他們幾件事情。爲此,我找到了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)不能像繼承。將一個矢量& file_names添加到參數將停止編譯。
那麼我該如何處理呢?我可以爲file_names使用全局變量,但是我正在學習編程的一切都告訴我不要。這將是一個快速解決方案,但我擔心這會鼓勵我在未來變得懶惰。我發現很難閱讀windows代碼,我不想深入研究它的細節。我什至不能找到什麼調用OnFileOk函數,即使我知道它來自兩個基類之一。
我是否真的需要理解所有的庫代碼才能讓這個函數做我想做的事?有沒有更快的方法來解決這個問題?因此,總而言之,如何在不使用全局變量或寫入磁盤的情況下從此繼承函數獲取信息?正如我之前所做的那樣,我沒有太多的把握我正在使用的代碼。爲了將來的參考,我應該如何處理這種情況?我使用C++,並希望儘可能避免c#和c。
一如既往的感謝。
感謝您的回覆。我試圖按照你的解決方案,但有細節問題。不幸的是,我不熟悉代碼庫。我實際上想出了另一個解決方案,一個我早先應該看到的解決方案。我仍然想了解你的解決方案,所以一旦我發佈了我的當前解決方案,我會寫幾個問題。 – David
好吧,我花了一點時間看你的解決方案。我無法弄清楚如何使用CFileOpenBasketPickerCallback之外的GetSelectedItems()。我也很難理解這部分 - 「你可以QI IOleWindow接口的地址」。我很想看看這是如何工作的,但是我必須閱讀的所有文檔都有點令人頭暈目眩。 – David
@David:查看我發佈的示例代碼! –