エクスプローラで選択されているファイルのパスを取得するには?

解決


2tom  2013-03-26 09:38:03  No: 73652  IP: 192.*.*.*

環境:VC6(MFC)

いつもお世話になっています。
現在、作成している常駐アプリでエクスプローラ選択されたファイル(単一・複数)のフルパスを取得する機能を実装しています。

いろいろ調べたところ、VBでは
Shell32.ShellFolderViewのSelectionChangedイベントで
取得できるところまではわかりました。
↓参考HP
http://hanatyan.sakura.ne.jp/patio/read.cgi?no=214

これをVCで行う場合、
LoadLibrary("SHELL32.DLL")
を行って、
GetProcAddress
で使用する関数のアドレスを取得すると思うのですが、
エクスプローラのSelectionChangedのイベントはどうすれば
捕まえることが出来るのでしょうか?

編集 削除
forty-five  2013-03-30 12:33:57  No: 73653  IP: 192.*.*.*

IDispatch とコネクションポイントを使うようです。

#import <shell32.dll>
#import <shdocvw.dll>

#include <vector>

class CTest : public Shell32::DShellFolderViewEvents
{
public:

    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppv)
    {
        if (iid == __uuidof(IUnknown))
        {
            _RPT0(_CRT_WARN, "IUnknown\n");

            *(IUnknown**)ppv = this;

            return S_OK;
        }

        if (iid == __uuidof(IDispatch))
        {
            _RPT0(_CRT_WARN, "IDispatch\n");

            *(IDispatch**)ppv = this;

            return S_OK;
        }

        return E_FAIL;
    }

    virtual ULONG STDMETHODCALLTYPE AddRef()
    {
        _RPT0(_CRT_WARN, "CTest::AddRef()\n");

        return 1;
    }

    virtual ULONG STDMETHODCALLTYPE Release()
    {
        _RPT0(_CRT_WARN, "CTest::Release()\n");

        return 0;
    }

    virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount( 
        /* [out] */ UINT *pctinfo){ return E_FAIL; }
    
    virtual HRESULT STDMETHODCALLTYPE GetTypeInfo( 
        /* [in] */ UINT iTInfo,
        /* [in] */ LCID lcid,
        /* [out] */ ITypeInfo **ppTInfo){ return E_FAIL; }
    
    virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames( 
        /* [in] */ REFIID riid,
        /* [size_is][in] */ LPOLESTR *rgszNames,
        /* [in] */ UINT cNames,
        /* [in] */ LCID lcid,
        /* [size_is][out] */ DISPID *rgDispId){ return E_FAIL; }
    
    virtual /* [local] */ HRESULT STDMETHODCALLTYPE Invoke( 
        /* [in] */ DISPID dispIdMember,
        /* [in] */ REFIID riid,
        /* [in] */ LCID lcid,
        /* [in] */ WORD wFlags,
        /* [out][in] */ DISPPARAMS *pDispParams,
        /* [out] */ VARIANT *pVarResult,
        /* [out] */ EXCEPINFO *pExcepInfo,
        /* [out] */ UINT *puArgErr)
    {
        _RPT1(_CRT_WARN, "CTest::Invoke(0x%08X)\n", dispIdMember);

        if (dispIdMember == 0xC8)
        {
            SelectionChanged();
        }

        return E_FAIL;
    }

public:

    CTest(const Shell32::IShellFolderViewDualPtr& shellFolderView)
    {
        _RPT0(_CRT_WARN, "CTest::CTest()\n");

        m_shellFolderView = shellFolderView;

        IConnectionPointContainerPtr cpc = m_shellFolderView;
        IConnectionPointPtr cp; cpc->FindConnectionPoint(__uuidof(Shell32::DShellFolderViewEvents), &cp);

        cp->Advise(this, &m_cookie);
    }

    virtual ~CTest()
    {
        _RPT0(_CRT_WARN, "CTest::~CTest()\n");

        IConnectionPointContainerPtr cpc = m_shellFolderView;
        IConnectionPointPtr cp; cpc->FindConnectionPoint(__uuidof(Shell32::DShellFolderViewEvents), &cp);

        cp->Unadvise(m_cookie);
    }

    void CTest::SelectionChanged()
    {
        _RPT0(_CRT_WARN, "CTest::SelectionChanged\n");

        Shell32::FolderItemsPtr folderItems = m_shellFolderView->SelectedItems();

        long count = folderItems->Count;

        _RPT1(_CRT_WARN, "count = %d\n", count);

        for (long i = 0; i < count; i++)
        {
            Shell32::FolderItemPtr folderItem = folderItems->Item(i);

            _RPT1(_CRT_WARN, "path = %s\n", (LPCTSTR)folderItem->Path);
        }
    }

private:

    Shell32::IShellFolderViewDualPtr m_shellFolderView;
    DWORD m_cookie;

};

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    ::CoInitialize(0);

    try
    {
        std::vector<CTest*> testContainer;

        SHDocVw::IShellWindowsPtr shellWindows(__uuidof(SHDocVw::ShellWindows));

        long count = shellWindows->Count;

        _RPT1(_CRT_WARN, "count = %d\n", count);

        for (long i = 0; i < count; i++)
        {
            SHDocVw::IWebBrowser2Ptr webBrowser = shellWindows->Item(i);
            Shell32::IShellFolderViewDualPtr shellFolderView = webBrowser->Document;

            if ((bool)shellFolderView)
            {
                CTest* test = new CTest(shellFolderView);

                testContainer.push_back(test);
            }
        }

        ::MessageBox(0, TEXT("Test"), TEXT("Test"), MB_OK);

        for (i = 0; i < (long)testContainer.size(); i++)
            delete testContainer[i];
    }
    catch (_com_error& e)
    {
    }

    ::CoUninitialize();

    return 0;
}

編集 削除
2tom  2013-04-01 08:54:23  No: 73654  IP: 192.*.*.*

>forty-five様
コードまで記載頂きありがとうございました。
おかげさまで目的の動作をすることができました。

編集 削除