//******************************************************************************************* // // Filename : Sfview.cpp // // Implementation file for CSFView // // Copyright (c) 1994 - 1996 Microsoft Corporation. All rights reserved // //******************************************************************************************* #include "Pch.H" #include "SFView.H" #include "SFVWnd.H" #include "Resource.H" #include "ThisGuid.H" #include "SFView.H" struct SFSTATE_HDR { CLSID clsThis; SFSTATE sfState; UINT nCols; } ; CSFView::CSFView(IShellFolder *psf, IShellFolderViewCallback *psfvcb) : m_psf(psf), m_erFolder(psf), m_erCB(psfvcb), m_pCDB(NULL), m_cView(this), m_uState(SVUIA_DEACTIVATE), m_pcmSel(NULL), m_cAccel(IDA_MAIN) { m_psfvcb = psfvcb; if (psfvcb) { psfvcb->AddRef(); } psf->AddRef(); m_aParamSort = DPA_Create(4); m_sfState.lParamSort = 0; } CSFView::~CSFView() { ReleaseSelContextMenu(); } STDMETHODIMP CSFView::QueryInterface(REFIID riid, void ** ppvObj) { static const IID *apiid[] = { &IID_IShellView, NULL }; LPUNKNOWN aobj[] = { (IShellView *)this }; return(QIHelper(riid, ppvObj, apiid, aobj)); } STDMETHODIMP_(ULONG) CSFView::AddRef() { return(AddRefHelper()); } STDMETHODIMP_(ULONG) CSFView::Release() { return(ReleaseHelper()); } STDMETHODIMP CSFView::GetWindow(HWND * lphwnd) { return(E_NOTIMPL); } STDMETHODIMP CSFView::ContextSensitiveHelp(BOOL fEnterMode) { return(E_NOTIMPL); } //***************************************************************************** // // CSFView::TranslateAccelerator // // Purpose: // Handle the accelerator keystrokes // // // Parameters: // LPMSG lpmsg - message structure // // // Comments: // //***************************************************************************** STDMETHODIMP CSFView::TranslateAccelerator(LPMSG lpmsg) { return(m_cAccel.TranslateAccelerator(m_cView, lpmsg) ? S_OK : S_FALSE); } STDMETHODIMP CSFView::EnableModeless(BOOL fEnable) { return(E_NOTIMPL); } //***************************************************************************** // // CSFView:UIActivate // // Purpose: // The explorer calls this member function whenever the activation // state of the view window is changed by a certain event that is // NOT caused by the shell view itself. // // // Parameters: // // UINT uState - UI activate flag // // Comments: // //***************************************************************************** STDMETHODIMP CSFView::UIActivate(UINT uState) { if (uState) { OnActivate(uState); } else { OnDeactivate(); } return S_OK; } STDMETHODIMP CSFView::Refresh() { FillList(FALSE); return S_OK;// yes, this is potentially bad, but we risk app compat problems if we change it. 2000/02/10 -ccooney } //***************************************************************************** // // CSFView::CreateViewWindow // // Purpose: // // called by IShellBrowser to create a contents pane window // // Parameters: // // IShellView *lpPrevView - previous view // LPCFOLDERSETTINGS lpfs - folder settings for the view // IShellBrowser *psb - pointer to the shell browser // RECT * prcView - view Rectangle // HWND * phWnd - pointer to Window handle // // // Comments: // //***************************************************************************** STDMETHODIMP CSFView::CreateViewWindow(IShellView *lpPrevView, LPCFOLDERSETTINGS lpfs, IShellBrowser * psb, RECT * prcView, HWND *phWnd) { *phWnd = NULL; if ((HWND)m_cView) { return(E_UNEXPECTED); } m_fs = *lpfs; m_psb = psb; // get the main window handle from shell browser psb->GetWindow(&m_hwndMain); // bring up the contents pane if (!m_cView.DoModeless(IDD_VIEW, m_hwndMain)) { return(E_OUTOFMEMORY); } *phWnd = m_cView; // map the current view mode into menu id and set the contents pane // view mode accordingly OnCommand(NULL, GET_WM_COMMAND_MPS(GetMenuIDFromViewMode(), 0, 0)); AddColumns(); RestoreViewState(); // size the contents pane SetWindowPos(m_cView, NULL, prcView->left, prcView->top, prcView->right-prcView->left, prcView->bottom-prcView->top, SWP_NOZORDER|SWP_SHOWWINDOW); FillList(TRUE); return(NOERROR); } STDMETHODIMP CSFView::DestroyViewWindow() { if (!(HWND)m_cView) { return(E_UNEXPECTED); } m_cView.DestroyWindow(); return(NOERROR); } STDMETHODIMP CSFView::GetCurrentInfo(LPFOLDERSETTINGS lpfs) { *lpfs = m_fs; return(NOERROR); } STDMETHODIMP CSFView::AddPropertySheetPages(DWORD dwReserved, LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam) { return(E_NOTIMPL); } STDMETHODIMP CSFView::SaveViewState() { SFSTATE_HDR hdr; LPSTREAM pstm; HRESULT hres = m_psb->GetViewStateStream(STGM_WRITE, &pstm); if (FAILED(hres)) { return(hres); } CEnsureRelease erStr(pstm); pstm->Write(&hdr, sizeof(hdr), NULL); hdr.clsThis = CLSID_ThisDll; hdr.sfState = m_sfState; hdr.nCols = SaveColumns(pstm); ULARGE_INTEGER libCurPosition; LARGE_INTEGER dlibMove; dlibMove.HighPart = 0; dlibMove.LowPart = 0; pstm->Seek(dlibMove, STREAM_SEEK_SET, &libCurPosition); hres = pstm->Write(&hdr, sizeof(hdr), NULL); return(hres); } STDMETHODIMP CSFView::SelectItem(LPCITEMIDLIST pidlItem, UINT uFlags) { return(E_NOTIMPL); } STDMETHODIMP CSFView::GetItemObject(UINT uItem, REFIID riid, void **ppv) { return(E_NOTIMPL); } int CSFView::AddObject(LPCITEMIDLIST pidl) { // Check the commdlg hook to see if we should include this // object. if (IncludeObject(pidl) != S_OK) { return(-1); } return(m_cView.AddObject(pidl)); } int CALLBACK CSFView::CompareIDs(LPVOID p1, LPVOID p2, LPARAM lParam) { PFNDPACOMPARE pfnCheckAPI = CompareIDs; CSFView *pThis = (CSFView *)lParam; HRESULT hres = pThis->m_psf->CompareIDs(pThis->m_sfState.lParamSort, (LPITEMIDLIST)p1, (LPITEMIDLIST)p2); return (hres); } //***************************************************************************** // // CSFView::FillList // // Purpose: // // Enumerates the objects in the namespace and fills up the // data structures // // // Comments: // //***************************************************************************** HRESULT CSFView::FillList(BOOL bInteractive) { m_cView.DeleteAllItems(); // Setup the enum flags. DWORD dwEnumFlags = SHCONTF_NONFOLDERS; if (ShowAllObjects()) { dwEnumFlags |= SHCONTF_INCLUDEHIDDEN ; } if (!(m_fs.fFlags & FWF_NOSUBFOLDERS)) { dwEnumFlags |= SHCONTF_FOLDERS; } // Create an enum object and get the IEnumIDList ptr LPENUMIDLIST peIDL; HRESULT hres = m_psf->EnumObjects(bInteractive ? m_hwndMain : NULL, dwEnumFlags, &peIDL); // Note the return may be S_FALSE which indicates no enumerator. // That's why we shouldn't use if (FAILED(hres)) if (hres != S_OK) { if (hres == S_FALSE) { return(NOERROR); } return(hres); } CEnsureRelease erEnum(peIDL); HDPA hdpaNew = DPA_Create(16); if (!hdpaNew) { return(E_OUTOFMEMORY); } LPITEMIDLIST pidl; ULONG celt; // Enumerate the idlist and insert into the DPA while (peIDL->Next(1, &pidl, &celt) == S_OK) { if (DPA_InsertPtr(hdpaNew, 0x7fff, pidl) == -1) { m_cMalloc.Free(pidl); } } DPA_Sort(hdpaNew, CompareIDs, (LPARAM)this); int cNew = DPA_GetPtrCount(hdpaNew); for (int i=0; i=0 && m_aParamSort) { DPA_InsertPtr(m_aParamSort, 0x7fff, (LPVOID)gdo.lParamSort); } if (hres != S_OK) { break; } } } // // Save (and check) column header information // Returns TRUE if the columns are the default width, FALSE otherwise // Side effect: the stream pointer is left right after the last column // BOOL CSFView::SaveColumns(LPSTREAM pstm) { UINT cxChar = m_cView.CharWidth(); BOOL bDefaultCols = TRUE; for (int i=0; ; ++i) { SFVCB_GETDETAILSOF_DATA gdo; gdo.pidl = NULL; if (CallCB(SFVCB_GETDETAILSOF, i, (LPARAM)&gdo) != S_OK) { break; } LV_COLUMN col; col.mask = LVCF_WIDTH; if (!m_cView.GetColumn(i, &col)) { // There is some problem, so just assume // default column widths bDefaultCols = TRUE; break; } if (col.cx != (int)(gdo.cChar * cxChar)) { bDefaultCols = FALSE; } // HACK: I don't really care about column widths larger // than 64K if (FAILED(pstm->Write(&col.cx, sizeof(USHORT), NULL))) { // There is some problem, so just assume // default column widths bDefaultCols = TRUE; break; } } return(bDefaultCols ? 0 : i); } void CSFView::RestoreColumns(LPSTREAM pstm, int nCols) { for (int i=0; iRead(&col.cx, sizeof(USHORT), NULL))) { break; } m_cView.SetColumn(i, &col); } } void CSFView::RestoreViewState() { SFSTATE_HDR hdr; LPSTREAM pstm; MergeToolBar(); // get the stream for storing view specific info if (FAILED(m_psb->GetViewStateStream(STGM_READ, &pstm))) { return; } CEnsureRelease erStr(pstm); if (FAILED(pstm->Read(&hdr, sizeof(hdr), NULL))) { return; } // Validate the header if (hdr.clsThis != CLSID_ThisDll) { return; } m_sfState = hdr.sfState; RestoreColumns(pstm, hdr.nCols); } void CSFView::CheckToolbar() { UINT idCmdCurView = GetMenuIDFromViewMode(); for (UINT idCmd=IDC_VIEW_ICON; idCmd<=IDC_VIEW_DETAILS; ++idCmd) { m_psb->SendControlMsg(FCW_TOOLBAR, TB_CHECKBUTTON, idCmd, (LPARAM)(idCmd == idCmdCurView), NULL); } } void CSFView::MergeToolBar() { enum { IN_STD_BMP = 0x4000, IN_VIEW_BMP = 0x8000, } ; static const TBBUTTON c_tbDefault[] = { { STD_COPY | IN_STD_BMP, IDC_EDIT_COPY, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, -1}, { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0,0}, 0, -1 }, // the bitmap indexes here are relative to the view bitmap { VIEW_LARGEICONS | IN_VIEW_BMP, IDC_VIEW_ICON, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0L, -1 }, { VIEW_SMALLICONS | IN_VIEW_BMP, IDC_VIEW_SMALLICON, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0L, -1 }, { VIEW_LIST | IN_VIEW_BMP, IDC_VIEW_LIST, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0L, -1 }, { VIEW_DETAILS | IN_VIEW_BMP, IDC_VIEW_DETAILS, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0L, -1 }, } ; LRESULT iStdBMOffset; LRESULT iViewBMOffset; TBADDBITMAP ab; ab.hInst = HINST_COMMCTRL; // hinstCommctrl ab.nID = IDB_STD_SMALL_COLOR; // std bitmaps m_psb->SendControlMsg(FCW_TOOLBAR, TB_ADDBITMAP, 8, (LPARAM)&ab, &iStdBMOffset); ab.nID = IDB_VIEW_SMALL_COLOR; // std view bitmaps m_psb->SendControlMsg(FCW_TOOLBAR, TB_ADDBITMAP, 8, (LPARAM)&ab, &iViewBMOffset); TBBUTTON tbActual[ARRAYSIZE(c_tbDefault)]; for (int i=0; iSetToolbarItems(tbActual, ARRAYSIZE(c_tbDefault), FCT_MERGE); CheckToolbar(); } HRESULT CreateShellFolderView(IShellFolder *psf, IShellFolderViewCallback *psfvcb, LPSHELLVIEW * ppsv) { CSFView *pSFView = new CSFView(psf, psfvcb); if (!pSFView) { return(E_OUTOFMEMORY); } pSFView->AddRef(); HRESULT hRes = pSFView->QueryInterface(IID_IShellView, (void **)ppsv); pSFView->Release(); return(hRes); }