ShellBrowserの実装 [ATL,WTL]

(2004.03.25)
#pragma once
 
#include "IShellBrowserImpl.h"
#include "ICommDlgBrowserImpl.h"
 
 
#ifndef WM_GETISHELLBROWSER
#define WM_GETISHELLBROWSER                (WM_USER + 7)
#endif
 
#define CLSID_THUMBSHELLVIEW            _T("{8BEBB290-52D0-11d0-B7F4-00C04FD706EC}")
 
 
/////////////////////////////////////////////////////////////////////////////
// CShellBrowser
 
template <class T>
class ATL_NO_VTABLE CShellBrowser :
    public IShellBrowserImpl<T>,
    public ICommDlgBrowserImpl<T>
{
public:
    CShellBrowser()
    {
        m_hWndShellView = NULL;
    }
    virtual ~CShellBrowser()
    {
    }
 
// IShellBrowser
public:
    STDMETHOD(QueryActiveShellView)(IShellView** ppshv)
    {
        if (ppshv == NULL)
        {
            return E_POINTER;
        }
 
        IShellViewPtr spShellView = m_spShellView;
        *ppshv = spShellView.Detach();
 
        return S_OK;
    }
 
// Window Message Handlers
public:
    // 完成
    // MESSAGE_HANDLER(WM_GETISHELLBROWSER, OnGetIShellBrowser)
    LRESULT OnGetIShellBrowser(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
    {
        T* pT = static_cast<T*>(this);
 
        IShellBrowserPtr spShellBrowser = pT->GetUnknown();
 
        pT->SetMsgHandled(FALSE);                    // 必要!!
        return (LRESULT)spShellBrowser.Detach();    // AddRef()しなくていいらしい。。
    }
 
public:
    // 完成
    HRESULT CreateShellViewWindow(IShellFolderPtr spShellFolder)
    {
        T* pT = static_cast<T*>(this);
 
        HRESULT hr = S_OK;
 
        if (spShellFolder == NULL)
        {
            ATLASSERT(0);
            return E_FAIL;
        }
 
        HWND hWndOwner = pT->GetHwnd();
        if (hWndOwner == NULL)
        {
            ATLASSERT(0);
            return E_FAIL;
        }
 
        // 以前のShellViewを保存
        IShellViewPtr spShellViewOld = m_spShellView;
 
        // メンバ変数を初期化
        m_spShellFolder = spShellFolder;
        m_spShellView = NULL;
        m_hWndShellView = NULL;
 
        // ビューのオブジェクトを作成する
        IShellViewPtr spShellView;
        hr = spShellFolder->CreateViewObject(hWndOwner, __uuidof(IShellView), (void**)&spShellView);
        if (FAILED(hr))
        {
            return E_FAIL;
        }
 
        FOLDERSETTINGS fs;
        if (spShellViewOld != NULL)
        {
            hr = spShellViewOld->GetCurrentInfo(&fs);
            if (FAILED(hr))
            {
                pT->GetDefaultFolderSettings(&fs);
            }
        }
        else
        {
            pT->GetDefaultFolderSettings(&fs);
        }
        
        IShellBrowserPtr spShellBrowser = pT->GetUnknown();
 
        CRect rc;
        ::GetClientRect(hWndOwner, &rc);
 
 
        // ビューのウィンドウを作成する
        HWND hWnd = NULL;
        hr = spShellView->CreateViewWindow(spShellView, &fs, spShellBrowser, &rc, &hWnd);
        if (FAILED(hr))
        {
            ATLASSERT(0);
            return hr;
        }
 
        // メンバ変数の設定
        //  → ビューのウィンドウの作成が終わった後にすること!!
        m_spShellView = spShellView;
        m_hWndShellView = hWnd;
 
        // 以前のビューのウィンドウ&オブジェクトを破棄する
        hr = pT->InternalDestroyShellViewWindow(spShellViewOld);
        if (FAILED(hr))
        {
            // 無視する。。
        }
 
        hr = spShellView->UIActivate(SVUIA_ACTIVATE_NOFOCUS);
        if (FAILED(hr))
        {
            // 無視する。。
        }
 
        return S_OK;
    }
    HRESULT CreateShellViewWindow2(IShellFolderPtr spShellFolder, CLSID& clsid)
    {
        T* pT = static_cast<T*>(this);
 
        HRESULT hr = S_OK;
 
        if (spShellFolder == NULL)
        {
            ATLASSERT(0);
            return E_FAIL;
        }
 
        HWND hWndOwner = pT->GetHwnd();
        if (hWndOwner == NULL)
        {
            ATLASSERT(0);
            return E_FAIL;
        }
 
        // 以前のShellViewを保存
        IShellViewPtr spShellViewOld = m_spShellView;
 
        // メンバ変数を初期化
        m_spShellFolder = spShellFolder;
        m_spShellView = NULL;
        m_hWndShellView = NULL;
 
        // ビューのオブジェクトを作成する
        IShellViewPtr spShellView;
        hr = spShellFolder->CreateViewObject(hWndOwner, __uuidof(IShellView), (void**)&spShellView);
        if (FAILED(hr))
        {
            return E_FAIL;
        }
 
        // IShellView2の取得
        IShellView2Ptr spShellView2 = spShellView;
 
        FOLDERSETTINGS fs;
        if (spShellViewOld != NULL)
        {
            hr = spShellViewOld->GetCurrentInfo(&fs);
            if (FAILED(hr))
            {
                pT->GetDefaultFolderSettings(&fs);
            }
        }
        else
        {
            pT->GetDefaultFolderSettings(&fs);
        }
        
        IShellBrowserPtr spShellBrowser = pT->GetUnknown();
 
        CRect rc;
        ::GetClientRect(hWndOwner, &rc);
 
        // ビューのウィンドウを作成する
        SV2CVW2_PARAMS sv2cvw2;
        memset(&sv2cvw2, 0, sizeof(sv2cvw2));
        sv2cvw2.cbSize = sizeof(sv2cvw2);
        sv2cvw2.psvPrev = spShellViewOld;
        sv2cvw2.pfs = &fs;
        sv2cvw2.psbOwner = spShellBrowser;
        sv2cvw2.prcView = &rc;
        sv2cvw2.pvid = &clsid;
        sv2cvw2.hwndView = NULL;
        hr = spShellView2->CreateViewWindow2(&sv2cvw2);
        if (FAILED(hr))
        {
            ATLASSERT(0);
            return hr;
        }
 
        // メンバ変数の設定
        //  → ビューのウィンドウの作成が終わった後にすること!!
        m_spShellView = spShellView;
        m_hWndShellView = sv2cvw2.hwndView;
 
        // 以前のビューのウィンドウ&オブジェクトを破棄する
        hr = pT->InternalDestroyShellViewWindow(spShellViewOld);
        if (FAILED(hr))
        {
            // 無視する。。
        }
 
        hr = spShellView2->UIActivate(SVUIA_ACTIVATE_NOFOCUS);
        if (FAILED(hr))
        {
            // 無視する。。
        }
 
        return S_OK;
    }
    // 完成
    HRESULT DestroyShellViewWindow()
    {
        T* pT = static_cast<T*>(this);
 
        HRESULT hr = S_OK;
 
        hr = pT->InternalDestroyShellViewWindow(m_spShellView);
        if (FAILED(hr))
        {
            // 無視する。。
        }
 
        m_spShellFolder = NULL;
        m_spShellView = NULL;
        m_hWndShellView = NULL;
 
        return S_OK;
    }
 
protected:
    HRESULT InternalDestroyShellViewWindow(IShellViewPtr spShellView)
    {
        HRESULT hr = S_OK;
 
        if (spShellView == NULL)
        {
            return S_FALSE;
        }
 
        hr = spShellView->UIActivate(SVUIA_DEACTIVATE);
        if (FAILED(hr))
        {
            // 無視する。。
        }
 
        hr = spShellView->DestroyViewWindow();
        if (FAILED(hr))
        {
            // 無視する。。
        }
 
        return S_OK;
    }
 
public:
    HRESULT SendMessageShellViewWindow(MSG* pMsg)
    {
        HRESULT hr = S_OK;
 
        if (m_spShellView == NULL)
        {
            return E_FAIL;
        }
 
        hr = m_spShellView->TranslateAccelerator(pMsg);
        if (FAILED(hr))
        {
            return hr;
        }
 
        return hr;
    }
    // とりあえず、Ctrlだけサポート
    HRESULT SendShortcutKeyShellViewWindow(int nKey)
    {
        T* pT = static_cast<T*>(this);
 
        HRESULT hr = S_OK;
 
        if (m_spShellView == NULL)
        {
            return S_OK;
        }
 
        HWND hWndOwner = pT->GetHwnd();
 
        BYTE keyStates[256];
        ::GetKeyboardState(keyStates);
        BYTE stateControl = keyStates[VK_CONTROL];
        keyStates[VK_CONTROL] = 0x80;
        ::SetKeyboardState(keyStates);
 
        this->SendMessageShellViewWindow(&CMsg(hWndOwner, WM_KEYDOWN, nKey));
        this->SendMessageShellViewWindow(&CMsg(hWndOwner, WM_KEYUP, nKey));
 
        keyStates[VK_CONTROL] = stateControl;
        ::SetKeyboardState(keyStates);
 
        return S_OK;
    }
 
public:
    virtual HRESULT GetDefaultFolderSettings(FOLDERSETTINGS* pfs)
    {
        if (pfs == NULL)
        {
            return E_POINTER;
        }
 
        pfs->ViewMode = FVM_ICON;
        pfs->fFlags = FWF_SHOWSELALWAYS | FWF_NOCLIENTEDGE;
 
        return S_OK;
    }
 
public:
    IShellFolderPtr m_spShellFolder;
    IShellViewPtr m_spShellView;
 
    HWND m_hWndShellView;
};
一覧に戻る
© 2003 WAC.com All Right Reserved.