#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;
};