Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1985 lines
50 KiB

  1. /**************************************************************************
  2. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3. ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  4. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5. PARTICULAR PURPOSE.
  6. Copyright 1998 Microsoft Corporation. All Rights Reserved.
  7. **************************************************************************/
  8. /**************************************************************************
  9. File: ShlView.cpp
  10. Description: Implements IShellView.
  11. **************************************************************************/
  12. /**************************************************************************
  13. #include statements
  14. **************************************************************************/
  15. #include "ShlView.h"
  16. #include "Guid.h"
  17. #include "Commands.h"
  18. #include "resource.h"
  19. #include "Tools.h"
  20. #include "ViewList.h"
  21. #include "DropSrc.h"
  22. /**************************************************************************
  23. global variables
  24. **************************************************************************/
  25. MYTOOLINFO g_Tools[] =
  26. {
  27. IDB_VIEW_SMALL_COLOR, IDM_NEW_FOLDER, VIEW_NEWFOLDER, IDS_NEW_FOLDER, TBSTATE_ENABLED, TBSTYLE_BUTTON,
  28. IDB_STD_SMALL_COLOR, IDM_NEW_ITEM, STD_FILENEW, IDS_NEW_ITEM, TBSTATE_ENABLED, TBSTYLE_BUTTON,
  29. 0, IDM_SEPARATOR, 0, 0, 0, TBSTYLE_SEP,
  30. IDB_VIEW_SMALL_COLOR, IDM_VIEW_LARGE, VIEW_LARGEICONS, IDS_VIEW_LARGE, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP,
  31. IDB_VIEW_SMALL_COLOR, IDM_VIEW_SMALL, VIEW_SMALLICONS, IDS_VIEW_SMALL, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP,
  32. IDB_VIEW_SMALL_COLOR, IDM_VIEW_LIST, VIEW_LIST, IDS_VIEW_LIST, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP,
  33. IDB_VIEW_SMALL_COLOR, IDM_VIEW_DETAILS, VIEW_DETAILS, IDS_VIEW_DETAILS, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP,
  34. 0, -1, 0, 0, 0, 0,
  35. };
  36. extern CViewList *g_pViewList;
  37. /**************************************************************************
  38. CShellView::CShellView()
  39. **************************************************************************/
  40. CShellView::CShellView(CShellFolder *pFolder, LPCITEMIDLIST pidl)
  41. {
  42. g_DllRefCount++;
  43. #ifdef INITCOMMONCONTROLSEX
  44. INITCOMMONCONTROLSEX iccex;
  45. iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
  46. iccex.dwICC = ICC_LISTVIEW_CLASSES;
  47. InitCommonControlsEx(&iccex);
  48. #else
  49. InitCommonControls();
  50. #endif //INITCOMMONCONTROLSEX
  51. m_hMenu = NULL;
  52. m_fInEdit = FALSE;
  53. m_hAccels = LoadAccelerators(g_hInst, MAKEINTRESOURCE(IDR_ACCELS));
  54. m_pPidlMgr = new CPidlMgr();
  55. if(!m_pPidlMgr)
  56. {
  57. delete this;
  58. return;
  59. }
  60. m_psfParent = pFolder;
  61. if(m_psfParent)
  62. m_psfParent->AddRef();
  63. //get the shell's IMalloc pointer
  64. //we'll keep this until we get destroyed
  65. if(FAILED(SHGetMalloc(&m_pMalloc)))
  66. {
  67. delete this;
  68. return;
  69. }
  70. m_pidl = m_pPidlMgr->Copy(pidl);
  71. m_uState = SVUIA_DEACTIVATE;
  72. if(g_pViewList)
  73. g_pViewList->AddToList(this);
  74. m_ObjRefCount = 1;
  75. }
  76. /**************************************************************************
  77. CShellView::~CShellView()
  78. **************************************************************************/
  79. CShellView::~CShellView()
  80. {
  81. if(g_pViewList)
  82. g_pViewList->RemoveFromList(this);
  83. if(m_pidl)
  84. {
  85. m_pPidlMgr->Delete(m_pidl);
  86. m_pidl = NULL;
  87. }
  88. if(m_psfParent)
  89. m_psfParent->Release();
  90. if(m_pMalloc)
  91. {
  92. m_pMalloc->Release();
  93. }
  94. if(m_pPidlMgr)
  95. {
  96. delete m_pPidlMgr;
  97. }
  98. g_DllRefCount--;
  99. }
  100. ///////////////////////////////////////////////////////////////////////////
  101. //
  102. // IUnknown Implementation
  103. //
  104. /**************************************************************************
  105. CShellView::QueryInterface
  106. **************************************************************************/
  107. STDMETHODIMP CShellView::QueryInterface(REFIID riid, LPVOID *ppReturn)
  108. {
  109. *ppReturn = NULL;
  110. //IUnknown
  111. if(IsEqualIID(riid, IID_IUnknown))
  112. {
  113. *ppReturn = this;
  114. }
  115. //IOleWindow
  116. else if(IsEqualIID(riid, IID_IOleWindow))
  117. {
  118. *ppReturn = (IOleWindow*)this;
  119. }
  120. //IShellView
  121. else if(IsEqualIID(riid, IID_IShellView))
  122. {
  123. *ppReturn = (IShellView*)this;
  124. }
  125. if(*ppReturn)
  126. {
  127. (*(LPUNKNOWN*)ppReturn)->AddRef();
  128. return S_OK;
  129. }
  130. return E_NOINTERFACE;
  131. }
  132. /**************************************************************************
  133. CShellView::AddRef
  134. **************************************************************************/
  135. STDMETHODIMP_(DWORD) CShellView::AddRef()
  136. {
  137. return ++m_ObjRefCount;
  138. }
  139. /**************************************************************************
  140. CShellView::Release
  141. **************************************************************************/
  142. STDMETHODIMP_(DWORD) CShellView::Release()
  143. {
  144. if(--m_ObjRefCount == 0)
  145. {
  146. delete this;
  147. return 0;
  148. }
  149. return m_ObjRefCount;
  150. }
  151. ///////////////////////////////////////////////////////////////////////////
  152. //
  153. // IOleWindow Implementation
  154. //
  155. /**************************************************************************
  156. CShellView::GetWindow()
  157. **************************************************************************/
  158. STDMETHODIMP CShellView::GetWindow(HWND *phWnd)
  159. {
  160. *phWnd = m_hWnd;
  161. return S_OK;
  162. }
  163. /**************************************************************************
  164. CShellView::ContextSensitiveHelp()
  165. **************************************************************************/
  166. STDMETHODIMP CShellView::ContextSensitiveHelp(BOOL fEnterMode)
  167. {
  168. return E_NOTIMPL;
  169. }
  170. ///////////////////////////////////////////////////////////////////////////
  171. //
  172. // IShellView Implementation
  173. //
  174. /**************************************************************************
  175. CShellView::TranslateAccelerator()
  176. **************************************************************************/
  177. STDMETHODIMP CShellView::TranslateAccelerator(LPMSG pmsg)
  178. {
  179. if(m_fInEdit)
  180. {
  181. if((pmsg->message >= WM_KEYFIRST) && (pmsg->message <= WM_KEYLAST))
  182. {
  183. TranslateMessage(pmsg);
  184. DispatchMessage(pmsg);
  185. return S_OK;
  186. }
  187. }
  188. else if(::TranslateAccelerator(m_hWnd, m_hAccels, pmsg))
  189. return S_OK;
  190. return S_FALSE;
  191. }
  192. /**************************************************************************
  193. CShellView::EnableModeless()
  194. **************************************************************************/
  195. STDMETHODIMP CShellView::EnableModeless(BOOL fEnable)
  196. {
  197. return E_NOTIMPL;
  198. }
  199. /**************************************************************************
  200. CShellView::OnActivate()
  201. **************************************************************************/
  202. LRESULT CShellView::OnActivate(UINT uState)
  203. {
  204. //don't do anything if the state isn't really changing
  205. if(m_uState == uState)
  206. return S_OK;
  207. OnDeactivate();
  208. //only do this if we are active
  209. if(uState != SVUIA_DEACTIVATE)
  210. {
  211. //merge the menus
  212. m_hMenu = CreateMenu();
  213. if(m_hMenu)
  214. {
  215. OLEMENUGROUPWIDTHS omw = {0, 0, 0, 0, 0, 0};
  216. MENUITEMINFO mii;
  217. m_pShellBrowser->InsertMenusSB(m_hMenu, &omw);
  218. //add your top level sub-menu here, if desired
  219. //get the view menu so we can merge with it
  220. ZeroMemory(&mii, sizeof(mii));
  221. mii.cbSize = sizeof(mii);
  222. mii.fMask = MIIM_SUBMENU;
  223. //merge our items into the File menu
  224. if(GetMenuItemInfo(m_hMenu, FCIDM_MENU_FILE, FALSE, &mii))
  225. {
  226. MergeFileMenu(mii.hSubMenu, (BOOL)(SVUIA_ACTIVATE_FOCUS == uState));
  227. }
  228. //merge our items into the Edit menu
  229. if(GetMenuItemInfo(m_hMenu, FCIDM_MENU_EDIT, FALSE, &mii))
  230. {
  231. MergeEditMenu(mii.hSubMenu, (BOOL)(SVUIA_ACTIVATE_FOCUS == uState));
  232. }
  233. //merge our items into the View menu
  234. if(GetMenuItemInfo(m_hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
  235. {
  236. MergeViewMenu(mii.hSubMenu);
  237. }
  238. //add the items that should only be added if we have the focus
  239. if(SVUIA_ACTIVATE_FOCUS == uState)
  240. {
  241. }
  242. m_pShellBrowser->SetMenuSB(m_hMenu, NULL, m_hWnd);
  243. }
  244. }
  245. m_uState = uState;
  246. UpdateToolbar();
  247. return 0;
  248. }
  249. /**************************************************************************
  250. CShellView::OnDeactivate()
  251. **************************************************************************/
  252. VOID CShellView::OnDeactivate(VOID)
  253. {
  254. if(m_uState != SVUIA_DEACTIVATE)
  255. {
  256. if(m_hMenu)
  257. {
  258. m_pShellBrowser->SetMenuSB(NULL, NULL, NULL);
  259. m_pShellBrowser->RemoveMenusSB(m_hMenu);
  260. DestroyMenu(m_hMenu);
  261. m_hMenu = NULL;
  262. }
  263. m_uState = SVUIA_DEACTIVATE;
  264. }
  265. }
  266. /**************************************************************************
  267. CShellView::UIActivate()
  268. This function activates the view window. Note that activating it
  269. will not change the focus, while setting the focus will activate it.
  270. **************************************************************************/
  271. STDMETHODIMP CShellView::UIActivate(UINT uState)
  272. {
  273. //don't do anything if the state isn't really changing
  274. if(m_uState == uState)
  275. return S_OK;
  276. //OnActivate handles the menu merging and internal state
  277. OnActivate(uState);
  278. //only do this if we are active
  279. if(uState != SVUIA_DEACTIVATE)
  280. {
  281. TCHAR szName[MAX_PATH] = TEXT("");
  282. LRESULT lResult;
  283. int nPartArray[1] = {-1};
  284. //update the status bar
  285. //set the number of parts
  286. m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, 1, (LPARAM)nPartArray, &lResult);
  287. //set the text for the parts
  288. m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 0, (LPARAM)g_szExtTitle, &lResult);
  289. }
  290. return S_OK;
  291. }
  292. /**************************************************************************
  293. CShellView::MergeFileMenu()
  294. **************************************************************************/
  295. VOID CShellView::MergeFileMenu(HMENU hMenu, BOOL fFocus)
  296. {
  297. MENUITEMINFO mii;
  298. UINT uPos = 0;
  299. ZeroMemory(&mii, sizeof(mii));
  300. //uPos += AddFileMenuItems(hMenu, 0, IDM_SEPARATOR, FALSE);
  301. uPos += AddFileMenuItems(hMenu, 0, 0, TRUE);
  302. //add a separator
  303. mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  304. mii.fType = MFT_SEPARATOR;
  305. mii.wID = IDM_SEPARATOR;
  306. mii.fState = MFS_ENABLED;
  307. //insert this item at the beginning of the menu
  308. InsertMenuItem(hMenu, uPos, TRUE, &mii);
  309. uPos++;
  310. if(fFocus)
  311. {
  312. TCHAR szText[MAX_PATH];
  313. //add the Delete item
  314. LoadString(g_hInst, IDS_DELETE, szText, sizeof(szText));
  315. mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  316. mii.fType = MFT_STRING;
  317. mii.fState = MFS_ENABLED;
  318. mii.dwTypeData = szText;
  319. mii.wID = IDM_DELETE;
  320. InsertMenuItem(hMenu, uPos, TRUE, &mii);
  321. uPos++;
  322. //add the Rename item
  323. LoadString(g_hInst, IDS_RENAME, szText, sizeof(szText));
  324. mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  325. mii.fType = MFT_STRING;
  326. mii.fState = MFS_ENABLED;
  327. mii.dwTypeData = szText;
  328. mii.wID = IDM_RENAME;
  329. InsertMenuItem(hMenu, uPos, TRUE, &mii);
  330. uPos++;
  331. //add a separator
  332. mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  333. mii.fType = MFT_SEPARATOR;
  334. mii.wID = IDM_SEPARATOR;
  335. mii.fState = MFS_ENABLED;
  336. InsertMenuItem(hMenu, uPos, TRUE, &mii);
  337. uPos++;
  338. }
  339. }
  340. /**************************************************************************
  341. CShellView::MergeViewMenu()
  342. **************************************************************************/
  343. VOID CShellView::MergeViewMenu(HMENU hMenu)
  344. {
  345. MENUITEMINFO mii;
  346. ZeroMemory(&mii, sizeof(mii));
  347. mii.cbSize = sizeof(mii);
  348. //add a separator at the correct position in the menu
  349. mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  350. mii.fType = MFT_SEPARATOR;
  351. mii.wID = IDM_SEPARATOR;
  352. mii.fState = MFS_ENABLED;
  353. InsertMenuItem(hMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
  354. AddViewMenuItems(hMenu, 0, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE);
  355. }
  356. /**************************************************************************
  357. CShellView::MergeEditMenu()
  358. **************************************************************************/
  359. VOID CShellView::MergeEditMenu(HMENU hMenu, BOOL fFocus)
  360. {
  361. if(hMenu)
  362. {
  363. MENUITEMINFO mii;
  364. TCHAR szText[MAX_PATH];
  365. ZeroMemory(&mii, sizeof(mii));
  366. mii.cbSize = sizeof(mii);
  367. if(fFocus)
  368. {
  369. LoadString(g_hInst, IDS_CUT, szText, sizeof(szText));
  370. mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  371. mii.fType = MFT_STRING;
  372. mii.fState = MFS_ENABLED;
  373. mii.dwTypeData = szText;
  374. mii.wID = IDM_CUT;
  375. InsertMenuItem(hMenu, -1, TRUE, &mii);
  376. LoadString(g_hInst, IDS_COPY, szText, sizeof(szText));
  377. mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  378. mii.fType = MFT_STRING;
  379. mii.fState = MFS_ENABLED;
  380. mii.dwTypeData = szText;
  381. mii.wID = IDM_COPY;
  382. InsertMenuItem(hMenu, -1, TRUE, &mii);
  383. }
  384. //add the paste menu items at the correct position in the menu
  385. LoadString(g_hInst, IDS_PASTE, szText, sizeof(szText));
  386. mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  387. mii.fType = MFT_STRING;
  388. mii.fState = MFS_ENABLED;
  389. mii.dwTypeData = szText;
  390. mii.wID = IDM_PASTE;
  391. InsertMenuItem(hMenu, -1, TRUE, &mii);
  392. }
  393. }
  394. /**************************************************************************
  395. CShellView::MergeToolbar()
  396. **************************************************************************/
  397. VOID CShellView::MergeToolbar(VOID)
  398. {
  399. int i;
  400. TBADDBITMAP tbab;
  401. LRESULT lStdOffset;
  402. LRESULT lViewOffset;
  403. m_pShellBrowser->SetToolbarItems(NULL, 0, FCT_MERGE);
  404. tbab.hInst = HINST_COMMCTRL;
  405. tbab.nID = (int)IDB_STD_SMALL_COLOR;
  406. m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ADDBITMAP, 0, (LPARAM)&tbab, &lStdOffset);
  407. tbab.hInst = HINST_COMMCTRL;
  408. tbab.nID = (int)IDB_VIEW_SMALL_COLOR;
  409. m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ADDBITMAP, 0, (LPARAM)&tbab, &lViewOffset);
  410. //get the number of items in tool array
  411. for(i = 0; -1 != g_Tools[i].idCommand; i++)
  412. {
  413. }
  414. LPTBBUTTON ptbb = (LPTBBUTTON)GlobalAlloc(GPTR, sizeof(TBBUTTON) * i);
  415. if(ptbb)
  416. {
  417. for(i = 0; -1 != g_Tools[i].idCommand; i++)
  418. {
  419. (ptbb + i)->iBitmap = 0;
  420. switch(g_Tools[i].uImageSet)
  421. {
  422. case IDB_STD_SMALL_COLOR:
  423. (ptbb + i)->iBitmap = lStdOffset + g_Tools[i].iImage;
  424. break;
  425. case IDB_VIEW_SMALL_COLOR:
  426. (ptbb + i)->iBitmap = lViewOffset + g_Tools[i].iImage;
  427. break;
  428. }
  429. (ptbb + i)->idCommand = g_Tools[i].idCommand;
  430. (ptbb + i)->fsState = g_Tools[i].bState;
  431. (ptbb + i)->fsStyle = g_Tools[i].bStyle;
  432. (ptbb + i)->dwData = 0;
  433. (ptbb + i)->iString = 0;
  434. }
  435. m_pShellBrowser->SetToolbarItems(ptbb, i, FCT_MERGE);
  436. GlobalFree((HGLOBAL)ptbb);
  437. }
  438. UpdateToolbar();
  439. }
  440. /**************************************************************************
  441. CShellView::Refresh()
  442. **************************************************************************/
  443. STDMETHODIMP CShellView::Refresh(VOID)
  444. {
  445. //empty the list
  446. ListView_DeleteAllItems(m_hwndList);
  447. //refill the list
  448. FillList();
  449. return S_OK;
  450. }
  451. /**************************************************************************
  452. CShellView::CreateViewWindow()
  453. **************************************************************************/
  454. STDMETHODIMP CShellView::CreateViewWindow( LPSHELLVIEW pPrevView,
  455. LPCFOLDERSETTINGS lpfs,
  456. LPSHELLBROWSER psb,
  457. LPRECT prcView,
  458. HWND *phWnd)
  459. {
  460. WNDCLASS wc;
  461. *phWnd = NULL;
  462. //if our window class has not been registered, then do so
  463. if(!GetClassInfo(g_hInst, NS_CLASS_NAME, &wc))
  464. {
  465. ZeroMemory(&wc, sizeof(wc));
  466. wc.style = CS_HREDRAW | CS_VREDRAW;
  467. wc.lpfnWndProc = WndProc;
  468. wc.cbClsExtra = 0;
  469. wc.cbWndExtra = 0;
  470. wc.hInstance = g_hInst;
  471. wc.hIcon = NULL;
  472. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  473. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  474. wc.lpszMenuName = NULL;
  475. wc.lpszClassName = NS_CLASS_NAME;
  476. if(!RegisterClass(&wc))
  477. return E_FAIL;
  478. }
  479. //set up the member variables
  480. m_pShellBrowser = psb;
  481. m_FolderSettings = *lpfs;
  482. //get our parent window
  483. m_pShellBrowser->GetWindow(&m_hwndParent);
  484. *phWnd = CreateWindowEx( 0,
  485. NS_CLASS_NAME,
  486. NULL,
  487. WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
  488. prcView->left,
  489. prcView->top,
  490. prcView->right - prcView->left,
  491. prcView->bottom - prcView->top,
  492. m_hwndParent,
  493. NULL,
  494. g_hInst,
  495. (LPVOID)this);
  496. if(!*phWnd)
  497. return E_FAIL;
  498. MergeToolbar();
  499. m_pShellBrowser->AddRef();
  500. return S_OK;
  501. }
  502. /**************************************************************************
  503. CShellView::DestroyViewWindow()
  504. **************************************************************************/
  505. STDMETHODIMP CShellView::DestroyViewWindow(VOID)
  506. {
  507. //Make absolutely sure all our UI is cleaned up.
  508. UIActivate(SVUIA_DEACTIVATE);
  509. if(m_hMenu)
  510. DestroyMenu(m_hMenu);
  511. DestroyWindow(m_hWnd);
  512. //release the shell browser object
  513. m_pShellBrowser->Release();
  514. return S_OK;
  515. }
  516. /**************************************************************************
  517. CShellView::GetCurrentInfo()
  518. **************************************************************************/
  519. STDMETHODIMP CShellView::GetCurrentInfo(LPFOLDERSETTINGS lpfs)
  520. {
  521. *lpfs = m_FolderSettings;
  522. return S_OK;
  523. }
  524. /**************************************************************************
  525. CShellView::AddPropertySheetPages()
  526. **************************************************************************/
  527. STDMETHODIMP CShellView::AddPropertySheetPages( DWORD dwReserved,
  528. LPFNADDPROPSHEETPAGE lpfn,
  529. LPARAM lParam)
  530. {
  531. return E_NOTIMPL;
  532. }
  533. /**************************************************************************
  534. CShellView::SaveViewState()
  535. **************************************************************************/
  536. STDMETHODIMP CShellView::SaveViewState(VOID)
  537. {
  538. return S_OK;
  539. }
  540. /**************************************************************************
  541. CShellView::SelectItem()
  542. **************************************************************************/
  543. STDMETHODIMP CShellView::SelectItem(LPCITEMIDLIST pidlItem, UINT uFlags)
  544. {
  545. return E_NOTIMPL;
  546. }
  547. /**************************************************************************
  548. CShellView::GetItemObject()
  549. **************************************************************************/
  550. STDMETHODIMP CShellView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut)
  551. {
  552. *ppvOut = NULL;
  553. return E_NOTIMPL;
  554. }
  555. /**************************************************************************
  556. CShellView::WndProc()
  557. **************************************************************************/
  558. LRESULT CALLBACK CShellView::WndProc( HWND hWnd,
  559. UINT uMessage,
  560. WPARAM wParam,
  561. LPARAM lParam)
  562. {
  563. CShellView *pThis = (CShellView*)GetWindowLong(hWnd, VIEW_POINTER_OFFSET);
  564. switch (uMessage)
  565. {
  566. case WM_NCCREATE:
  567. {
  568. LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
  569. pThis = (CShellView*)(lpcs->lpCreateParams);
  570. SetWindowLong(hWnd, VIEW_POINTER_OFFSET, (LONG)pThis);
  571. //set the window handle
  572. pThis->m_hWnd = hWnd;
  573. }
  574. break;
  575. case WM_SIZE:
  576. return pThis->OnSize(LOWORD(lParam), HIWORD(lParam));
  577. case WM_CREATE:
  578. return pThis->OnCreate();
  579. case WM_DESTROY:
  580. return pThis->OnDestroy();
  581. case WM_SETFOCUS:
  582. return pThis->OnSetFocus();
  583. case WM_KILLFOCUS:
  584. return pThis->OnKillFocus();
  585. case WM_ACTIVATE:
  586. return pThis->OnActivate(SVUIA_ACTIVATE_FOCUS);
  587. case WM_COMMAND:
  588. return pThis->OnCommand( GET_WM_COMMAND_ID(wParam, lParam),
  589. GET_WM_COMMAND_CMD(wParam, lParam),
  590. GET_WM_COMMAND_HWND(wParam, lParam));
  591. case WM_INITMENUPOPUP:
  592. return pThis->UpdateMenu((HMENU)wParam);
  593. case WM_NOTIFY:
  594. return pThis->OnNotify((UINT)wParam, (LPNMHDR)lParam);
  595. case WM_SETTINGCHANGE:
  596. return pThis->OnSettingChange((LPCTSTR)lParam);
  597. case WM_CONTEXTMENU:
  598. {
  599. pThis->DoContextMenu(LOWORD(lParam), HIWORD(lParam), FALSE, (UINT)-1);
  600. return 0;
  601. }
  602. }
  603. return DefWindowProc(hWnd, uMessage, wParam, lParam);
  604. }
  605. /**************************************************************************
  606. CShellView::OnSetFocus()
  607. **************************************************************************/
  608. LRESULT CShellView::OnSetFocus(VOID)
  609. {
  610. /*
  611. Tell the browser one of our windows has received the focus. This should always
  612. be done before merging menus (OnActivate merges the menus) if one of our
  613. windows has the focus.
  614. */
  615. m_pShellBrowser->OnViewWindowActive(this);
  616. OnActivate(SVUIA_ACTIVATE_FOCUS);
  617. return 0;
  618. }
  619. /**************************************************************************
  620. CShellView::OnKillFocus()
  621. **************************************************************************/
  622. LRESULT CShellView::OnKillFocus(VOID)
  623. {
  624. OnActivate(SVUIA_ACTIVATE_NOFOCUS);
  625. return 0;
  626. }
  627. /**************************************************************************
  628. CShellView::OnCommand()
  629. **************************************************************************/
  630. LRESULT CShellView::OnCommand(DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
  631. {
  632. //ignore command messages while in edit mode
  633. if(m_fInEdit)
  634. return 0;
  635. DoContextMenu(0, 0, FALSE, dwCmdID);
  636. return 0;
  637. }
  638. /**************************************************************************
  639. CShellView::UpdateMenu()
  640. **************************************************************************/
  641. LRESULT CShellView::UpdateMenu(HMENU hMenu)
  642. {
  643. UINT uCommand;
  644. //enable/disable your menu items here
  645. OpenClipboard(NULL);
  646. HGLOBAL hClip = GetClipboardData(RegisterClipboardFormat(CFSTR_SAMPVIEWDATA));
  647. CloseClipboard();
  648. EnableMenuItem(hMenu, IDM_PASTE, MF_BYCOMMAND | (hClip ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
  649. uCommand = ListView_GetSelectedCount(m_hwndList);
  650. EnableMenuItem(hMenu, IDM_CUT, MF_BYCOMMAND | (uCommand ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
  651. EnableMenuItem(hMenu, IDM_COPY, MF_BYCOMMAND | (uCommand ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
  652. switch(m_FolderSettings.ViewMode)
  653. {
  654. case FVM_ICON:
  655. uCommand = IDM_VIEW_LARGE;
  656. break;
  657. case FVM_SMALLICON:
  658. uCommand = IDM_VIEW_SMALL;
  659. break;
  660. case FVM_LIST:
  661. uCommand = IDM_VIEW_LIST;
  662. break;
  663. case FVM_DETAILS:
  664. default:
  665. uCommand = IDM_VIEW_DETAILS;
  666. break;
  667. }
  668. CheckMenuRadioItem(hMenu, IDM_VIEW_LARGE, IDM_VIEW_DETAILS, uCommand, MF_BYCOMMAND);
  669. return 0;
  670. }
  671. /**************************************************************************
  672. CShellView::UpdateToolbar()
  673. **************************************************************************/
  674. LRESULT CShellView::UpdateToolbar(VOID)
  675. {
  676. LRESULT lResult;
  677. UINT uCommand;
  678. //enable/disable/check the toolbar items here
  679. switch(m_FolderSettings.ViewMode)
  680. {
  681. case FVM_ICON:
  682. uCommand = IDM_VIEW_LARGE;
  683. break;
  684. case FVM_SMALLICON:
  685. uCommand = IDM_VIEW_SMALL;
  686. break;
  687. case FVM_LIST:
  688. uCommand = IDM_VIEW_LIST;
  689. break;
  690. case FVM_DETAILS:
  691. default:
  692. uCommand = IDM_VIEW_DETAILS;
  693. break;
  694. }
  695. m_pShellBrowser->SendControlMsg( FCW_TOOLBAR,
  696. TB_CHECKBUTTON,
  697. uCommand,
  698. MAKELPARAM(TRUE, 0),
  699. &lResult);
  700. return 0;
  701. }
  702. /**************************************************************************
  703. CShellView::OnNotify()
  704. **************************************************************************/
  705. #define MENU_MAX 100
  706. LRESULT CShellView::OnNotify(UINT CtlID, LPNMHDR lpnmh)
  707. {
  708. switch(lpnmh->code)
  709. {
  710. /*
  711. The original shell on NT will always send TTN_NEEDTEXTW, so handle the
  712. cases separately.
  713. */
  714. case TTN_NEEDTEXTA:
  715. {
  716. LPNMTTDISPINFOA pttt = (LPNMTTDISPINFOA)lpnmh;
  717. int i;
  718. for(i = 0; -1 != g_Tools[i].idCommand; i++)
  719. {
  720. if(g_Tools[i].idCommand == pttt->hdr.idFrom)
  721. {
  722. LoadStringA(g_hInst, g_Tools[i].idString, pttt->szText, sizeof(pttt->szText));
  723. return TRUE;
  724. }
  725. }
  726. }
  727. break;
  728. case TTN_NEEDTEXTW:
  729. {
  730. LPNMTTDISPINFOW pttt = (LPNMTTDISPINFOW)lpnmh;
  731. int i;
  732. for(i = 0; -1 != g_Tools[i].idCommand; i++)
  733. {
  734. if(g_Tools[i].idCommand == pttt->hdr.idFrom)
  735. {
  736. LoadStringW(g_hInst, g_Tools[i].idString, pttt->szText, sizeof(pttt->szText));
  737. return TRUE;
  738. }
  739. }
  740. }
  741. break;
  742. case NM_SETFOCUS:
  743. OnSetFocus();
  744. break;
  745. case NM_KILLFOCUS:
  746. OnDeactivate();
  747. break;
  748. case HDN_ENDTRACK:
  749. {
  750. g_nColumn = ListView_GetColumnWidth(m_hwndList, 0);
  751. ListView_SetColumnWidth(m_hwndList, 1, LVSCW_AUTOSIZE_USEHEADER);
  752. }
  753. return 0;
  754. case LVN_DELETEITEM:
  755. {
  756. NM_LISTVIEW *lpnmlv = (NM_LISTVIEW*)lpnmh;
  757. //delete the pidl because we made a copy of it
  758. m_pPidlMgr->Delete((LPITEMIDLIST)lpnmlv->lParam);
  759. }
  760. break;
  761. #ifdef LVN_ITEMACTIVATE
  762. case LVN_ITEMACTIVATE:
  763. #else //LVN_ITEMACTIVATE
  764. case NM_DBLCLK:
  765. case NM_RETURN:
  766. #endif //LVN_ITEMACTIVATE
  767. DoContextMenu(0, 0, TRUE, (DWORD)-1);
  768. return 0;
  769. case LVN_GETDISPINFO:
  770. {
  771. NMLVDISPINFO *lpdi = (NMLVDISPINFO*)lpnmh;
  772. LPITEMIDLIST pidl = (LPITEMIDLIST)lpdi->item.lParam;
  773. //is the sub-item information being requested?
  774. if(lpdi->item.iSubItem)
  775. {
  776. //is the text being requested?
  777. if(lpdi->item.mask & LVIF_TEXT)
  778. {
  779. //is this a folder or a value?
  780. if(m_pPidlMgr->IsFolder(pidl))
  781. {
  782. LoadString(g_hInst, IDS_FOLDER_DATA, lpdi->item.pszText, lpdi->item.cchTextMax);
  783. }
  784. //its an item
  785. else
  786. {
  787. m_pPidlMgr->GetData(pidl, lpdi->item.pszText, lpdi->item.cchTextMax);
  788. }
  789. }
  790. }
  791. //the item text is being requested
  792. else
  793. {
  794. //is the text being requested?
  795. if(lpdi->item.mask & LVIF_TEXT)
  796. {
  797. STRRET str;
  798. if(SUCCEEDED(m_psfParent->GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &str)))
  799. {
  800. GetTextFromSTRRET(m_pMalloc, &str, pidl, lpdi->item.pszText, lpdi->item.cchTextMax);
  801. }
  802. }
  803. //is the image being requested?
  804. if(lpdi->item.mask & LVIF_IMAGE)
  805. {
  806. IExtractIcon *pei;
  807. if(SUCCEEDED(m_psfParent->GetUIObjectOf(m_hWnd, 1, (LPCITEMIDLIST*)&pidl, IID_IExtractIcon, NULL, (LPVOID*)&pei)))
  808. {
  809. UINT uFlags;
  810. //GetIconLocation will give us the index into our image list
  811. pei->GetIconLocation(GIL_FORSHELL, NULL, 0, &lpdi->item.iImage, &uFlags);
  812. pei->Release();
  813. }
  814. }
  815. }
  816. }
  817. return 0;
  818. case LVN_BEGINLABELEDIT:
  819. {
  820. NMLVDISPINFO *lpdi = (NMLVDISPINFO*)lpnmh;
  821. LPITEMIDLIST pidl = (LPITEMIDLIST)lpdi->item.lParam;
  822. DWORD dwAttr = SFGAO_CANRENAME;
  823. m_psfParent->GetAttributesOf(1, (LPCITEMIDLIST*)&pidl, &dwAttr);
  824. if(SFGAO_CANRENAME & dwAttr)
  825. {
  826. m_fInEdit = TRUE;
  827. return FALSE;
  828. }
  829. }
  830. return TRUE;
  831. case LVN_ENDLABELEDIT:
  832. {
  833. LRESULT lResult = 0;
  834. NMLVDISPINFO *pdi = (NMLVDISPINFO*)lpnmh;
  835. if(pdi->item.pszText)
  836. {
  837. //the user wants to keep the change
  838. LVITEM lvItem;
  839. LPITEMIDLIST pidl;
  840. WCHAR wszNewName[MAX_PATH];
  841. ZeroMemory(&lvItem, sizeof(lvItem));
  842. lvItem.mask = LVIF_PARAM;
  843. lvItem.iItem = pdi->item.iItem;
  844. ListView_GetItem(m_hwndList, &lvItem);
  845. LocalToWideChar(wszNewName, pdi->item.pszText, MAX_PATH);
  846. /*
  847. This will cause this class' RenameItem function to be called. This
  848. can cause problems, so the m_fInEdit flag will prevent RenameItem
  849. from being called on this object. SetNameOf will also free the old
  850. PIDL, so we don't have to do it again.
  851. */
  852. HRESULT hr = m_psfParent->SetNameOf(NULL, (LPITEMIDLIST)lvItem.lParam, wszNewName, 0, &pidl);
  853. if(SUCCEEDED(hr) && pidl)
  854. {
  855. lvItem.mask = LVIF_PARAM;
  856. lvItem.lParam = (LPARAM)pidl;
  857. ListView_SetItem(m_hwndList, &lvItem);
  858. lResult = TRUE;
  859. }
  860. }
  861. m_fInEdit = FALSE;
  862. return lResult;
  863. }
  864. case LVN_BEGINDRAG:
  865. {
  866. HRESULT hr;
  867. IDataObject *pDataObject = NULL;
  868. UINT uItemCount;
  869. LPITEMIDLIST *aPidls;
  870. //get the number of selected items
  871. uItemCount = ListView_GetSelectedCount(m_hwndList);
  872. if(!uItemCount)
  873. return 0;
  874. aPidls = (LPITEMIDLIST*)m_pMalloc->Alloc(uItemCount * sizeof(LPITEMIDLIST));
  875. if(aPidls)
  876. {
  877. int i;
  878. UINT x;
  879. for(i = 0, x = 0; x < uItemCount && i < ListView_GetItemCount(m_hwndList); i++)
  880. {
  881. if(ListView_GetItemState(m_hwndList, i, LVIS_SELECTED))
  882. {
  883. LVITEM lvItem;
  884. lvItem.mask = LVIF_PARAM;
  885. lvItem.iItem = i;
  886. ListView_GetItem(m_hwndList, &lvItem);
  887. aPidls[x] = (LPITEMIDLIST)lvItem.lParam;
  888. x++;
  889. }
  890. }
  891. hr = m_psfParent->GetUIObjectOf( m_hWnd,
  892. uItemCount,
  893. (LPCITEMIDLIST*)aPidls,
  894. IID_IDataObject,
  895. NULL,
  896. (LPVOID*)&pDataObject);
  897. if(SUCCEEDED(hr) && pDataObject)
  898. {
  899. IDropSource *pDropSource = new CDropSource;
  900. DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
  901. DWORD dwAttributes = SFGAO_CANLINK;
  902. hr = m_psfParent->GetAttributesOf( uItemCount,
  903. (LPCITEMIDLIST*)aPidls,
  904. &dwAttributes);
  905. if(SUCCEEDED(hr) && (dwAttributes & SFGAO_CANLINK))
  906. {
  907. dwEffect |= DROPEFFECT_LINK;
  908. }
  909. DoDragDrop( pDataObject,
  910. pDropSource,
  911. dwEffect,
  912. &dwEffect);
  913. pDataObject->Release();
  914. pDropSource->Release();
  915. }
  916. m_pMalloc->Free(aPidls);
  917. }
  918. }
  919. break;
  920. case LVN_ITEMCHANGED:
  921. {
  922. UpdateToolbar();
  923. }
  924. break;
  925. }
  926. return 0;
  927. }
  928. /**************************************************************************
  929. CShellView::OnSize()
  930. **************************************************************************/
  931. LRESULT CShellView::OnSize(WORD wWidth, WORD wHeight)
  932. {
  933. //resize the ListView to fit our window
  934. if(m_hwndList)
  935. {
  936. MoveWindow(m_hwndList, 0, 0, wWidth, wHeight, TRUE);
  937. ListView_SetColumnWidth(m_hwndList, 0, g_nColumn);
  938. ListView_SetColumnWidth(m_hwndList, 1, LVSCW_AUTOSIZE_USEHEADER);
  939. }
  940. return 0;
  941. }
  942. /**************************************************************************
  943. CShellView::OnCreate()
  944. **************************************************************************/
  945. LRESULT CShellView::OnCreate(VOID)
  946. {
  947. //create the ListView
  948. if(CreateList())
  949. {
  950. if(InitList())
  951. {
  952. FillList();
  953. }
  954. }
  955. HRESULT hr;
  956. IDropTarget *pdt;
  957. //get the IDropTarget for this folder
  958. hr = m_psfParent->CreateViewObject( m_hWnd,
  959. IID_IDropTarget,
  960. (LPVOID*)&pdt);
  961. if(SUCCEEDED(hr))
  962. {
  963. //register the window as a drop target
  964. RegisterDragDrop(m_hWnd, pdt);
  965. pdt->Release();
  966. }
  967. return 0;
  968. }
  969. /**************************************************************************
  970. CShellView::OnDestroy()
  971. **************************************************************************/
  972. LRESULT CShellView::OnDestroy(VOID)
  973. {
  974. //unregister the window as a drop target
  975. RevokeDragDrop(m_hWnd);
  976. return 0;
  977. }
  978. /**************************************************************************
  979. CShellView::CreateList()
  980. **************************************************************************/
  981. BOOL CShellView::CreateList(VOID)
  982. {
  983. DWORD dwStyle;
  984. dwStyle = WS_TABSTOP |
  985. WS_VISIBLE |
  986. WS_CHILD |
  987. WS_BORDER |
  988. LVS_NOSORTHEADER |
  989. LVS_SHAREIMAGELISTS |
  990. LVS_EDITLABELS;
  991. switch(m_FolderSettings.ViewMode)
  992. {
  993. default:
  994. case FVM_ICON:
  995. dwStyle |= LVS_ICON;
  996. break;
  997. case FVM_SMALLICON:
  998. dwStyle |= LVS_SMALLICON;
  999. break;
  1000. case FVM_LIST:
  1001. dwStyle |= LVS_LIST;
  1002. break;
  1003. case FVM_DETAILS:
  1004. dwStyle |= LVS_REPORT;
  1005. break;
  1006. }
  1007. if(FWF_AUTOARRANGE & m_FolderSettings.fFlags)
  1008. dwStyle |= LVS_AUTOARRANGE;
  1009. m_hwndList = CreateWindowEx( WS_EX_CLIENTEDGE,
  1010. WC_LISTVIEW,
  1011. NULL,
  1012. dwStyle,
  1013. 0,
  1014. 0,
  1015. 0,
  1016. 0,
  1017. m_hWnd,
  1018. (HMENU)ID_LISTVIEW,
  1019. g_hInst,
  1020. NULL);
  1021. if(!m_hwndList)
  1022. return FALSE;
  1023. GetShellSettings();
  1024. return TRUE;
  1025. }
  1026. /**************************************************************************
  1027. CShellView::InitList()
  1028. **************************************************************************/
  1029. BOOL CShellView::InitList(VOID)
  1030. {
  1031. LVCOLUMN lvColumn;
  1032. TCHAR szString[MAX_PATH];
  1033. //empty the list
  1034. ListView_DeleteAllItems(m_hwndList);
  1035. //initialize the columns
  1036. lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  1037. lvColumn.fmt = LVCFMT_LEFT;
  1038. lvColumn.pszText = szString;
  1039. lvColumn.cx = g_nColumn;
  1040. LoadString(g_hInst, IDS_COLUMN1, szString, sizeof(szString));
  1041. ListView_InsertColumn(m_hwndList, 0, &lvColumn);
  1042. lvColumn.cx = g_nColumn;
  1043. LoadString(g_hInst, IDS_COLUMN2, szString, sizeof(szString));
  1044. ListView_InsertColumn(m_hwndList, 1, &lvColumn);
  1045. ListView_SetImageList(m_hwndList, g_himlLarge, LVSIL_NORMAL);
  1046. ListView_SetImageList(m_hwndList, g_himlSmall, LVSIL_SMALL);
  1047. return TRUE;
  1048. }
  1049. /**************************************************************************
  1050. CShellView::FillList()
  1051. **************************************************************************/
  1052. VOID CShellView::FillList(VOID)
  1053. {
  1054. LPENUMIDLIST pEnumIDList;
  1055. if(SUCCEEDED(m_psfParent->EnumObjects(m_hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList)))
  1056. {
  1057. LPITEMIDLIST pidl;
  1058. DWORD dwFetched;
  1059. //turn the listview's redrawing off
  1060. SendMessage(m_hwndList, WM_SETREDRAW, FALSE, 0);
  1061. while((S_OK == pEnumIDList->Next(1, &pidl, &dwFetched)) && dwFetched)
  1062. {
  1063. AddItem(pidl);
  1064. /*
  1065. */
  1066. }
  1067. //sort the items
  1068. ListView_SortItems(m_hwndList, CompareItems, (LPARAM)m_psfParent);
  1069. //turn the listview's redrawing back on and force it to draw
  1070. SendMessage(m_hwndList, WM_SETREDRAW, TRUE, 0);
  1071. InvalidateRect(m_hwndList, NULL, TRUE);
  1072. UpdateWindow(m_hwndList);
  1073. pEnumIDList->Release();
  1074. }
  1075. }
  1076. /**************************************************************************
  1077. CShellView::GetShellSettings()
  1078. **************************************************************************/
  1079. #if (_WIN32_IE >= 0x0400)
  1080. typedef VOID (WINAPI *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
  1081. VOID CShellView::GetShellSettings(VOID)
  1082. {
  1083. SHELLFLAGSTATE sfs;
  1084. HINSTANCE hinstShell32;
  1085. /*
  1086. Since SHGetSettings is not implemented in all versions of the shell, get the
  1087. function address manually at run time. This allows the extension to run on all
  1088. platforms.
  1089. */
  1090. ZeroMemory(&sfs, sizeof(sfs));
  1091. /*
  1092. The default, in case any of the following steps fails, is classic Windows 95
  1093. style.
  1094. */
  1095. sfs.fWin95Classic = TRUE;
  1096. hinstShell32 = LoadLibrary(TEXT("shell32.dll"));
  1097. if(hinstShell32)
  1098. {
  1099. PFNSHGETSETTINGSPROC pfnSHGetSettings;
  1100. pfnSHGetSettings = (PFNSHGETSETTINGSPROC)GetProcAddress(hinstShell32, "SHGetSettings");
  1101. if(pfnSHGetSettings)
  1102. {
  1103. (*pfnSHGetSettings)(&sfs, SSF_DOUBLECLICKINWEBVIEW | SSF_WIN95CLASSIC);
  1104. }
  1105. FreeLibrary(hinstShell32);
  1106. }
  1107. DWORD dwExStyles = 0;
  1108. if(!sfs.fWin95Classic && !sfs.fDoubleClickInWebView)
  1109. {
  1110. dwExStyles |= LVS_EX_ONECLICKACTIVATE |
  1111. LVS_EX_TRACKSELECT |
  1112. LVS_EX_UNDERLINEHOT;
  1113. }
  1114. ListView_SetExtendedListViewStyle(m_hwndList, dwExStyles);
  1115. }
  1116. #else
  1117. VOID CShellView::GetShellSettings(VOID)
  1118. {
  1119. }
  1120. #endif
  1121. /**************************************************************************
  1122. CShellView::OnSettingChange()
  1123. **************************************************************************/
  1124. LRESULT CShellView::OnSettingChange(LPCTSTR lpszSection)
  1125. {
  1126. if(0 == lstrcmpi(lpszSection, TEXT("ShellState")))
  1127. {
  1128. GetShellSettings();
  1129. return 0;
  1130. }
  1131. return 0;
  1132. }
  1133. /**************************************************************************
  1134. CShellView::DoContextMenu()
  1135. **************************************************************************/
  1136. VOID CShellView::DoContextMenu(WORD x, WORD y, BOOL fDefault, DWORD dwCmdIn)
  1137. {
  1138. UINT uSelected = 0;
  1139. LPITEMIDLIST *aSelectedItems = NULL;
  1140. LPCONTEXTMENU pContextMenu = NULL;
  1141. if(m_uState != SVUIA_ACTIVATE_NOFOCUS)
  1142. {
  1143. uSelected = ListView_GetSelectedCount(m_hwndList);
  1144. }
  1145. if(uSelected)
  1146. {
  1147. aSelectedItems = (LPITEMIDLIST*)m_pMalloc->Alloc((uSelected + 1) * sizeof(LPITEMIDLIST));
  1148. if(aSelectedItems)
  1149. {
  1150. UINT i;
  1151. LVITEM lvItem;
  1152. ZeroMemory(&lvItem, sizeof(lvItem));
  1153. lvItem.mask = LVIF_STATE | LVIF_PARAM;
  1154. lvItem.stateMask = LVIS_SELECTED;
  1155. lvItem.iItem = 0;
  1156. i = 0;
  1157. while(ListView_GetItem(m_hwndList, &lvItem) && (i < uSelected))
  1158. {
  1159. if(lvItem.state & LVIS_SELECTED)
  1160. {
  1161. aSelectedItems[i] = (LPITEMIDLIST)lvItem.lParam;
  1162. i++;
  1163. }
  1164. lvItem.iItem++;
  1165. }
  1166. m_psfParent->GetUIObjectOf( m_hwndParent,
  1167. uSelected,
  1168. (LPCITEMIDLIST*)aSelectedItems,
  1169. IID_IContextMenu,
  1170. NULL,
  1171. (LPVOID*)&pContextMenu);
  1172. }
  1173. }
  1174. else
  1175. {
  1176. m_psfParent->CreateViewObject( m_hwndParent,
  1177. IID_IContextMenu,
  1178. (LPVOID*)&pContextMenu);
  1179. }
  1180. if(pContextMenu)
  1181. {
  1182. HMENU hMenu = CreatePopupMenu();
  1183. /*
  1184. See if we are in Explore or Open mode. If the browser's tree is present,
  1185. then we are in Explore mode.
  1186. */
  1187. BOOL fExplore = FALSE;
  1188. HWND hwndTree = NULL;
  1189. if(SUCCEEDED(m_pShellBrowser->GetControlWindow(FCW_TREE, &hwndTree)) && hwndTree)
  1190. {
  1191. fExplore = TRUE;
  1192. }
  1193. if(hMenu && SUCCEEDED(pContextMenu->QueryContextMenu( hMenu,
  1194. 0,
  1195. 0,
  1196. MENU_MAX,
  1197. CMF_NORMAL |
  1198. (fExplore ? CMF_EXPLORE : 0) |
  1199. ((uSelected > 1) ? MYCMF_MULTISELECT: 0))))
  1200. {
  1201. UINT uCommand;
  1202. if(fDefault)
  1203. {
  1204. MENUITEMINFO mii;
  1205. int nMenuIndex;
  1206. uCommand = 0;
  1207. ZeroMemory(&mii, sizeof(mii));
  1208. mii.cbSize = sizeof(mii);
  1209. mii.fMask = MIIM_STATE | MIIM_ID;
  1210. nMenuIndex = 0;
  1211. //find the default item in the menu
  1212. while(GetMenuItemInfo(hMenu, nMenuIndex, TRUE, &mii))
  1213. {
  1214. if(mii.fState & MFS_DEFAULT)
  1215. {
  1216. uCommand = mii.wID;
  1217. break;
  1218. }
  1219. nMenuIndex++;
  1220. }
  1221. }
  1222. else if(-1 != dwCmdIn)
  1223. {
  1224. //this command will get sent directly without bringing up the menu
  1225. uCommand = dwCmdIn;
  1226. }
  1227. else
  1228. {
  1229. uCommand = TrackPopupMenu( hMenu,
  1230. TPM_LEFTALIGN | TPM_RETURNCMD,
  1231. x,
  1232. y,
  1233. 0,
  1234. m_hWnd,
  1235. NULL);
  1236. }
  1237. if(uCommand > 0)
  1238. {
  1239. //some commands need to be handled by the view itself
  1240. switch(uCommand)
  1241. {
  1242. case IDM_VIEW_LARGE:
  1243. OnViewLarge();
  1244. break;
  1245. case IDM_VIEW_SMALL:
  1246. OnViewSmall();
  1247. break;
  1248. case IDM_VIEW_LIST:
  1249. OnViewList();
  1250. break;
  1251. case IDM_VIEW_DETAILS:
  1252. OnViewDetails();
  1253. break;
  1254. default:
  1255. {
  1256. CMINVOKECOMMANDINFO cmi;
  1257. ZeroMemory(&cmi, sizeof(cmi));
  1258. cmi.cbSize = sizeof(cmi);
  1259. cmi.hwnd = m_hWnd;
  1260. cmi.lpVerb = (LPCSTR)MAKEINTRESOURCE(uCommand);
  1261. pContextMenu->InvokeCommand(&cmi);
  1262. }
  1263. break;
  1264. }
  1265. }
  1266. DestroyMenu(hMenu);
  1267. }
  1268. pContextMenu->Release();
  1269. }
  1270. if(aSelectedItems)
  1271. m_pMalloc->Free(aSelectedItems);
  1272. UpdateToolbar();
  1273. }
  1274. /**************************************************************************
  1275. CShellView::AddItem()
  1276. **************************************************************************/
  1277. BOOL CShellView::AddItem(LPCITEMIDLIST pidl)
  1278. {
  1279. LVITEM lvItem;
  1280. ZeroMemory(&lvItem, sizeof(lvItem));
  1281. //set the mask
  1282. lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  1283. //add the item to the end of the list
  1284. lvItem.iItem = ListView_GetItemCount(m_hwndList);
  1285. //set the item's data
  1286. lvItem.lParam = (LPARAM)m_pPidlMgr->Copy(pidl);
  1287. //get text on a callback basis
  1288. lvItem.pszText = LPSTR_TEXTCALLBACK;
  1289. //get the image on a callback basis
  1290. lvItem.iImage = I_IMAGECALLBACK;
  1291. //add the item
  1292. if(-1 == ListView_InsertItem(m_hwndList, &lvItem))
  1293. return FALSE;
  1294. return TRUE;
  1295. }
  1296. /**************************************************************************
  1297. CShellView::DeleteItem()
  1298. **************************************************************************/
  1299. BOOL CShellView::DeleteItem(LPCITEMIDLIST pidl)
  1300. {
  1301. //delete the item from the list
  1302. int nIndex = FindItemPidl(pidl);
  1303. if(-1 != nIndex)
  1304. {
  1305. return ListView_DeleteItem(m_hwndList, nIndex);
  1306. }
  1307. return FALSE;
  1308. }
  1309. /**************************************************************************
  1310. CShellView::RenameItem()
  1311. **************************************************************************/
  1312. BOOL CShellView::RenameItem(LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew)
  1313. {
  1314. //don't allow this to be called if this object is the being edited
  1315. if(m_fInEdit)
  1316. return TRUE;
  1317. //find the item in the list
  1318. int nIndex = FindItemPidl(pidlOld);
  1319. if(-1 != nIndex)
  1320. {
  1321. BOOL fReturn;
  1322. LVITEM lvItem;
  1323. ZeroMemory(&lvItem, sizeof(lvItem));
  1324. lvItem.mask = LVIF_PARAM;
  1325. lvItem.iItem = nIndex;
  1326. ListView_GetItem(m_hwndList, &lvItem);
  1327. m_pPidlMgr->Delete((LPITEMIDLIST)lvItem.lParam);
  1328. ZeroMemory(&lvItem, sizeof(lvItem));
  1329. lvItem.mask = LVIF_PARAM;
  1330. lvItem.iItem = nIndex;
  1331. lvItem.lParam = (LPARAM)m_pPidlMgr->Copy(pidlNew);
  1332. fReturn = ListView_SetItem(m_hwndList, &lvItem);
  1333. ListView_Update(m_hwndList, nIndex);
  1334. return fReturn;
  1335. }
  1336. return FALSE;
  1337. }
  1338. /**************************************************************************
  1339. CShellView::GetPidl()
  1340. **************************************************************************/
  1341. LPITEMIDLIST CShellView::GetPidl()
  1342. {
  1343. return m_psfParent->CreateFQPidl(NULL);
  1344. }
  1345. /**************************************************************************
  1346. CShellView::GetFQPidl()
  1347. **************************************************************************/
  1348. LPITEMIDLIST CShellView::GetFQPidl()
  1349. {
  1350. return m_psfParent->CreateFQPidl(NULL);
  1351. }
  1352. /**************************************************************************
  1353. CShellView::FindItemPidl()
  1354. **************************************************************************/
  1355. int CShellView::FindItemPidl(LPCITEMIDLIST pidl)
  1356. {
  1357. LVITEM lvItem;
  1358. ZeroMemory(&lvItem, sizeof(lvItem));
  1359. lvItem.mask = LVIF_PARAM;
  1360. for(lvItem.iItem = 0; ListView_GetItem(m_hwndList, &lvItem); lvItem.iItem++)
  1361. {
  1362. LPITEMIDLIST pidlFound = (LPITEMIDLIST)lvItem.lParam;
  1363. HRESULT hr = m_psfParent->CompareIDs(0, pidl, pidlFound);
  1364. if(SUCCEEDED(hr) && 0 == HRESULT_CODE(hr))
  1365. {
  1366. //we found the item
  1367. return lvItem.iItem;
  1368. }
  1369. }
  1370. return -1;
  1371. }
  1372. /**************************************************************************
  1373. CShellView::MarkItemsAsCut()
  1374. Marks the items as cut.
  1375. **************************************************************************/
  1376. VOID CShellView::MarkItemsAsCut(LPCITEMIDLIST *aPidls, UINT uItemCount)
  1377. {
  1378. UINT i;
  1379. for(i = 0; i < uItemCount; i++)
  1380. {
  1381. LPITEMIDLIST pidlTemp = m_pPidlMgr->GetLastItem(aPidls[i]);
  1382. int nIndex = FindItemPidl(pidlTemp);
  1383. if(nIndex != -1)
  1384. {
  1385. ListView_SetItemState(m_hwndList, nIndex, LVIS_CUT, LVIS_CUT);
  1386. }
  1387. }
  1388. }
  1389. /**************************************************************************
  1390. CShellView::EditItem()
  1391. **************************************************************************/
  1392. VOID CShellView::EditItem(LPCITEMIDLIST pidl)
  1393. {
  1394. int i;
  1395. i = FindItemPidl(pidl);
  1396. if(-1 != i)
  1397. {
  1398. SetFocus(m_hwndList);
  1399. //put the ListView into edit mode
  1400. ListView_EditLabel(m_hwndList, i);
  1401. }
  1402. }
  1403. /**************************************************************************
  1404. CShellView::UpdateData()
  1405. **************************************************************************/
  1406. VOID CShellView::UpdateData(LPCITEMIDLIST pidl)
  1407. {
  1408. int i;
  1409. i = FindItemPidl(pidl);
  1410. if(-1 != i)
  1411. {
  1412. LVITEM lvItem;
  1413. ZeroMemory(&lvItem, sizeof(lvItem));
  1414. lvItem.mask = LVIF_PARAM;
  1415. lvItem.iItem = i;
  1416. ListView_GetItem(m_hwndList, &lvItem);
  1417. m_pPidlMgr->Delete((LPITEMIDLIST)lvItem.lParam);
  1418. ZeroMemory(&lvItem, sizeof(lvItem));
  1419. lvItem.mask = LVIF_PARAM;
  1420. lvItem.iItem = i;
  1421. lvItem.lParam = (LPARAM)m_pPidlMgr->Copy(pidl);
  1422. ListView_SetItem(m_hwndList, &lvItem);
  1423. ListView_Update(m_hwndList, i);
  1424. }
  1425. }
  1426. /**************************************************************************
  1427. CShellView::OnViewLarge()
  1428. **************************************************************************/
  1429. LRESULT CShellView::OnViewLarge(VOID)
  1430. {
  1431. m_FolderSettings.ViewMode = FVM_ICON;
  1432. DWORD dwStyle = GetWindowLong(m_hwndList, GWL_STYLE);
  1433. dwStyle &= ~LVS_TYPEMASK;
  1434. dwStyle |= LVS_ICON;
  1435. SetWindowLong(m_hwndList, GWL_STYLE, dwStyle);
  1436. return 0;
  1437. }
  1438. /**************************************************************************
  1439. CShellView::OnViewSmall()
  1440. **************************************************************************/
  1441. LRESULT CShellView::OnViewSmall(VOID)
  1442. {
  1443. m_FolderSettings.ViewMode = FVM_SMALLICON;
  1444. DWORD dwStyle = GetWindowLong(m_hwndList, GWL_STYLE);
  1445. dwStyle &= ~LVS_TYPEMASK;
  1446. dwStyle |= LVS_SMALLICON;
  1447. SetWindowLong(m_hwndList, GWL_STYLE, dwStyle);
  1448. return 0;
  1449. }
  1450. /**************************************************************************
  1451. CShellView::OnViewList()
  1452. **************************************************************************/
  1453. LRESULT CShellView::OnViewList(VOID)
  1454. {
  1455. m_FolderSettings.ViewMode = FVM_LIST;
  1456. DWORD dwStyle = GetWindowLong(m_hwndList, GWL_STYLE);
  1457. dwStyle &= ~LVS_TYPEMASK;
  1458. dwStyle |= LVS_LIST;
  1459. SetWindowLong(m_hwndList, GWL_STYLE, dwStyle);
  1460. return 0;
  1461. }
  1462. /**************************************************************************
  1463. CShellView::OnViewDetails()
  1464. **************************************************************************/
  1465. LRESULT CShellView::OnViewDetails(VOID)
  1466. {
  1467. m_FolderSettings.ViewMode = FVM_DETAILS;
  1468. DWORD dwStyle = GetWindowLong(m_hwndList, GWL_STYLE);
  1469. dwStyle &= ~LVS_TYPEMASK;
  1470. dwStyle |= LVS_REPORT;
  1471. SetWindowLong(m_hwndList, GWL_STYLE, dwStyle);
  1472. return 0;
  1473. }