/*++ Implements IShellView. --*/ #include #include #include #include #include #include #include "pstore.h" #include "shfolder.h" #include "shview.h" #include "guid.h" #include "resource.h" #include "tools.h" #include "utility.h" #include "enumid.h" #include "listu.h" extern HINSTANCE g_hInst; extern LONG g_DllRefCount; BOOL AddListItem( HWND hWnd, DWORD dwType, PST_KEY KeyType, LPCWSTR szName, LPITEMIDLIST pidl ); #define TOOLBAR_ID (L"TBar") #define INITIAL_COLUMN_POS 100 MYTOOLINFO g_Buttons[] = { IDM_MESSAGE1, 0, IDS_TB_MESSAGE1, IDS_MI_MESSAGE1, TBSTATE_ENABLED, TBSTYLE_BUTTON, IDM_MESSAGE2, 0, IDS_TB_MESSAGE2, IDS_MI_MESSAGE2, TBSTATE_ENABLED, TBSTYLE_BUTTON, -1, 0, 0, 0, 0, }; CShellView::CShellView( CShellFolder *pFolder, LPCITEMIDLIST pidl ) { m_hMenu = NULL; ZeroMemory(&m_MenuWidths, sizeof(m_MenuWidths)); m_nColumn1 = INITIAL_COLUMN_POS; m_nColumn2 = INITIAL_COLUMN_POS; m_pSFParent = pFolder; if(m_pSFParent) m_pSFParent->AddRef(); m_pidl = (LPITEMIDLIST)pidl; m_uState = SVUIA_DEACTIVATE; m_ObjRefCount = 1; InterlockedIncrement(&g_DllRefCount); } CShellView::~CShellView() { if(m_pSFParent) m_pSFParent->Release(); InterlockedDecrement(&g_DllRefCount); } STDMETHODIMP CShellView::QueryInterface( REFIID riid, LPVOID *ppReturn ) /*++ IUnknown::QueryInterface --*/ { *ppReturn = NULL; if(IsEqualIID(riid, IID_IUnknown)) *ppReturn = (IUnknown*)(IShellView*)this; else if(IsEqualIID(riid, IID_IOleWindow)) *ppReturn = (IOleWindow*)this; else if(IsEqualIID(riid, IID_IShellView)) *ppReturn = (CShellView*)this; else if(IsEqualIID(riid, IID_IOleCommandTarget)) *ppReturn = (IOleCommandTarget*)this; if(*ppReturn == NULL) return E_NOINTERFACE; (*(LPUNKNOWN*)ppReturn)->AddRef(); return S_OK; } STDMETHODIMP_(DWORD) CShellView::AddRef() /*++ IUnknown::AddRef --*/ { return InterlockedIncrement(&m_ObjRefCount); } STDMETHODIMP_(DWORD) CShellView::Release() /*++ IUnknown::Release --*/ { LONG lDecremented = InterlockedDecrement(&m_ObjRefCount); if(lDecremented == 0) delete this; return lDecremented; } STDMETHODIMP CShellView::GetWindow( HWND *phWnd ) /*++ IOleWindow::GetWindow --*/ { *phWnd = m_hWnd; return S_OK; } STDMETHODIMP CShellView::ContextSensitiveHelp( BOOL fEnterMode ) /*++ Inherited from IOleWindow::ContextSensitiveHelp. --*/ { return E_NOTIMPL; } STDMETHODIMP CShellView::QueryStatus( const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText ) /*++ IOleCommandTarget::QueryStatus --*/ { ULONG i; // // only process the commands for our command group // if(pguidCmdGroup && (*pguidCmdGroup != CLSID_CmdGrp)) return OLECMDERR_E_UNKNOWNGROUP; // // make sure prgCmds is not NULL // if(prgCmds == NULL) return E_POINTER; // // run through all of the commands and supply the correct information // for(i = 0; i < cCmds;i++) { switch(prgCmds[i].cmdID) { case IDM_MESSAGE1: prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED; break; case IDM_MESSAGE2: prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED; break; } } return S_OK; } STDMETHODIMP CShellView::Exec( const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut ) /*++ IOleCommandTarget::Exec --*/ { // // only process the commands for our command group // if(pguidCmdGroup && (*pguidCmdGroup == CLSID_CmdGrp)) { OnCommand(nCmdID, 0, NULL); return S_OK; } return OLECMDERR_E_UNKNOWNGROUP; } STDMETHODIMP CShellView::TranslateAccelerator( LPMSG pMsg ) /*++ Same as the IOleInPlaceFrame::TranslateAccelerator, but will be never called because we don't support EXEs (i.e., the explorer has the message loop). This member function is defined here for possible future enhancement. --*/ { return E_NOTIMPL; } STDMETHODIMP CShellView::EnableModeless( BOOL fEnable ) /*++ Same as the IOleInPlaceFrame::EnableModeless. --*/ { return E_NOTIMPL; } STDMETHODIMP CShellView::UIActivate( UINT uState ) /*++ IShellView::UIActivate --*/ { // // don't do anything if the state isn't really changing // if(m_uState == uState) return S_OK; // // Always do this because we will cause problems if we are going from // SVUIA_ACTIVATE_FOCUS to SVUIA_ACTIVATE_NOFOCUS or vice versa. // m_uState = SVUIA_DEACTIVATE; m_pShellBrowser->SetMenuSB(NULL, NULL, NULL); if(m_hMenu) { DestroyMenu(m_hMenu); m_hMenu = NULL; } // // only do this if we are active // if(uState != SVUIA_DEACTIVATE) { m_uState = uState; // // update the Explorer's menu // if(m_hMenu == NULL) m_hMenu = CreateMenu(); if(m_hMenu) { MENUITEMINFO mii; TCHAR szText[MAX_PATH]; m_pShellBrowser->InsertMenusSB(m_hMenu, &m_MenuWidths); // // get the menu item's text // LoadString(g_hInst, IDS_MI_REGISTRY, szText, sizeof(szText)); // // build our menu // ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE; mii.fType = MFT_STRING; mii.fState = MFS_ENABLED; mii.dwTypeData = szText; mii.hSubMenu = BuildMenu(); // // insert our menu // InsertMenuItem(m_hMenu, FCIDM_MENU_HELP, FALSE, &mii); m_pShellBrowser->SetMenuSB(m_hMenu, NULL, m_hWnd); } // // TODO: update the status bar // /* TCHAR szName[MAX_PATH]; LoadString(g_hInst, IDS_PSTORE_TITLE, szName, sizeof(szName)); m_pSFParent->GetPidlFullText(m_pidl, szName + lstrlen(szName), sizeof(szName) - lstrlen(szName)); LRESULT lResult; int nPartArray[1] = {-1}; //set the number of parts m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, 1, (LPARAM)nPartArray, &lResult); //set the text for the parts m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 0, (LPARAM)szName, &lResult); */ } return S_OK; } HMENU CShellView::BuildMenu( void ) { HMENU hSubMenu = CreatePopupMenu(); if(hSubMenu == NULL) return NULL; TCHAR szText[MAX_PATH]; MENUITEMINFO mii; int nButtons, i; // // get the number of items in our global array // for(nButtons = 0; g_Buttons[nButtons].idCommand != -1; nButtons++) { ; } // // add the menu items // for(i = 0; i < nButtons; i++) { LoadString(g_hInst, g_Buttons[i].idMenuString, szText, sizeof(szText)); ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE; if(TBSTYLE_SEP != g_Buttons[i].bStyle) { mii.fType = MFT_STRING; mii.fState = MFS_ENABLED; mii.dwTypeData = szText; mii.wID = g_Buttons[i].idCommand; } else { mii.fType = MFT_SEPARATOR; } // // tack this item onto the end of the menu // InsertMenuItem(hSubMenu, (UINT)-1, TRUE, &mii); } // // add a couple more that aren't in the button array // LoadString(g_hInst, IDS_MI_VIEW_ISTB, szText, sizeof(szText)); ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE; mii.fType = MFT_STRING; mii.fState = MFS_ENABLED; mii.dwTypeData = szText; mii.wID = IDM_VIEW_ISTB; // // tack this item onto the end of the menu // InsertMenuItem(hSubMenu, (UINT)-1, TRUE, &mii); LoadString(g_hInst, IDS_MI_VIEW_IETB, szText, sizeof(szText)); ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE; mii.fType = MFT_STRING; mii.fState = MFS_ENABLED; mii.dwTypeData = szText; mii.wID = IDM_VIEW_IETB; // // tack this item onto the end of the menu // InsertMenuItem(hSubMenu, (UINT)-1, TRUE, &mii); return hSubMenu; } STDMETHODIMP CShellView::Refresh( void ) /*++ IShellView::Refresh --*/ { // // empty the list // ListView_DeleteAllItems(m_hwndList); // // refill the list // FillList(); return S_OK; } STDMETHODIMP CShellView::CreateViewWindow( LPSHELLVIEW pPrevView, LPCFOLDERSETTINGS lpfs, LPSHELLBROWSER psb, LPRECT prcView, HWND *phWnd ) /*++ CreateViewWindow creates a view window. This can be either the right pane of the Explorer or the client window of a folder window. --*/ { WNDCLASS wc; *phWnd = NULL; // // if our window class has not been registered, then do so // if(!GetClassInfo(g_hInst, NS_CLASS_NAME, &wc)) { ZeroMemory(&wc, sizeof(wc)); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = g_hInst; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszMenuName = NULL; wc.lpszClassName = NS_CLASS_NAME; if(!RegisterClass(&wc)) return E_FAIL; } // // set up the member variables // m_pShellBrowser = psb; m_FolderSettings.ViewMode = lpfs->ViewMode; m_FolderSettings.fFlags = lpfs->fFlags; // // get our parent window // m_pShellBrowser->GetWindow(&m_hwndParent); GetSettings(); *phWnd = CreateWindowEx( 0, NS_CLASS_NAME, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, prcView->left, prcView->top, prcView->right - prcView->left, prcView->bottom - prcView->top, m_hwndParent, NULL, g_hInst, (LPVOID)this); if(*phWnd == NULL) return E_FAIL; // // addref the IShellBrowser interface to allow communication with Explorer // m_pShellBrowser->AddRef(); return S_OK; } STDMETHODIMP CShellView::DestroyViewWindow( void ) /*++ The Explorer calls this method when a folder window or the Explorer is being closed. --*/ { if(m_hMenu) DestroyMenu(m_hMenu); DestroyWindow(m_hWnd); // // release the shell browser object // m_pShellBrowser->Release(); return S_OK; } STDMETHODIMP CShellView::GetCurrentInfo( LPFOLDERSETTINGS lpfs ) /*++ The Explorer uses GetCurrentInfo to query the view for standard settings. --*/ { // TODO, check proper approach. *lpfs = m_FolderSettings; // lpfs->ViewMode = m_FolderSettings.ViewMode; // lpfs->fFlags = m_FolderSettings.fFlags; return NOERROR; } STDMETHODIMP CShellView::AddPropertySheetPages( DWORD dwReserved, LPFNADDPROPSHEETPAGE lpfn, LPARAM lParam ) /*++ The Explorer calls this method when it is opening the View.Options... property sheet. Views can add pages by creating them and calling the callback function with the page handles. --*/ { OutputDebugStringA("IShellView::AddPropertySheetPages\n"); return E_NOTIMPL; } STDMETHODIMP CShellView::SaveViewState( void ) /*++ IShellView::SaveViewState --*/ { SaveSettings(); return S_OK; } STDMETHODIMP CShellView::SelectItem( LPCITEMIDLIST pidlItem, UINT uFlags ) /*++ IShellView::SelectItem --*/ { return E_NOTIMPL; } STDMETHODIMP CShellView::GetItemObject( UINT uItem, REFIID riid, LPVOID *ppvOut ) /*++ Used by the common dialogs to get the selected items from the view. --*/ { return E_NOTIMPL; } LRESULT CALLBACK CShellView::WndProc( HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam ) { CShellView *pThis = (CShellView*)GetWindowLongPtr(hWnd, GWLP_USERDATA); switch (uMessage) { case WM_NCCREATE: { LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam; pThis = (CShellView*)(lpcs->lpCreateParams); SetWindowLongPtr(hWnd, GWLP_USERDATA, (LPARAM)pThis); //set the window handle pThis->m_hWnd = hWnd; break; } case WM_SIZE: return pThis->OnSize(LOWORD(lParam), HIWORD(lParam)); case WM_CREATE: return pThis->OnCreate(); case WM_SETFOCUS: return pThis->OnSetFocus(); case WM_ACTIVATE: return pThis->OnActivate(wParam, lParam); case WM_COMMAND: return pThis->OnCommand( GET_WM_COMMAND_ID(wParam, lParam), GET_WM_COMMAND_CMD(wParam, lParam), GET_WM_COMMAND_HWND(wParam, lParam)); case WM_INITMENUPOPUP: return pThis->UpdateMenu((HMENU)wParam); case WM_NOTIFY: return pThis->OnNotify((UINT)wParam, (LPNMHDR)lParam); } return DefWindowProc(hWnd, uMessage, wParam, lParam); } LRESULT CShellView::OnSetFocus( void ) { // // tell the browser we got the focus // m_pShellBrowser->OnViewWindowActive(this); return 0; } LRESULT CShellView::OnActivate( WPARAM wParam, LPARAM lParam ) { // // tell the browser we got the focus // if(wParam) m_pShellBrowser->OnViewWindowActive(this); return 0; } LRESULT CShellView::OnCommand( DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd ) { switch(dwCmdID) { case IDM_MESSAGE1: MessageBox(m_hWnd, TEXT("Message 1 was selected"), TEXT("Notice"), MB_OK | MB_ICONEXCLAMATION); break; case IDM_MESSAGE2: MessageBox(m_hWnd, TEXT("Message 2 was selected"), TEXT("Notice"), MB_OK | MB_ICONEXCLAMATION); break; case IDM_VIEW_ISTB: m_bShowISTB = ! m_bShowISTB; UpdateToolbar(); break; case IDM_VIEW_IETB: m_bShowIETB = ! m_bShowIETB; UpdateToolbar(); break; } return 0; } HRESULT CShellView::SaveSettings( void ) /*++ Called by IShellView::SaveViewState to store the relevant setting data to the browser stream. --*/ { HRESULT hr; LPSTREAM pStream; hr = m_pShellBrowser->GetViewStateStream(STGM_WRITE, &pStream); if(SUCCEEDED(hr)) { ULONG uWritten; pStream->Write(&m_bShowISTB, sizeof(m_bShowISTB), &uWritten); pStream->Write(&m_bShowIETB, sizeof(m_bShowIETB), &uWritten); pStream->Write(&m_nColumn1, sizeof(m_nColumn1), &uWritten); pStream->Write(&m_nColumn2, sizeof(m_nColumn2), &uWritten); pStream->Release(); } return hr; } HRESULT CShellView::GetSettings( void ) { HRESULT hr; LPSTREAM pStream; hr = m_pShellBrowser->GetViewStateStream(STGM_READ, &pStream); if(SUCCEEDED(hr)) { ULONG uRead; if(S_OK != pStream->Read(&m_bShowISTB, sizeof(m_bShowISTB), &uRead)) m_bShowISTB = FALSE; if(S_OK != pStream->Read(&m_bShowIETB, sizeof(m_bShowIETB), &uRead)) m_bShowIETB = FALSE; if(S_OK != pStream->Read(&m_nColumn1, sizeof(m_nColumn1), &uRead)) m_nColumn1 = INITIAL_COLUMN_POS; if(S_OK != pStream->Read(&m_nColumn2, sizeof(m_nColumn2), &uRead)) m_nColumn2 = INITIAL_COLUMN_POS; pStream->Release(); } return hr; } LRESULT CShellView::UpdateMenu( HMENU hMenu ) { return 0; } void CShellView::UpdateToolbar() { // nothing to update yet } LRESULT CShellView::OnNotify( UINT CtlID, LPNMHDR pNotify ) { LPNM_LISTVIEW pNotifyLV = (LPNM_LISTVIEW)pNotify; LV_DISPINFO *pNotifyDI = (LV_DISPINFO *)pNotify; LPTBNOTIFY pNotifyTB = (LPTBNOTIFY)pNotify; LPTOOLTIPTEXT pNotifyTT = (LPTOOLTIPTEXT)pNotify; switch(pNotify->code) { // // HDN_BEGINTRACK // HDN_DIVIDERDBLCLICK // HDN_ENDTRACK // HDN_ITEMCHANGED // HDN_ITEMCHANGING // HDN_ITEMCLICK // HDN_ITEMDBLCLICK // HDN_TRACK // case HDN_ENDTRACK: { m_nColumn1 = ListView_GetColumnWidth(m_hwndList, 0); m_nColumn2 = ListView_GetColumnWidth(m_hwndList, 1); break; } // // LVN_BEGINDRAG // LVN_BEGINLABELEDIT // LVN_BEGINRDRAG // LVN_COLUMNCLICK // LVN_DELETEALLITEMS // LVN_DELETEITEM // LVN_ENDLABELEDIT // LVN_GETDISPINFO // LVN_INSERTITEM // LVN_ITEMCHANGED // LVN_ITEMCHANGING // LVN_KEYDOWN // LVN_SETDISPINFO // case LVN_DELETEITEM: { LPITEMIDLIST pidl = (LPITEMIDLIST)(pNotifyLV->lParam); // // free the memory for the pidl associated with this item. // if(pidl != NULL) FreePidl(pidl); break; } // NM_CLICK // NM_DBLCLK // NM_KILLFOCUS // NM_LISTVIEW // NM_OUTOFMEMORY // NM_RCLICK // NM_RDBLCLK // NM_RETURN // NM_SETFOCUS // NM_TREEVIEW // NM_UPDOWN // case NM_RETURN: case NM_DBLCLK: { UINT wFlags = SBSP_RELATIVE | SBSP_DEFMODE; int iItem = -1; // // if we are in explorer mode, start out in DEFBROWSER mode, // otherwise, start in NEWBROWSER mode. // HWND hwnd = NULL; m_pShellBrowser->GetControlWindow(FCW_TREE, &hwnd); if(hwnd != NULL) { wFlags |= SBSP_DEFBROWSER; } else { wFlags |= SBSP_NEWBROWSER; } // // loop through all the selected items. // TODO: if more than two are selected, we only get to view // two. // do { LV_ITEM item; iItem = ListView_GetNextItem(m_hwndList, iItem, LVNI_SELECTED | LVNI_ALL); ZeroMemory(&item, sizeof(item)); item.mask = LVIF_PARAM; item.iItem = iItem; if(!ListView_GetItem(m_hwndList, &item)) break; LPCITEMIDLIST pidl = (LPCITEMIDLIST)(item.lParam); if(pidl != NULL) { // // don't browse into items. // if(GetLastPidlType(pidl) > PIDL_TYPE_SUBTYPE) break; m_pShellBrowser->BrowseObject(pidl, wFlags); } // // if multiple items selected, bring up a new browser // wFlags &= ~SBSP_DEFBROWSER; wFlags |= SBSP_NEWBROWSER; } while (iItem != -1); } // // TBN_BEGINADJUST // TBN_BEGINDRAG // TBN_CUSTHELP // TBN_ENDADJUST // TBN_ENDDRAG // TBN_GETBUTTONINFO // TBN_QUERYDELETE // TBN_QUERYINSERT // TBN_RESET // TBN_TOOLBARCHANGE // case TBN_BEGINDRAG: default: return 0; } return 0; } LRESULT CShellView::OnSize( WORD wWidth, WORD wHeight ) { // // resize the ListView to fit our window // if(m_hwndList) MoveWindow(m_hwndList, 0, 0, wWidth, wHeight, TRUE); return 0; } LRESULT CShellView::OnCreate( void ) { // // create the ListView // if(CreateList()) { if(InitList()) { FillList(); } } return 0; } BOOL CShellView::CreateList( void ) { DWORD dwStyle; // // fetch the prior listview style and use // that as the new listview style. // switch (m_FolderSettings.ViewMode) { case FVM_ICON: dwStyle = LVS_ICON; break; case FVM_SMALLICON: dwStyle = LVS_SMALLICON; break; case FVM_LIST: dwStyle = LVS_LIST; break; case FVM_DETAILS: dwStyle = LVS_REPORT; break; default: dwStyle = LVS_ICON; break; } m_hwndList = CreateWindowEx( WS_EX_CLIENTEDGE, WC_LISTVIEW, NULL, WS_TABSTOP | WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_SORTASCENDING | dwStyle | LVS_NOSORTHEADER | 0, 0, 0, 0, 0, m_hWnd, (HMENU)ID_LISTVIEW, g_hInst, NULL ); return (BOOL)(NULL != m_hwndList); } BOOL CShellView::InitList( void ) { LV_COLUMN lvColumn; HIMAGELIST himlSmall; HIMAGELIST himlLarge; RECT rc; TCHAR szString[MAX_PATH]; // // empty the list // ListView_DeleteAllItems(m_hwndList); // // initialize the columns // lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvColumn.fmt = LVCFMT_LEFT; lvColumn.pszText = szString; lvColumn.cx = m_nColumn1; LoadString(g_hInst, IDS_COLUMN1, szString, sizeof(szString)); ListView_InsertColumn(m_hwndList, 0, &lvColumn); GetClientRect(m_hWnd, &rc); lvColumn.cx = m_nColumn2; LoadString(g_hInst, IDS_COLUMN2, szString, sizeof(szString)); ListView_InsertColumn(m_hwndList, 1, &lvColumn); int cxSmall; int cySmall; int cxLarge; int cyLarge; SHFILEINFO sfi; HIMAGELIST himl; // // get large and small icon size info from shell // himl = (HIMAGELIST)SHGetFileInfo( NULL, 0, &sfi, sizeof(sfi), SHGFI_LARGEICON | SHGFI_SYSICONINDEX ); if(!ImageList_GetIconSize(himl, &cxLarge, &cyLarge)) { cxLarge = GetSystemMetrics(SM_CXICON); cyLarge = GetSystemMetrics(SM_CYICON); } himl = (HIMAGELIST)SHGetFileInfo( NULL, 0, &sfi, sizeof(sfi), SHGFI_SMALLICON | SHGFI_SYSICONINDEX ); if(!ImageList_GetIconSize(himl, &cxSmall, &cySmall)) { cxSmall = GetSystemMetrics(SM_CXSMICON); cySmall = GetSystemMetrics(SM_CYSMICON); } // // Create the full-sized and small icon image lists. // himlLarge = ImageList_Create( cxLarge, cyLarge, ILC_COLORDDB | ILC_MASK, 4, // initial image count 0 ); himlSmall = ImageList_Create( cxSmall, cySmall, ILC_COLORDDB | ILC_MASK, 4, // initial image count 0 ); // // Add icons to each image list. // TODO cache icons // HICON hIconSmall; HICON hIconLarge; // icon 0: Provider icon hIconSmall = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_PROVIDER), IMAGE_ICON, cxSmall, cySmall, LR_DEFAULTCOLOR | LR_SHARED); hIconLarge = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_PROVIDER), IMAGE_ICON, cxLarge, cyLarge, LR_DEFAULTCOLOR | LR_SHARED); ImageList_AddIcon(himlSmall, hIconSmall); ImageList_AddIcon(himlLarge, hIconLarge); // icon 1: type icon hIconSmall = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_FOLDER), IMAGE_ICON, cxSmall, cySmall, LR_DEFAULTCOLOR | LR_SHARED); hIconLarge = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_FOLDER), IMAGE_ICON, cxLarge, cyLarge, LR_DEFAULTCOLOR | LR_SHARED); ImageList_AddIcon(himlSmall, hIconSmall); ImageList_AddIcon(himlLarge, hIconLarge); // icon 2: item icon hIconSmall = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_ITEM), IMAGE_ICON, cxSmall, cySmall, LR_DEFAULTCOLOR | LR_SHARED); hIconLarge = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_ITEM), IMAGE_ICON, cxLarge, cyLarge, LR_DEFAULTCOLOR | LR_SHARED); ImageList_AddIcon(himlSmall, hIconSmall); ImageList_AddIcon(himlLarge, hIconLarge); // icon 3: global type hIconSmall = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_GLOBAL), IMAGE_ICON, cxSmall, cySmall, LR_DEFAULTCOLOR | LR_SHARED); hIconLarge = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_GLOBAL), IMAGE_ICON, cxLarge, cyLarge, LR_DEFAULTCOLOR | LR_SHARED); ImageList_AddIcon(himlSmall, hIconSmall); ImageList_AddIcon(himlLarge, hIconLarge); // // Assign the image lists to the list view control. // ListView_SetImageList(m_hwndList, himlLarge, LVSIL_NORMAL); ListView_SetImageList(m_hwndList, himlSmall, LVSIL_SMALL); return TRUE; } BOOL CShellView::FillList( void ) { LPENUMIDLIST pEnumIDList; ULONG ulFetched; LPITEMIDLIST pidl = NULL; pEnumIDList = new CEnumIDList(m_pidl, TRUE); if(pEnumIDList == NULL) return FALSE; // // enumerate the sub folders or items, based on the parent m_pidl. // note that storage is allocated for the pidlNew, which is a copy // of the current path + pidl - that storage is later freed during // the processing of LVN_DELETEITEM // while( NOERROR == pEnumIDList->Next(1, &pidl, &ulFetched) ) { LPCWSTR szText = GetPidlText(pidl); PST_KEY KeyType = GetPidlKeyType(pidl); DWORD dwPidlType = GetPidlType(pidl); // // make a fully qualified (absolute) pidl // // LPITEMIDLIST pidlNew = CopyCatPidl(m_pidl, pidl); // // free pidl associated with Next enumeration // // FreePidl(pidl); // // add item with absolute pidl to listview // AddListItem(m_hwndList, dwPidlType, KeyType, szText, pidl); } pEnumIDList->Release(); return TRUE; } BOOL AddListItem( HWND hWnd, DWORD dwType, PST_KEY KeyType, LPCWSTR szName, LPITEMIDLIST pidl ) /*++ This function is a temporary hack to support image list add/set data. This will be replaced by an Unicode interface that operates on WinNT and Win95 in the near future. --*/ { LVITEM lvItem; int nIndex; DWORD dwIconIndex; // // determine which icon to use. // when PST_KEY is not PST_KEY_LOCAL_MACHINE, use a different folder // icon at the type and subtype level. // switch(dwType) { case PIDL_TYPE_PROVIDER: dwIconIndex = 0; break; case PIDL_TYPE_TYPE: case PIDL_TYPE_SUBTYPE: if(KeyType == PST_KEY_CURRENT_USER) dwIconIndex = 1; else dwIconIndex = 3; // global (shared) icon break; case PIDL_TYPE_ITEM: dwIconIndex = 2; break; default: dwIconIndex = 0; } ZeroMemory(&lvItem, sizeof(lvItem)); lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; lvItem.iItem = 0; lvItem.lParam = (LPARAM)pidl; lvItem.pszText = (LPTSTR)szName; lvItem.iImage = dwIconIndex; // image index nIndex = ListView_InsertItemU(hWnd, &lvItem); // ListView_SetItemTextU(hWnd, nIndex, 1, (LPWSTR)szValue); return TRUE; }