0

これがこのフォーラムの範囲内に収まることを願っています。

Windows シェル (?) を使用して、ユーザーがいくつかのファイルを選択できるようにしてから、プログラムにいくつかのことを実行させたいと考えています。このために、MSDN サンプル「CommonFileDialogModes」を見つけました - http://msdn.microsoft.com/en-us/library/windows/desktop/dd940350%28v=vs.85%29.aspx

このクラスのサンプル: class CFileOpenBasketPickerCallback : public IFileDialogEvents, public 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 を追加すると、コンパイルが停止します。

では、これにどのように対処すればよいでしょうか。file_names にグローバル変数を使用することもできますが、プログラミングについて学んでいることはすべて、使用しないように指示しています。手っ取り早い解決策ですが、将来怠けるようになるのではないかと心配です。Windows のコードを読むのは難しいと思いますが、その詳細についてあまり深く掘り下げたくありません。2 つの基本クラスのいずれかからのものであることはわかっていますが、OnFileOk 関数を呼び出しているものを見つけることさえできません。

この 1 つの関数を自分のやりたいことを実行させるためだけに、すべてのライブラリ コードを理解する必要がありますか? これについてもっと速い方法はありますか?

要約すると、グローバル変数を使用したりディスクに書き込んだりせずに、この継承された関数から情報を取得するにはどうすればよいでしょうか? 前に述べたように、私は自分が作業しているコードをあまり理解していません。また、今後の参考のために、この種の状況にどのように対処すればよいですか? 私は c++ を使用していますが、c# と c はできるだけ避けたいと考えています。

いつもありがとう。

4

2 に答える 2

0

簡単な解決策は、継承されたクラス内にメンバー データを追加し、コンストラクターからリンクすることでした。

class CFileOpenBasketPickerCallback : public IFileDialogEvents, public IFileDialogControlEvents
{
public:
    CFileOpenBasketPickerCallback(vector<wstring>& files) : files_(files)
    {
    }
// functions

private:
vector<wstring>& files_;
};

オブジェクトを構築するとき

vector<std::wstring> files
CFileOpenBasketPickerCallback foacb(files);

そして IFACEMETHODIMP OnFileOk(IFileDialog *pfd) で

ReportSelectedItems(pfd, psia, files_);

ReportSelectedItems はメンバーではないため、引数を変更できます。

于 2013-10-25T04:02:45.373 に答える