View.cpp
上传用户:hy_wanghao
上传日期:2007-01-08
资源大小:279k
文件大小:36k
- // View.cpp : Implementation of CView
- #include "stdafx.h"
- #include "View.h"
- #include "Misc.h"
- #include "DropSource.h"
- #include "DataObject.h"
- #include "PropDlg.h"
- /////////////////////////////////////////////////////////////////////////////
- // CView
- HRESULT CView::FinalConstruct()
- {
- ATLTRACE(_T("CView::FinalConstructn"));
- // Win95 requires us to call ::OleInitialize() on the View because we use
- // ::OleSetClipboard() and ::DoDragDrop() ???
- // But we've already called it! The 2nd call is ignored on other platforms.
- ::OleInitialize(NULL);
- // Reset variables
- m_pFolder = NULL;
- m_hAccels = ::LoadAccelerators(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_ACCELERATOR));
- m_hMenu = NULL;
- m_bInEdit = false;
- m_bShowDeletedFiles = false;
- m_dwListViewStyle = WS_TABSTOP |
- WS_VISIBLE |
- WS_CHILD |
- WS_BORDER |
- LVS_REPORT |
- LVS_AUTOARRANGE |
- LVS_EDITLABELS |
- LVS_SHOWSELALWAYS |
- LVS_SHAREIMAGELISTS;
- return S_OK;
- }
- void CView::FinalRelease()
- {
- ATLASSERT(m_pFolder);
- m_pFolder->Release();
- ::OleUninitialize();
- }
- /////////////////////////////////////////////////////////////////////////////
- // IShellView
- STDMETHODIMP CView::CreateViewWindow(
- IShellView *lpPrevView,
- LPCFOLDERSETTINGS lpFS,
- IShellBrowser *pSB,
- RECT *prcView,
- HWND *phWnd)
- {
- ATLTRACE("CView::CreateViewWindown");
- ATLASSERT(m_pFolder);
- HRESULT Hr;
- HR( IShellViewImpl<CView>::CreateViewWindow(lpPrevView, lpFS, pSB, prcView, phWnd) );
- // Register view as drop target
- LPDROPTARGET pDropTarget = NULL;
- HR( m_pFolder->CreateViewObject(m_hWnd, IID_IDropTarget, (LPVOID *)&pDropTarget) );
- HR( ::RegisterDragDrop(m_hwndList, pDropTarget) );
- return S_OK;
- }
- STDMETHODIMP CView::DestroyViewWindow(void)
- {
- ATLTRACE("CView::DestroyViewWindown");
- ATLASSERT(::IsWindow(m_hwndList));
- ::RevokeDragDrop(m_hwndList);
- return IShellViewImpl<CView>::DestroyViewWindow();
- }
- STDMETHODIMP CView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppRetVal)
- {
- ATLTRACE(_T("CView::GetItemObject %s (%d)n"), DbgGetIID(riid), uItem);
- VALIDATE_OUT_POINTER(ppRetVal);
- switch( uItem ) {
- case SVGIO_BACKGROUND:
- {
- HRESULT Hr;
- Hr = m_pFolder->CreateViewObject(NULL, riid, ppRetVal);
- if( FAILED(Hr) ) Hr = m_pFolder->QueryInterface(riid, ppRetVal);
- return Hr;
- }
- case SVGIO_SELECTION:
- {
- CPidlList pidls(m_hwndList);
- return m_pFolder->GetUIObjectOf(m_hWnd, pidls.GetCount(), pidls, riid, NULL, ppRetVal);
- }
- case SVGIO_ALLVIEW:
- {
- CPidlList pidls(m_hwndList, LVNI_ALL);
- return m_pFolder->GetUIObjectOf(m_hWnd, pidls.GetCount(), pidls, riid, NULL, ppRetVal);
- }
- default:
- ATLASSERT(false);
- return E_NOINTERFACE;
- }
- }
- STDMETHODIMP CView::TranslateAccelerator(LPMSG pmsg)
- {
- ATLASSERT(pmsg);
- if( m_bInEdit ) {
- if( (pmsg->message >= WM_KEYFIRST) && (pmsg->message <= WM_KEYLAST) ) {
- ::TranslateMessage(pmsg);
- ::DispatchMessage(pmsg);
- return S_OK;
- }
- }
- else {
- if( ::TranslateAccelerator(m_hWnd, m_hAccels, pmsg) ) return S_OK;
- }
- return S_FALSE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Implementation
- HRESULT CView::_Init(CFolder *pFolder)
- {
- ATLTRACE("CView::_Initn");
- ATLASSERT(pFolder);
- m_pFolder = pFolder;
- m_pFolder->AddRef();
- return S_OK;
- }
- // Sort List View item callback function.
- int CALLBACK CView::_ListViewSortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
- {
- LPCPIDLDATA pData1 = (LPCPIDLDATA)CPidl::_GetLastItem((LPCITEMIDLIST)lParam1);
- LPCPIDLDATA pData2 = (LPCPIDLDATA)CPidl::_GetLastItem((LPCITEMIDLIST)lParam2);
- return CFolder::_CompareItems((short)lParamSort, pData1, pData2);
- }
- // Setup ListView control
- // Adds column headers and clears all items.
- BOOL CView::_InitListView()
- {
- ATLTRACE("CView::_InitListViewn");
- // Empty the list
- ListView_DeleteAllItems(m_hwndList);
- // Initialize the columns
- LV_COLUMN lvColumn;
- CResString<64> str;
- lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
- lvColumn.fmt = LVCFMT_LEFT;
- lvColumn.pszText = str; // We reuse same buffer for all columns
- str.LoadString(IDS_COL_NAME);
- lvColumn.cx = 210;
- ListView_InsertColumn(m_hwndList, COL_NAME, &lvColumn);
- str.LoadString(IDS_COL_SIZE);
- lvColumn.cx = 70;
- lvColumn.fmt = LVCFMT_RIGHT;
- ListView_InsertColumn(m_hwndList, COL_SIZE, &lvColumn);
- str.LoadString(IDS_COL_TYPE);
- lvColumn.cx = 80;
- lvColumn.fmt = LVCFMT_LEFT;
- ListView_InsertColumn(m_hwndList, COL_TYPE, &lvColumn);
- str.LoadString(IDS_COL_MODIFIED);
- lvColumn.cx = 130;
- ListView_InsertColumn(m_hwndList, COL_TIME, &lvColumn);
- if( m_ShellFlags.fShowAttribCol ) {
- str.LoadString(IDS_COL_ATTR);
- lvColumn.cx = 60;
- lvColumn.fmt = LVCFMT_RIGHT;
- ListView_InsertColumn(m_hwndList, COL_ATTRIBS, &lvColumn);
- }
- ListView_SetImageList(m_hwndList, _Module.m_ImageLists.m_hImageListLarge, LVSIL_NORMAL);
- ListView_SetImageList(m_hwndList, _Module.m_ImageLists.m_hImageListSmall, LVSIL_SMALL);
- return TRUE;
- }
- BOOL CView::_FillListView()
- {
- ATLTRACE(_T("CView::_FillListViewn"));
- DWORD dwFlags = SHCONTF_NONFOLDERS | SHCONTF_FOLDERS;
- if( m_bShowDeletedFiles ) dwFlags |= SHCONTF_INCLUDEDELETED;
- LPENUMIDLIST pEnumIDList;
- if (SUCCEEDED(m_pFolder->EnumObjects(m_hWnd, dwFlags, &pEnumIDList) ) ) {
- // Turn the listview's redrawing off
- ::SendMessage(m_hwndList, WM_SETREDRAW, FALSE, 0L);
-
- DWORD dwFetched = 0;
- LPITEMIDLIST pidl = NULL;
- int iItem = 0;
- while( (S_OK == pEnumIDList->Next(1, &pidl, &dwFetched)) && (dwFetched!=0) ) {
- LPCPIDLDATA pData = pidl_cast(pidl);
- LV_ITEM lvi = { 0 };
- lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_PARAM;
- lvi.pszText = LPSTR_TEXTCALLBACK;
- lvi.iImage = I_IMAGECALLBACK;
- lvi.iItem = iItem++;
- lvi.state = 0;
- if( pData->dwEntryFlags & EF_DELETED ) lvi.state |= LVIS_CUT;
- lvi.stateMask = (UINT)-1;
- lvi.lParam = (LPARAM)CPidl::_Copy(pidl);
- ListView_InsertItem(m_hwndList, &lvi);
- }
- pEnumIDList->Release();
- ListView_SortItems(m_hwndList, _ListViewSortFunc, 0);
- // Turn the listview's redrawing back on and force it to draw
- ::SendMessage(m_hwndList, WM_SETREDRAW, TRUE, 0L);
- ::InvalidateRect(m_hwndList, NULL, TRUE);
- ::UpdateWindow(m_hwndList);
- }
- return TRUE;
- }
- // Merge the toolbar
- BOOL CView::_MergeToolbar(UINT uState)
- {
- ATLTRACE(_T("CView::_MergeToolbarn"));
- ATLASSERT(m_pShellBrowser);
- static NS_TOOLBUTTONINFO ToolBarItems[] =
- {
- TBI_STD, { STD_CUT, ID_EDIT_CUT, 0, TBSTYLE_BUTTON, 0, 0 },
- TBI_STD, { STD_COPY, ID_EDIT_COPY, 0, TBSTYLE_BUTTON, 0, 0 },
- TBI_STD, { STD_PASTE, ID_EDIT_PASTE, 0, TBSTYLE_BUTTON, 0, 0 },
- TBI_STD, { 0, 0, 0, TBSTYLE_SEP, 0, 0 },
- TBI_STD, { STD_DELETE, ID_EDIT_DELETE, 0, TBSTYLE_BUTTON, 0, 0 },
- TBI_STD, { STD_PROPERTIES, ID_EDIT_PROPERTIES, 0, TBSTYLE_BUTTON, 0, 0 },
- };
- // Don't unmerge toolbar; Shell will do it.
- if( uState==SVUIA_DEACTIVATE ) return TRUE;
- HRESULT Hr;
- LRESULT lOffsetFile = 0;
- LRESULT lOffsetView = 0;
- LRESULT lOffsetCustom = 0;
- Hr = m_pShellBrowser->SetToolbarItems(NULL, 0, FCT_MERGE);
- // Add the toolbar bitmaps (use standard COMCTRL bitmaps)
- TBADDBITMAP tbab;
- tbab.hInst = HINST_COMMCTRL;
- tbab.nID = IDB_STD_SMALL_COLOR;
- Hr = m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ADDBITMAP, 0, (LPARAM)&tbab, &lOffsetFile);
- tbab.hInst = HINST_COMMCTRL;
- tbab.nID = IDB_VIEW_SMALL_COLOR;
- Hr = m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ADDBITMAP, 0, (LPARAM)&tbab, &lOffsetView);
- // Add the buttons
- BOOL res = _AppendToolbarItems(ToolBarItems, lengthof(ToolBarItems),
- lOffsetFile,lOffsetView,lOffsetCustom);
- if( !res ) return FALSE;
- _UpdateToolbar();
- return TRUE;
- }
- // Updates the toolbar.
- BOOL CView::_UpdateToolbar()
- {
- ATLTRACE(_T("CView::_UpdateToolbarn"));
- ATLASSERT(m_pShellBrowser);
- ATLASSERT(::IsWindow(m_hwndList));
- LPARAM lResult;
- UINT nCount = ListView_GetSelectedCount(m_hwndList);
- m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON, ID_EDIT_COPY, MAKELPARAM(nCount!=0, 0), &lResult);
- m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON, ID_EDIT_CUT, MAKELPARAM(nCount!=0, 0), &lResult);
- m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON, ID_EDIT_PROPERTIES, MAKELPARAM(nCount==1, 0), &lResult);
- m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON, ID_EDIT_DELETE, MAKELPARAM(nCount!=0, 0), &lResult);
- BOOL bClipboardCopy = _HasClipDataReady();
- m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON, ID_EDIT_PASTE, MAKELPARAM(bClipboardCopy, 0), &lResult);
- return TRUE;
- }
- // Merge our own menus into the Shell.
- // The 'uState' argument is called with SVUIA_DEACTIVATE
- // when the menus should be destroyed rather than created.
- BOOL CView::_MergeMenus(UINT uState)
- {
- ATLTRACE(_T("CView::_MergeMenus (%d)n"), uState);
- ATLASSERT(m_pShellBrowser);
- typedef enum {
- MENU_INDEX_FILE = 0,
- MENU_INDEX_EDIT = 1,
- MENU_INDEX_VIEW = 2,
- MENU_INDEX_HELP = 3,
- } MENUINDEX;
- if( uState!=SVUIA_DEACTIVATE ) {
- // Create the menu
- // Some undocumented behaviour allows us to tell when the
- // menu is merge when browsing solely in the folder tree or
- // when to merge the view menu. There's a difference because
- // the Explorer adds the "Delete", "Rename" etc items when
- // you browse in the folder tree.
- // We must look at the "uState": SVUIA_ACTIVATE_FOCUS means
- // the view menu should be merged, SVUIA_ACTIVATE_NOFOCUS
- // is the folder tree menu.
- ATLASSERT(m_hMenu==NULL); // Don't merge twice without unmerge
- if( m_hMenu!=NULL ) return FALSE;
- // Load the menu we build the Shell menu from.
- HMENU hSharedMenu = ::LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MENU));
- ATLASSERT(hSharedMenu);
- // Merge the menus
- m_hMenu = ::CreateMenu();
- ATLASSERT(m_hMenu);
- if( m_hMenu==NULL ) return FALSE;
- OLEMENUGROUPWIDTHS omw = {0, 0, 0, 0, 0, 0};
- m_pShellBrowser->InsertMenusSB(m_hMenu, &omw);
- // Add top level sub-menus...
- MENUITEMINFO mii = { 0 };
- mii.cbSize = sizeof(mii);
- mii.fMask = MIIM_SUBMENU;
- // Merge our items into the File menu
- if( uState==SVUIA_ACTIVATE_FOCUS ) {
- if( ::GetMenuItemInfo(m_hMenu, FCIDM_MENU_FILE, FALSE, &mii)) {
- HMENU hMenuPopup = ::GetSubMenu(hSharedMenu, MENU_INDEX_FILE);
- _AppendMenu(mii.hSubMenu, hMenuPopup, 0);
- }
- }
- // Merge our items into the Edit menu
- if( uState==SVUIA_ACTIVATE_FOCUS ) {
- if( ::GetMenuItemInfo(m_hMenu, FCIDM_MENU_EDIT, FALSE, &mii)) {
- // Merge our menu
- HMENU hMenuPopup = ::GetSubMenu(hSharedMenu, MENU_INDEX_EDIT);
- _AppendMenu(mii.hSubMenu, hMenuPopup, 0);
- }
- }
- // Merge our items into the View menu
- if( ::GetMenuItemInfo(m_hMenu, FCIDM_MENU_VIEW, FALSE, &mii)) {
- // Find the position of the Seperator
- UINT nPos = _GetMenuPosFromID(mii.hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS);
- // and merge...
- HMENU hMenuPopup = ::GetSubMenu(hSharedMenu, MENU_INDEX_VIEW);
- _AppendMenu(mii.hSubMenu, hMenuPopup, nPos+1);
- }
- // Merge our items into the Help menu
- if( ::GetMenuItemInfo(m_hMenu, FCIDM_MENU_HELP, FALSE, &mii)) {
- // Merge our menu
- HMENU hMenuPopup = ::GetSubMenu(hSharedMenu, MENU_INDEX_HELP);
- _AppendMenu(mii.hSubMenu, hMenuPopup, 0);
- }
- m_pShellBrowser->SetMenuSB(m_hMenu, NULL, m_hWnd);
- ::DestroyMenu(hSharedMenu);
- }
- else {
- // Dismantle menu
- m_pShellBrowser->SetMenuSB(NULL, NULL, NULL);
- if( m_hMenu!=NULL ) {
- ATLASSERT(::IsMenu(m_hMenu));
- m_pShellBrowser->RemoveMenusSB(m_hMenu);
- ::DestroyMenu(m_hMenu);
- m_hMenu = NULL;
- }
- }
- return TRUE;
- }
- // Updates the menu.
- // This function is usually called when the user opens one of the
- // Shell menus. The HMENU argument is the handled to the opened menu.
- BOOL CView::_UpdateMenu(HMENU hMenu)
- {
- ATLTRACE(_T("CView::_UpdateMenun"));
- if( !::IsMenu(hMenu) ) return FALSE; // Gets called with our own File sub-menu popups?
- // Deselect some menuitems if there are too many/few ListView items selected
- UINT nCount = ListView_GetSelectedCount(m_hwndList);
- ::EnableMenuItem(hMenu, ID_FILE_OPEN, nCount==1 ? MF_ENABLED | MF_BYCOMMAND : MF_GRAYED | MF_BYCOMMAND);
- ::EnableMenuItem(hMenu, ID_FILE_RENAME, nCount==1 ? MF_ENABLED | MF_BYCOMMAND : MF_GRAYED | MF_BYCOMMAND);
- ::EnableMenuItem(hMenu, ID_EDIT_PROPERTIES, nCount<=1 ? MF_ENABLED | MF_BYCOMMAND : MF_GRAYED | MF_BYCOMMAND);
- ::EnableMenuItem(hMenu, ID_EDIT_COPY, nCount!=0 ? MF_ENABLED | MF_BYCOMMAND : MF_GRAYED | MF_BYCOMMAND);
- ::EnableMenuItem(hMenu, ID_EDIT_CUT, nCount!=0 ? MF_ENABLED | MF_BYCOMMAND : MF_GRAYED | MF_BYCOMMAND);
- ::EnableMenuItem(hMenu, ID_EDIT_DELETE, nCount!=0 ? MF_ENABLED | MF_BYCOMMAND : MF_GRAYED | MF_BYCOMMAND);
- ::CheckMenuItem(hMenu, ID_VIEW_DELETEDFILES, m_bShowDeletedFiles ? MF_CHECKED | MF_BYCOMMAND : MF_UNCHECKED | MF_BYCOMMAND);
- // Check the "View" menu
- UINT idMenu = ID_VIEW_REPORT;
- switch( m_FolderSettings.ViewMode ) {
- case FVM_ICON:
- idMenu = ID_VIEW_LARGEICONS;
- break;
- case FVM_SMALLICON:
- idMenu = ID_VIEW_SMALLICONS;
- break;
- case FVM_LIST:
- idMenu = ID_VIEW_LIST;
- break;
- case FVM_DETAILS:
- idMenu = ID_VIEW_REPORT;
- break;
- }
- ATLASSERT(ID_VIEW_LARGEICONS<ID_VIEW_REPORT);
- ::CheckMenuRadioItem(hMenu, ID_VIEW_LARGEICONS, ID_VIEW_REPORT, idMenu, MF_BYCOMMAND);
- BOOL bClipboardCopy = _HasClipDataReady();
- ::EnableMenuItem(hMenu, ID_EDIT_PASTE, bClipboardCopy ? MF_ENABLED | MF_BYCOMMAND : MF_GRAYED | MF_BYCOMMAND);
- return TRUE;
- }
- // Check that data exists on the clipboard for paste
- BOOL CView::_HasClipDataReady()
- {
- BOOL bClipboardCopy = FALSE;
- CComPtr<IDataObject> spDataObject;
- if( SUCCEEDED( ::OleGetClipboard(&spDataObject) ) ) {
- if( !bClipboardCopy ) {
- FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
- if( SUCCEEDED( spDataObject->QueryGetData(&fe) ) ) {
- bClipboardCopy = TRUE;
- }
- }
- if( !bClipboardCopy ) {
- FORMATETC fe = { _Module.m_CFSTR_FILEDESCRIPTOR, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
- if( SUCCEEDED( spDataObject->QueryGetData(&fe) ) ) {
- bClipboardCopy = TRUE;
- }
- }
- if( bClipboardCopy ) {
- if( m_pFolder->_IsDroppedPathSame(spDataObject) ) bClipboardCopy = FALSE;
- }
- }
- return bClipboardCopy;
- }
- // This method handles both "Copy/Cut" menu-items and drag'n'drop
- // operations. In both cases we need to create an IDataObject object
- // and pass it to Windows.
- HRESULT CView::_DoCopyOperation(bool bDragDrop, bool bCut)
- {
- ATLTRACE(_T("CView::_DoCopyOperationn"));
-
- // Get list from selected ListView items
- CPidlList pidls(m_hwndList);
- pidls.Filter(m_pFolder, bCut ? SFGAO_CANMOVE : SFGAO_CANCOPY);
- if( pidls.GetCount()==0 ) return E_FAIL;
- // Update the ListView to reflect the possible CUT operation.
- // Remove all previous CUT items.
- if( !bDragDrop ) ListView_SetItemState(m_hwndList, -1, 0, LVIS_CUT);
- if( bCut ) {
- // Now mark all selected items as CUT
- int nItem = -1;
- while( (nItem = ListView_GetNextItem(m_hwndList, nItem, LVNI_SELECTED)) != -1 ) {
- ListView_SetItemState(m_hwndList, nItem, LVIS_CUT, LVIS_CUT);
- }
- }
- // Create a IDataObject and let the system handle operation...
- HRESULT Hr;
- CComPtr<IDataObject> spDataObject;
- Hr = m_pFolder->GetUIObjectOf(m_hWnd,
- pidls.GetCount(),
- pidls,
- IID_IDataObject,
- NULL,
- (LPVOID*)&spDataObject);
- if( SUCCEEDED(Hr) && (spDataObject!=NULL) ) {
- if( bCut ) {
- // If we're doing 'cut' in copy/cut/paste, we need
- // to notify the IDataObject about our intention
- DataObj_SetDWORD(spDataObject, _Module.m_CFSTR_PREFERREDDROPEFFECT, DROPEFFECT_MOVE);
- }
- if( bDragDrop ) {
- // If we're dragging then call Window's DoDragDrop()
- // method with a freshly created IDropSource object
- CComObject<CDropSource> *pDropSource;
- HR( CComObject<CDropSource>::CreateInstance(&pDropSource) );
- pDropSource->AddRef();
- DWORD dwEffect = 0;
- Hr = ::DoDragDrop(spDataObject,
- pDropSource,
- DROPEFFECT_COPY | DROPEFFECT_MOVE,
- &dwEffect);
- // If the drag drop turned out to be a move operation, we should
- // delete the files
- if( (Hr==DRAGDROP_S_DROP) && (dwEffect & DROPEFFECT_MOVE) ) {
- CPidlList pidls(m_hwndList);
- m_pFolder->_DeleteFiles(pidls, pidls.GetCount());
- ::OleSetClipboard(NULL);
- Refresh();
- }
- pDropSource->Release();
- }
- else {
- // In case of regular copy/cut/paste operatons, we
- // simply need to put the IDataObject on the clipboard.
- // The auto-ptr will release our reference on function
- // exit.
- ::OleSetClipboard(spDataObject);
- }
- }
- _UpdateToolbar();
- return S_OK;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Message Handlers
- LRESULT CView::OnNotifyDispInfo(UINT /*CtlID*/, LPNMHDR lpnmh, BOOL& /*bHandled*/)
- {
- USES_CONVERSION;
- LV_DISPINFO *lpdi = (LV_DISPINFO *)lpnmh;
- LPITEMIDLIST pidl = (LPITEMIDLIST)lpdi->item.lParam;
- ATLASSERT(pidl);
- lpdi->item.mask |= LVIF_DI_SETITEM; // dont ask us again
- if( lpdi->item.iSubItem>0 ) {
- // Sub-item information being requested.
- // Is the text being requested?
- if(lpdi->item.mask & LVIF_TEXT) {
-
- TCHAR szTemp[MAX_PATH];
- LPCPIDLDATA pData = pidl_cast(pidl);
- switch( lpdi->item.iSubItem ) {
- case COL_SIZE:
- if( pData->type==PT_FILE ) {
- WCHAR szwTemp[32];
- if( pData->dwEntryFlags & EF_DELETED ) {
- szwTemp[0] = L' ';
- }
- else {
- LONGLONG longlong = pData->dwSize;
- ::StrFormatByteSizeW(longlong, szwTemp, lengthof(szwTemp));
- }
- _tcsncpy(lpdi->item.pszText, W2CT(szwTemp), lpdi->item.cchTextMax);
- }
- break;
- case COL_TYPE:
- _tcsncpy(lpdi->item.pszText, pData->szType, lpdi->item.cchTextMax);
- break;
- case COL_TIME:
- {
- TCHAR szDate[32];
- TCHAR szTime[32];
- ::GetDateFormat( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &pData->ftTime, NULL, szDate, lengthof(szDate) );
- ::GetTimeFormat( LOCALE_USER_DEFAULT, 0, &pData->ftTime, NULL, szTime, lengthof(szTime) );
- ::wsprintf(szTemp, _T("%s %s"), szDate, szTime);
- _tcsncpy(lpdi->item.pszText, szTemp, lpdi->item.cchTextMax);
- };
- break;
- case COL_ATTRIBS:
- {
- // Construct attribute string
- CAdfFile::ConvertAccess(pData->dwAccess, szTemp);
- _tcsncpy(lpdi->item.pszText, szTemp, lpdi->item.cchTextMax);
- };
- break;
- }
- }
- }
- else {
- // The main item information is being requested
- if( lpdi->item.mask & LVIF_TEXT ) {
- STRRET str;
- if(SUCCEEDED(m_pFolder->GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &str))) {
- switch( str.uType ) {
- case STRRET_WSTR:
- _tcsncpy(lpdi->item.pszText, OLE2CT(str.pOleStr), lpdi->item.cchTextMax);
- _Module.m_Allocator.Free(str.pOleStr); // Delete the string
- break;
- case STRRET_CSTR:
- _tcsncpy(lpdi->item.pszText, A2CT(str.cStr), lpdi->item.cchTextMax);
- break;
- default:
- ATLASSERT(false);
- }
- }
- }
- if( lpdi->item.mask & LVIF_IMAGE ) {
- IExtractIcon *pEI;
- if( SUCCEEDED(m_pFolder->GetUIObjectOf(m_hWnd,
- 1,
- (LPCITEMIDLIST *)&pidl,
- IID_IExtractIcon,
- NULL,
- (LPVOID*)&pEI)) )
- {
- // GetIconLoaction will give us the index into our image list
- UINT uFlags;
- pEI->GetIconLocation(GIL_FORSHELL, NULL, 0, &lpdi->item.iImage, &uFlags);
- ATLASSERT(uFlags & GIL_NOTFILENAME);
- pEI->Release();
- }
- }
- }
- return 0;
- }
- LRESULT CView::OnHeaderClick(UINT /*CtlID*/, LPNMHDR lpnmh, BOOL& /*bHandled*/)
- {
- ATLTRACE(_T("CView::OnHeaderClickn"));
- NMHEADER *pnmh = (NMHEADER *)lpnmh;
- // Handle left-click only
- if( pnmh->iButton==0 ) {
- // Sort the list by the column that was clicked
- ListView_SortItems(m_hwndList, _ListViewSortFunc, pnmh->iItem);
- }
- return 0;
- }
- LRESULT CView::OnDeleteItem(UINT /*CtlID*/, LPNMHDR lpnmh, BOOL& /*bHandled*/)
- {
- // Delete the pidl because we made a copy of it
- NM_LISTVIEW *lpnmlv = (NM_LISTVIEW *)lpnmh;
- CPidl::_Delete((LPITEMIDLIST)lpnmlv->lParam);
- return 0;
- }
- // Bring up Context Menu.
- LRESULT CView::OnContextMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
- {
- ATLTRACE(_T("CView::OnContextMenun"));
- CPidl pidl;
- UINT nCount = ListView_GetSelectedCount(m_hwndList);
- if( nCount==0 ) {
- // Nothing selected? Use the View menu then (see code below).
- }
- else {
- // We don't support merging of menus when more than one item
- // is selected, so the menu for the first item is shown.
- CPidlList pidls(m_hwndList);
- pidl.Copy(pidls[0]);
- }
- UINT resMenu = 0;
- if( pidl.IsEmpty() ) {
- resMenu = IDM_POPUP_VIEW;
- }
- else {
- LPCPIDLDATA pData = pidl_cast((LPCITEMIDLIST)pidl);
- if( pData->dwEntryFlags & EF_DELETED ) {
- resMenu = IDM_POPUP_DELETED;
- }
- else {
- switch( pData->type ) {
- case PT_FOLDER:
- resMenu = IDM_POPUP_FOLDER;
- break;
- case PT_FILE:
- resMenu = IDM_POPUP_FILE;
- break;
- default:
- ATLASSERT(""=="Invalid menu type");
- }
- }
- }
- // Prepare menu
- POINT pt = { LOWORD(lParam), HIWORD(lParam) };
- if( lParam==-1 ) {
- // Windows sends -1 as lParam when using SHIFT+F10 to activate context menu
- RECT rc;
- ListView_GetItemRect(m_hwndList, ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED), &rc, LVIR_ICON);
- pt.x = rc.left + ((rc.right-rc.left)/2);
- pt.y = rc.top + ((rc.bottom-rc.top)/2);
- ::ClientToScreen(m_hwndList, &pt);
- }
- HMENU hMenu = ::LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(resMenu));
- ATLASSERT(::IsMenu(hMenu));
- HMENU hSubMenu = ::GetSubMenu(hMenu,0);
- // Let generic menu-updater handle popup too...
- _UpdateMenu(hSubMenu);
- // Show popup menu
- ::SetMenuDefaultItem(hSubMenu, ID_FILE_OPEN, FALSE);
- ::SetForegroundWindow(m_hWnd);
- ::TrackPopupMenu(hSubMenu,
- TPM_LEFTALIGN|TPM_LEFTBUTTON,
- pt.x, pt.y,
- 0,
- m_hWnd,
- NULL);
- ::DestroyMenu(hMenu);
- // Reset statusbar
- OnItemChanged(0,NULL,bHandled);
- return 0;
- }
- LRESULT CView::OnItemActivated(UINT /*CtlID*/, LPNMHDR /*lpnmh*/, BOOL& bHandled)
- {
- ATLTRACE(_T("CView::OnItemActivatedn"));
- return OnFileOpen(0,0,0,bHandled);
- }
- LRESULT CView::OnLabelEditBegin(UINT /*CtlID*/, LPNMHDR lpnmh, BOOL& /*bHandled*/)
- {
- ATLTRACE(_T("CView::OnLabelEditBeginn"));
- NMLVDISPINFO *lpdi = (NMLVDISPINFO*)lpnmh;
- DWORD dwAttr = SFGAO_CANRENAME;
- m_pFolder->GetAttributesOf(1, (LPCITEMIDLIST*)&lpdi->item.lParam, &dwAttr);
- if( (dwAttr & SFGAO_CANRENAME)==0 ) return TRUE;
- m_bInEdit = true;
- return FALSE; // Allow edit!
- }
- LRESULT CView::OnLabelEditEnd(UINT /*CtlID*/, LPNMHDR lpnmh, BOOL& /*bHandled*/)
- {
- ATLTRACE(_T("CView::OnLabelEditEndn"));
- NMLVDISPINFO *lpdi = (NMLVDISPINFO*)lpnmh;
- m_bInEdit = false;
- if( lpdi->item.pszText==NULL ) return FALSE; // User cancelled editing
- LVITEM lvItem = { 0 };
- lvItem.mask = LVIF_PARAM;
- lvItem.iItem = lpdi->item.iItem;
- ListView_GetItem(m_hwndList, &lvItem);
- LPITEMIDLIST pidlOldItem = (LPITEMIDLIST)lvItem.lParam;
- // The IShellFolder handles the actual rename...
- USES_CONVERSION;
- LPCWSTR pwstr = T2CW(lpdi->item.pszText);
- LPITEMIDLIST pidlNewItem = NULL;
- HRESULT Hr = m_pFolder->SetNameOf(NULL, pidlOldItem, pwstr, 0, &pidlNewItem);
- if( FAILED(Hr) || (pidlNewItem==NULL) ) {
- ::MessageBeep(MB_ICONEXCLAMATION);
- return FALSE;
- }
- // Set the new PIDL structure
- lvItem.mask = LVIF_PARAM;
- lvItem.lParam = (LPARAM)pidlNewItem;
- ListView_SetItem(m_hwndList, &lvItem);
- CPidl::_Delete(pidlOldItem);
- return TRUE; // Accept rename
- }
- LRESULT CView::OnBeginDrag(UINT /*CtlID*/, LPNMHDR /*lpnmh*/, BOOL& /*bHandled*/)
- {
- ATLTRACE(_T("CView::OnBeginDragn"));
- _DoCopyOperation(true, false);
- return TRUE;
- }
- LRESULT CView::OnItemChanged(UINT /*CtlID*/, LPNMHDR /*lpnmh*/, BOOL& /*bHandled*/)
- {
- ATLTRACE(_T("CView::OnItemChangedn"));
- ATLASSERT(m_pShellBrowser);
- // Set the status bar text
- TCHAR szText[64] = { 0 };
- UINT nCount = ListView_GetSelectedCount(m_hwndList);
- if( nCount>0 ) {
- // Show "x object(s) selected" message
- CResString<64> sFormat(IDS_OBJECTSELECTED);
- ::wsprintf(szText, sFormat, nCount);
- }
- USES_CONVERSION;
- m_pShellBrowser->SetStatusTextSB(T2CW(szText));
- _UpdateToolbar();
- return TRUE;
- }
- LRESULT CView::OnMenuSelect(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
- {
- ATLTRACE(_T("CView::OnMenuSelectn"));
- ATLASSERT(m_pShellBrowser);
- WORD wFlags = HIWORD(wParam);
- if( wFlags==0xFFFF && lParam==NULL ) {
- bHandled = FALSE;
- return 1; // Menu closing!
- }
- CResString<80> sText(LOWORD(wParam));
- if( _tcslen(sText)==0 ) {
- bHandled = FALSE;
- return 1; // No text. Not processed!
- }
- LRESULT lResult;
- m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, (255 | SBT_NOBORDERS), (LPARAM)(LPCTSTR)sText, &lResult);
- return 0;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Message Command Handlers
- LRESULT CView::OnNewFolder(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- // Create a new folder right away
- CResString<MAXNAMELEN> sName(IDS_NEWFOLDER);
- DWORD dwFileOpFlags = CFolder::FILEOP_UNIQUENAME;
- if( FAILED( m_pFolder->_CreateFolder(sName, &dwFileOpFlags) ) ) return 0;
- Refresh();
- // Get new PIDL structure
- LVFINDINFO fi = { 0 };
- fi.flags = LVFI_STRING;
- fi.psz = sName;
- int iItem = ListView_FindItem(m_hwndList, -1, &fi);
- ATLASSERT(iItem!=-1);
- LVITEM lvItem = { 0 };
- lvItem.mask = LVIF_PARAM;
- lvItem.iItem = iItem;
- ListView_GetItem(m_hwndList, &lvItem);
- // Notify Shell so it can create the folder in the Explorer tree
- CPidl pidl;
- pidl.Copy(m_pFolder->m_pidl);
- pidl.Concatenate(m_pFolder->m_pidlPath);
- pidl.Concatenate((LPCITEMIDLIST)lvItem.lParam);
- ::SHChangeNotify(SHCNE_MKDIR, SHCNF_IDLIST | SHCNF_FLUSH, pidl, NULL);
- // Put ListView item in edit mode...
- ::SetFocus(m_hwndList);
- ListView_EditLabel(m_hwndList, iItem);
- return 0;
- }
- LRESULT CView::OnFileOpen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- ATLASSERT(m_pShellBrowser);
- CPidlList pidls(m_hwndList);
- pidls.Filter(m_pFolder, SFGAO_BROWSABLE);
- if( pidls.GetCount()==0 ) return 0;
- CPidl pidl;
- pidl.Copy( m_pFolder->m_pidl );
- pidl.Concatenate( m_pFolder->m_pidlPath );
- pidl.Concatenate( pidls[0] );
- m_pShellBrowser->BrowseObject(pidl, SBSP_DEFBROWSER | SBSP_ABSOLUTE);
- return 0;
- }
- LRESULT CView::OnFileRename(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- UINT nCount = ListView_GetSelectedCount(m_hwndList);
- if( nCount!=1 ) return 0;
- // Put the ListView into edit mode
- ::SetFocus(m_hwndList);
- int nItem;
- if( (nItem = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED)) != -1 ) {
- ListView_EditLabel(m_hwndList, nItem);
- }
- return 0;
- }
- LRESULT CView::OnFileUndelete(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- CPidlList pidls(m_hwndList);
- pidls.Filter(m_pFolder, SFGAO_GHOSTED);
- if( pidls.GetCount()==0 ) return 0;
- m_pFolder->_UnDeleteFiles(pidls, pidls.GetCount());
- Refresh();
- return 0;
- }
- LRESULT CView::OnGoUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- ATLASSERT(m_pShellBrowser);
- m_pShellBrowser->BrowseObject(NULL, SBSP_SAMEBROWSER | SBSP_PARENT);
- return 0;
- }
- LRESULT CView::OnViewDeletedFiles(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- m_bShowDeletedFiles = !m_bShowDeletedFiles;
- Refresh();
- return 0;
- }
- LRESULT CView::OnViewChange(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- int dwListStyle = LVS_REPORT;
- int dwViewMode = FVM_DETAILS;
- switch( wID ) {
- case ID_VIEW_REPORT:
- dwListStyle = LVS_REPORT;
- dwViewMode = FVM_DETAILS;
- break;
- case ID_VIEW_LARGEICONS:
- dwListStyle = LVS_ICON;
- dwViewMode = FVM_ICON;
- break;
- case ID_VIEW_SMALLICONS:
- dwListStyle = LVS_SMALLICON;
- dwViewMode = FVM_SMALLICON;
- break;
- case ID_VIEW_LIST:
- dwListStyle = LVS_LIST;
- dwViewMode = FVM_LIST;
- break;
- }
- // Change the FolderSettings and change ListView control
- m_FolderSettings.ViewMode = dwViewMode;
- DWORD dwStyle = ::GetWindowLong(m_hwndList, GWL_STYLE);
- dwStyle &= ~LVS_TYPEMASK;
- dwStyle |= dwListStyle;
- ::SetWindowLong(m_hwndList, GWL_STYLE, dwStyle);
- // Need to update toolbar as well
- _UpdateToolbar();
- return 0;
- }
- LRESULT CView::OnShowHelp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- TCHAR szFileName[MAX_PATH];
- ::GetModuleFileName(_Module.GetModuleInstance(), szFileName, lengthof(szFileName));
- ::PathRemoveExtension(szFileName);
- ::PathAddExtension(szFileName, _T(".hlp"));
- ::WinHelp(m_hWnd, szFileName, HELP_CONTENTS, 0);
- return 0;
- }
- LRESULT CView::OnRefresh(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- Refresh();
- return 0;
- }
- LRESULT CView::OnFileProperties(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- UINT nCount = ListView_GetSelectedCount(m_hwndList);
- if( nCount==0 ) {
- // Show the View's Properties
- if( m_pFolder->m_pidlPath.IsEmpty() ) {
- // Show properties for root!
- // We basically bring up the standard Property Pages for the ADF file.
- SHELLEXECUTEINFO sei = { 0 };
- sei.cbSize = sizeof(sei);
- sei.hwnd = m_hWnd;
- sei.fMask = SEE_MASK_IDLIST | SEE_MASK_INVOKEIDLIST;
- sei.lpIDList = m_pFolder->m_pidl;
- sei.lpVerb = _T("properties");
- sei.nShow = SW_SHOWNORMAL;
- ::ShellExecuteEx(&sei);
- }
- else {
- // Show properties for active folder
- CPropertiesDlg dlg;
- if( SUCCEEDED(dlg._Init(m_pFolder, NULL)) ) {
- if( dlg.DoModal()==IDOK ) {
- Refresh();
- }
- }
- }
- }
- else {
- CPidlList pidls(m_hwndList);
- pidls.Filter(m_pFolder, SFGAO_HASPROPSHEET);
- if( pidls.GetCount()==0 ) return 0;
- // Show the Folder/File Properties
- switch( PidlGetType(pidls[0]) ) {
- case PT_FOLDER:
- case PT_FILE:
- {
- CPropertiesDlg dlg;
- if( SUCCEEDED( dlg._Init(m_pFolder, pidls[0])) ) {;
- if( dlg.DoModal()==IDOK ) {
- Refresh();
- }
- }
- }
- break;
- default:
- ATLASSERT(""=="Invalid property page request");
- }
- }
- return 0;
- }
- LRESULT CView::OnFileDelete(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- ATLASSERT(m_pFolder);
- CPidlList pidls(m_hwndList);
- pidls.Filter(m_pFolder, SFGAO_CANDELETE);
- if( pidls.GetCount()==0 ) return 0;
- // Complex task of putting up a confirmation dialog...
- if( m_ShellFlags.fNoConfirmRecycle==0 ) {
- DWORD dwFlags = 0;
- if( m_pFolder->_ConfirmDelete(pidls, pidls.GetCount(), &dwFlags)==IDNO ) return 0;
- }
- m_pFolder->_DeleteFiles(pidls, pidls.GetCount());
- Refresh();
- ::SetFocus(m_hwndList);
- return 0;
- }
- LRESULT CView::OnCopy(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- _DoCopyOperation(false,false);
- return 0;
- }
- LRESULT CView::OnCut(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- _DoCopyOperation(false,true);
- return 0;
- }
- LRESULT CView::OnPaste(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- CComPtr<IDataObject> spDataObject;
- if( SUCCEEDED( ::OleGetClipboard(&spDataObject) ) ) {
-
- // We attempt to do an "non-optimized move".
- // The formal communication when doing the paste, is to let the
- // IDataObject know about the success of the paste operation.
- // MSDN explains the procedures...
- FORMATETC fe = { _Module.m_CFSTR_PREFERREDDROPEFFECT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
- STGMEDIUM med;
- HRESULT HrHadData = spDataObject->GetData(&fe, &med);
- if( SUCCEEDED(HrHadData) ) {
- fe.cfFormat = _Module.m_CFSTR_PERFORMEDDROPEFFECT;
- spDataObject->SetData(&fe,&med,FALSE);
- }
- // Handle drop
- HRESULT Hr;
- Hr = m_pFolder->_DoDrop(spDataObject, DROPEFFECT_COPY);
- // Tell the IDataObject if we succeeded
- if( Hr==S_OK ) {
- // We ask the IDataObject to delete the items (if we're moving files)
- if( SUCCEEDED(HrHadData) ) {
- fe.cfFormat = _Module.m_CFSTR_PASTESUCCEEDED;
- spDataObject->SetData(&fe,&med,FALSE);
- }
- }
- else if( Hr==S_FALSE ) {
- // Do something! Anything!
- }
- else {
- ::MessageBeep(MB_ICONEXCLAMATION);
- }
- if( SUCCEEDED(HrHadData) ) ::ReleaseStgMedium(&med);
- Refresh();
- }
- return 0;
- }
- LRESULT CView::OnSelectAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- ::SetFocus(m_hwndList);
- ListView_SetItemState(m_hwndList, -1, LVIS_SELECTED, LVIS_SELECTED);
- return 0;
- }
- LRESULT CView::OnInvertSelection(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
- {
- ::SetFocus(m_hwndList);
- int nItem = -1;
- while( (nItem = ListView_GetNextItem(m_hwndList, nItem, LVNI_ALL)) != -1 ) {
- UINT state = ListView_GetItemState(m_hwndList, nItem, LVIS_SELECTED);
- ListView_SetItemState(m_hwndList, nItem, (state ^ LVIS_SELECTED), LVIS_SELECTED);
- }
- return 0;
- }