|
|
#include "shellprv.h"
#include "cowsite.h"
#pragma hdrstop
// this is the comdlg frame that we will use to host the file picker object, it mostly is
// a stub that will forward accordingly
//
// the lifetime of this is handled by the DefView object we are attached to, which when
// the parent (CFolderViewHost) is destroyed will be taken down.
class CViewHostBrowser : public IShellBrowser, ICommDlgBrowser2, IServiceProvider { public: CViewHostBrowser(HWND hwndParent, IShellView *psvWeak, IUnknown *punkSiteWeak); ~CViewHostBrowser(); // IServiceProvider
STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void **ppv);
// *** IUnknown methods ***
STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObj); STDMETHOD_(ULONG,AddRef)(THIS); STDMETHOD_(ULONG,Release)(THIS);
// *** IOleWindow methods ***
STDMETHOD(GetWindow)(HWND *lphwnd) { *lphwnd = _hwndParent; return S_OK; } STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode) { return S_OK; }
// *** IShellBrowser methods *** (same as IOleInPlaceFrame)
STDMETHOD(InsertMenusSB)(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) { return E_NOTIMPL; } STDMETHOD(SetMenuSB)(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject) { return S_OK; } STDMETHOD(RemoveMenusSB)(HMENU hmenuShared) { return E_NOTIMPL; } STDMETHOD(SetStatusTextSB)(LPCOLESTR lpszStatusText) { return S_OK; } STDMETHOD(EnableModelessSB)(BOOL fEnable) { return S_OK; } STDMETHOD(TranslateAcceleratorSB)(LPMSG lpmsg, WORD wID) { return S_FALSE; }
// *** IShellBrowser methods ***
STDMETHOD(BrowseObject)(LPCITEMIDLIST pidl, UINT wFlags) { return E_FAIL; } STDMETHOD(GetViewStateStream)(DWORD grfMode, LPSTREAM *pStrm) { return E_FAIL; } STDMETHOD(GetControlWindow)(UINT id, HWND *lphwnd) { return E_NOTIMPL; } STDMETHOD(SendControlMsg)(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pret); STDMETHOD(QueryActiveShellView)(IShellView **ppshv); STDMETHOD(OnViewWindowActive)(IShellView *pshv) { return S_OK; } STDMETHOD(SetToolbarItems)(LPTBBUTTON lpButtons, UINT nButtons, UINT uFlags) { return S_OK; }
// *** ICommDlgBrowser methods ***
STDMETHOD(OnDefaultCommand)(IShellView *ppshv) { return S_OK; } STDMETHOD(OnStateChange)(IShellView *ppshv, ULONG uChange); STDMETHOD(IncludeObject)(IShellView *ppshv, LPCITEMIDLIST lpItem);
// *** ICommDlgBrowser2 methods ***
STDMETHOD(Notify)(IShellView *ppshv, DWORD dwNotifyType) { return S_FALSE; } STDMETHOD(GetDefaultMenuText)(IShellView *ppshv, WCHAR *pszText, INT cchMax) { return S_FALSE; } STDMETHOD(GetViewFlags)(DWORD *pdwFlags) { *pdwFlags = 0; return S_OK; }
private: long _cRef; HWND _hwndParent;
IShellView *_psvWeak; IUnknown *_punkSiteWeak; // not addref'd.
friend class CFolderViewHost; };
CViewHostBrowser::CViewHostBrowser(HWND hwndParent, IShellView *psvWeak, IUnknown *punkSiteWeak) : _cRef(1), _hwndParent(hwndParent), _psvWeak(psvWeak), _punkSiteWeak(punkSiteWeak) { // _psvWeak->AddRef(); // we hold a weak refernece to our parent, therefore don't AddRef()
// _punkSiteWeak->AddRef(); // we hold a weak reference to our parent, therefore don't AddRef()!
}
CViewHostBrowser::~CViewHostBrowser() { // _psvWeak->Release(); // this is scoped on the lifetime of our parent
// _punkSiteWeak->Release(); // we hold a weak reference to our parent, therefore don't Release()!
}
HRESULT CViewHostBrowser::QueryInterface(REFIID riid, void **ppvObj) { static const QITAB qit[] = { QITABENT(CViewHostBrowser, IShellBrowser), // IID_IShellBrowser
QITABENT(CViewHostBrowser, ICommDlgBrowser2), // IID_ICommDlgBrowser2
QITABENTMULTI(CViewHostBrowser, ICommDlgBrowser, ICommDlgBrowser2), // IID_ICommDlgBrowser
QITABENT(CViewHostBrowser, IServiceProvider), // IID_IServiceProvider
{ 0 }, }; return QISearch(this, qit, riid, ppvObj); }
ULONG CViewHostBrowser::AddRef() { return InterlockedIncrement(&_cRef); }
ULONG CViewHostBrowser::Release() { if (InterlockedDecrement(&_cRef)) return _cRef;
delete this; return 0; }
// IShellBrowser
HRESULT CViewHostBrowser::SendControlMsg(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pret) { if (pret) *pret = 0L; return S_OK; }
HRESULT CViewHostBrowser::QueryActiveShellView(IShellView **ppshv) { HRESULT hr = E_NOINTERFACE; if (_psvWeak) { hr = _psvWeak->QueryInterface(IID_PPV_ARG(IShellView, ppshv)); } return hr; }
// ICommDlgBrowser - these are forwarded to our site object
HRESULT CViewHostBrowser::OnStateChange(IShellView *ppshv, ULONG uChange) { HRESULT hr = S_OK; ICommDlgBrowser *pcdb; if (SUCCEEDED(IUnknown_QueryService(_punkSiteWeak, SID_SCommDlgBrowser, IID_PPV_ARG(ICommDlgBrowser, &pcdb)))) { hr = pcdb->OnStateChange(ppshv, uChange); pcdb->Release(); } return hr; }
HRESULT CViewHostBrowser::IncludeObject(IShellView *ppshv, LPCITEMIDLIST lpItem) { HRESULT hr = S_OK; ICommDlgBrowser *pcdb; if (SUCCEEDED(IUnknown_QueryService(_punkSiteWeak, SID_SCommDlgBrowser, IID_PPV_ARG(ICommDlgBrowser, &pcdb)))) { hr = pcdb->IncludeObject(ppshv, lpItem); pcdb->Release(); } return hr; }
// IServiceProvider
HRESULT CViewHostBrowser::QueryService(REFGUID guidService, REFIID riid, void **ppvObj) { HRESULT hr = E_FAIL; *ppvObj = NULL; if (IsEqualGUID(guidService, SID_SCommDlgBrowser)) { hr = this->QueryInterface(riid, ppvObj); }
return hr; }
// this is the file picker object it creates an IShellView (which for us should result in
// a defview implement). from this we can then give the window to the caller and they
// can place on their dialog as needed.
class CFolderViewHost : public IFolderViewHost, IServiceProvider, IOleWindow, IFolderView, CObjectWithSite { public: CFolderViewHost(); ~CFolderViewHost();
// *** IFolderViewHost ***
STDMETHODIMP Initialize(HWND hwndParent, IDataObject *pdo, RECT *prc);
// *** IUnknown methods ***
STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObj); STDMETHOD_(ULONG,AddRef)(THIS); STDMETHOD_(ULONG,Release)(THIS);
// *** IOleWindow methods ***
STDMETHOD(GetWindow)(HWND *lphwnd) { *lphwnd = _hwndView; return S_OK; } STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode) { return S_OK; }
// IServiceProvider
STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void **ppv) { return IUnknown_QueryService(_punkSite, guidService, riid, ppv); }
// IFolderView
STDMETHODIMP GetCurrentViewMode(UINT *pViewMode) { return _pfv->GetCurrentViewMode(pViewMode); } STDMETHODIMP SetCurrentViewMode(UINT ViewMode) { return _pfv->SetCurrentViewMode(ViewMode); } STDMETHODIMP GetFolder(REFIID ridd, void **ppv) { return _pfv->GetFolder(ridd, ppv); } STDMETHODIMP Item(int iItemIndex, LPITEMIDLIST *ppidl) { return _pfv->Item(iItemIndex, ppidl); } STDMETHODIMP ItemCount(UINT uFlags, int *pcItems) { return _pfv->ItemCount(uFlags, pcItems); } STDMETHODIMP Items(UINT uFlags, REFIID riid, void **ppv) { return _pfv->Items(uFlags, riid, ppv); } STDMETHODIMP GetSelectionMarkedItem(int *piItem) { return _pfv->GetSelectionMarkedItem(piItem); } STDMETHODIMP GetFocusedItem(int *piItem) { return _pfv->GetFocusedItem(piItem); } STDMETHODIMP GetItemPosition(LPCITEMIDLIST pidl, POINT* ppt) { return _pfv->GetItemPosition(pidl, ppt); } STDMETHODIMP GetSpacing(POINT* ppt) { return _pfv->GetSpacing(ppt); } STDMETHODIMP GetDefaultSpacing(POINT* ppt) { return _pfv->GetDefaultSpacing(ppt); } STDMETHODIMP GetAutoArrange() { return _pfv->GetAutoArrange(); } STDMETHODIMP SelectItem(int iItem, DWORD dwFlags) { return _pfv->SelectItem(iItem, dwFlags); } STDMETHODIMP SelectAndPositionItems(UINT cidl, LPCITEMIDLIST* apidl, POINT* apt, DWORD dwFlags) { return _pfv->SelectAndPositionItems(cidl, apidl, apt, dwFlags); }
private: long _cRef; IFolderView *_pfv; // IFolderView
HWND _hwndView; };
CFolderViewHost::CFolderViewHost() : _cRef(1) { }
CFolderViewHost::~CFolderViewHost() { if (_pfv) _pfv->Release(); }
HRESULT CFolderViewHost::QueryInterface(REFIID riid, void **ppvObj) { static const QITAB qit[] = { QITABENT(CFolderViewHost, IFolderViewHost), // IID_IFolderViewHost
QITABENT(CFolderViewHost, IOleWindow), // IID_IOleWindow
QITABENT(CFolderViewHost, IFolderView), // IID_IFolderView
QITABENT(CFolderViewHost, IServiceProvider), // IID_IServiceProvider
QITABENT(CFolderViewHost, IObjectWithSite), // IID_IObjectWithSite
{ 0 }, }; return QISearch(this, qit, riid, ppvObj); }
ULONG CFolderViewHost::AddRef() { return InterlockedIncrement(&_cRef); }
ULONG CFolderViewHost::Release() { if (InterlockedDecrement(&_cRef)) return _cRef;
delete this; return 0; }
// the initialize method handles the creation of the view object from the.
HRESULT CFolderViewHost::Initialize(HWND hwndParent, IDataObject *pdo, RECT *prc) { // first we perform a namespace walk, this will retrieve our selection from the view
// using this we can then create the view object.
INamespaceWalk *pnsw; HRESULT hr = CoCreateInstance(CLSID_NamespaceWalker, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(INamespaceWalk, &pnsw)); if (SUCCEEDED(hr)) { LPITEMIDLIST *aItems = NULL; UINT cItems = 0;
hr = pnsw->Walk(pdo, NSWF_NONE_IMPLIES_ALL, 0, NULL); if (SUCCEEDED(hr)) { IShellFolder *psf = NULL;
hr = pnsw->GetIDArrayResult(&cItems, &aItems); if (S_OK == hr) { hr = SHBindToIDListParent(aItems[0], IID_PPV_ARG(IShellFolder, &psf), NULL); } else if (S_FALSE == hr) { hr = E_FAIL; // fail unless we perform the bind.
STGMEDIUM medium; LPIDA pida = DataObj_GetHIDA(pdo, &medium); if (pida) { if (pida->cidl == 1) { LPITEMIDLIST pidl = IDA_ILClone(pida, 0); if (pidl) { hr = SHBindToObjectEx(NULL, pidl, NULL, IID_PPV_ARG(IShellFolder, &psf)); ILFree(pidl); } } HIDA_ReleaseStgMedium(pida, &medium); } } else { hr = E_FAIL; }
if (SUCCEEDED(hr)) { IShellView *psv; hr = psf->CreateViewObject(hwndParent, IID_PPV_ARG(IShellView, &psv)); if (SUCCEEDED(hr)) { CViewHostBrowser *pvhb = new CViewHostBrowser(hwndParent, psv, SAFECAST(this, IServiceProvider*)); if (pvhb) { hr = psv->QueryInterface(IID_PPV_ARG(IFolderView, &_pfv)); if (SUCCEEDED(hr)) { FOLDERSETTINGS fs = {0}; fs.ViewMode = FVM_THUMBNAIL; fs.fFlags = FWF_AUTOARRANGE|FWF_NOWEBVIEW|FWF_HIDEFILENAMES|FWF_CHECKSELECT;
IFolderView *pfv; if (SUCCEEDED(IUnknown_QueryService(_punkSite, SID_SFolderView, IID_PPV_ARG(IFolderView, &pfv)))) { pfv->GetCurrentViewMode(&fs.ViewMode); pfv->Release(); }
hr = psv->CreateViewWindow(NULL, &fs, pvhb, prc, &_hwndView); if (SUCCEEDED(hr)) { hr = psv->UIActivate(SVUIA_INPLACEACTIVATE); } }
pvhb->Release(); } else { hr = E_OUTOFMEMORY; } psv->Release(); }
for (int i = 0; SUCCEEDED(hr) && (i != cItems); i++) { LPCITEMIDLIST pidlChild = ILFindLastID(aItems[i]); hr = _pfv->SelectAndPositionItems(1, &pidlChild, NULL, SVSI_CHECK); }
psf->Release(); }
FreeIDListArray(aItems, cItems); }
pnsw->Release(); }
return hr; }
STDAPI CFolderViewHost_CreateInstance(IUnknown *punkOut, REFIID riid, void **ppv) { CFolderViewHost *pfp = new CFolderViewHost(); if (!pfp) return E_OUTOFMEMORY;
HRESULT hr = pfp->QueryInterface(riid, ppv); pfp->Release(); return hr; }
|