Source code of Windows XP (NT5)
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.

1412 lines
27 KiB

  1. /*++
  2. Implements IShellView.
  3. --*/
  4. #include <windows.h>
  5. #include <windowsx.h>
  6. #include <objbase.h>
  7. #include <shlobj.h>
  8. #include <docobj.h>
  9. #include <shellapi.h>
  10. #include "pstore.h"
  11. #include "shfolder.h"
  12. #include "shview.h"
  13. #include "guid.h"
  14. #include "resource.h"
  15. #include "tools.h"
  16. #include "utility.h"
  17. #include "enumid.h"
  18. #include "listu.h"
  19. extern HINSTANCE g_hInst;
  20. extern LONG g_DllRefCount;
  21. BOOL
  22. AddListItem(
  23. HWND hWnd,
  24. DWORD dwType,
  25. PST_KEY KeyType,
  26. LPCWSTR szName,
  27. LPITEMIDLIST pidl
  28. );
  29. #define TOOLBAR_ID (L"TBar")
  30. #define INITIAL_COLUMN_POS 100
  31. MYTOOLINFO g_Buttons[] =
  32. {
  33. IDM_MESSAGE1, 0, IDS_TB_MESSAGE1, IDS_MI_MESSAGE1, TBSTATE_ENABLED, TBSTYLE_BUTTON,
  34. IDM_MESSAGE2, 0, IDS_TB_MESSAGE2, IDS_MI_MESSAGE2, TBSTATE_ENABLED, TBSTYLE_BUTTON,
  35. -1, 0, 0, 0, 0,
  36. };
  37. CShellView::CShellView(
  38. CShellFolder *pFolder,
  39. LPCITEMIDLIST pidl
  40. )
  41. {
  42. m_hMenu = NULL;
  43. ZeroMemory(&m_MenuWidths, sizeof(m_MenuWidths));
  44. m_nColumn1 = INITIAL_COLUMN_POS;
  45. m_nColumn2 = INITIAL_COLUMN_POS;
  46. m_pSFParent = pFolder;
  47. if(m_pSFParent)
  48. m_pSFParent->AddRef();
  49. m_pidl = (LPITEMIDLIST)pidl;
  50. m_uState = SVUIA_DEACTIVATE;
  51. m_ObjRefCount = 1;
  52. InterlockedIncrement(&g_DllRefCount);
  53. }
  54. CShellView::~CShellView()
  55. {
  56. if(m_pSFParent)
  57. m_pSFParent->Release();
  58. InterlockedDecrement(&g_DllRefCount);
  59. }
  60. STDMETHODIMP
  61. CShellView::QueryInterface(
  62. REFIID riid,
  63. LPVOID *ppReturn
  64. )
  65. /*++
  66. IUnknown::QueryInterface
  67. --*/
  68. {
  69. *ppReturn = NULL;
  70. if(IsEqualIID(riid, IID_IUnknown))
  71. *ppReturn = (IUnknown*)(IShellView*)this;
  72. else if(IsEqualIID(riid, IID_IOleWindow))
  73. *ppReturn = (IOleWindow*)this;
  74. else if(IsEqualIID(riid, IID_IShellView))
  75. *ppReturn = (CShellView*)this;
  76. else if(IsEqualIID(riid, IID_IOleCommandTarget))
  77. *ppReturn = (IOleCommandTarget*)this;
  78. if(*ppReturn == NULL)
  79. return E_NOINTERFACE;
  80. (*(LPUNKNOWN*)ppReturn)->AddRef();
  81. return S_OK;
  82. }
  83. STDMETHODIMP_(DWORD)
  84. CShellView::AddRef()
  85. /*++
  86. IUnknown::AddRef
  87. --*/
  88. {
  89. return InterlockedIncrement(&m_ObjRefCount);
  90. }
  91. STDMETHODIMP_(DWORD)
  92. CShellView::Release()
  93. /*++
  94. IUnknown::Release
  95. --*/
  96. {
  97. LONG lDecremented = InterlockedDecrement(&m_ObjRefCount);
  98. if(lDecremented == 0)
  99. delete this;
  100. return lDecremented;
  101. }
  102. STDMETHODIMP
  103. CShellView::GetWindow(
  104. HWND *phWnd
  105. )
  106. /*++
  107. IOleWindow::GetWindow
  108. --*/
  109. {
  110. *phWnd = m_hWnd;
  111. return S_OK;
  112. }
  113. STDMETHODIMP
  114. CShellView::ContextSensitiveHelp(
  115. BOOL fEnterMode
  116. )
  117. /*++
  118. Inherited from IOleWindow::ContextSensitiveHelp.
  119. --*/
  120. {
  121. return E_NOTIMPL;
  122. }
  123. STDMETHODIMP
  124. CShellView::QueryStatus(
  125. const GUID *pguidCmdGroup,
  126. ULONG cCmds,
  127. OLECMD prgCmds[],
  128. OLECMDTEXT *pCmdText
  129. )
  130. /*++
  131. IOleCommandTarget::QueryStatus
  132. --*/
  133. {
  134. ULONG i;
  135. //
  136. // only process the commands for our command group
  137. //
  138. if(pguidCmdGroup && (*pguidCmdGroup != CLSID_CmdGrp))
  139. return OLECMDERR_E_UNKNOWNGROUP;
  140. //
  141. // make sure prgCmds is not NULL
  142. //
  143. if(prgCmds == NULL)
  144. return E_POINTER;
  145. //
  146. // run through all of the commands and supply the correct information
  147. //
  148. for(i = 0; i < cCmds;i++)
  149. {
  150. switch(prgCmds[i].cmdID)
  151. {
  152. case IDM_MESSAGE1:
  153. prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  154. break;
  155. case IDM_MESSAGE2:
  156. prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  157. break;
  158. }
  159. }
  160. return S_OK;
  161. }
  162. STDMETHODIMP
  163. CShellView::Exec(
  164. const GUID *pguidCmdGroup,
  165. DWORD nCmdID,
  166. DWORD nCmdExecOpt,
  167. VARIANTARG *pvaIn,
  168. VARIANTARG *pvaOut
  169. )
  170. /*++
  171. IOleCommandTarget::Exec
  172. --*/
  173. {
  174. //
  175. // only process the commands for our command group
  176. //
  177. if(pguidCmdGroup && (*pguidCmdGroup == CLSID_CmdGrp))
  178. {
  179. OnCommand(nCmdID, 0, NULL);
  180. return S_OK;
  181. }
  182. return OLECMDERR_E_UNKNOWNGROUP;
  183. }
  184. STDMETHODIMP
  185. CShellView::TranslateAccelerator(
  186. LPMSG pMsg
  187. )
  188. /*++
  189. Same as the IOleInPlaceFrame::TranslateAccelerator, but will be
  190. never called because we don't support EXEs (i.e., the explorer has
  191. the message loop). This member function is defined here for possible
  192. future enhancement.
  193. --*/
  194. {
  195. return E_NOTIMPL;
  196. }
  197. STDMETHODIMP
  198. CShellView::EnableModeless(
  199. BOOL fEnable
  200. )
  201. /*++
  202. Same as the IOleInPlaceFrame::EnableModeless.
  203. --*/
  204. {
  205. return E_NOTIMPL;
  206. }
  207. STDMETHODIMP
  208. CShellView::UIActivate(
  209. UINT uState
  210. )
  211. /*++
  212. IShellView::UIActivate
  213. --*/
  214. {
  215. //
  216. // don't do anything if the state isn't really changing
  217. //
  218. if(m_uState == uState)
  219. return S_OK;
  220. //
  221. // Always do this because we will cause problems if we are going from
  222. // SVUIA_ACTIVATE_FOCUS to SVUIA_ACTIVATE_NOFOCUS or vice versa.
  223. //
  224. m_uState = SVUIA_DEACTIVATE;
  225. m_pShellBrowser->SetMenuSB(NULL, NULL, NULL);
  226. if(m_hMenu) {
  227. DestroyMenu(m_hMenu);
  228. m_hMenu = NULL;
  229. }
  230. //
  231. // only do this if we are active
  232. //
  233. if(uState != SVUIA_DEACTIVATE) {
  234. m_uState = uState;
  235. //
  236. // update the Explorer's menu
  237. //
  238. if(m_hMenu == NULL)
  239. m_hMenu = CreateMenu();
  240. if(m_hMenu) {
  241. MENUITEMINFO mii;
  242. TCHAR szText[MAX_PATH];
  243. m_pShellBrowser->InsertMenusSB(m_hMenu, &m_MenuWidths);
  244. //
  245. // get the menu item's text
  246. //
  247. LoadString(g_hInst, IDS_MI_REGISTRY, szText, sizeof(szText));
  248. //
  249. // build our menu
  250. //
  251. ZeroMemory(&mii, sizeof(mii));
  252. mii.cbSize = sizeof(mii);
  253. mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
  254. mii.fType = MFT_STRING;
  255. mii.fState = MFS_ENABLED;
  256. mii.dwTypeData = szText;
  257. mii.hSubMenu = BuildMenu();
  258. //
  259. // insert our menu
  260. //
  261. InsertMenuItem(m_hMenu, FCIDM_MENU_HELP, FALSE, &mii);
  262. m_pShellBrowser->SetMenuSB(m_hMenu, NULL, m_hWnd);
  263. }
  264. //
  265. // TODO: update the status bar
  266. //
  267. /*
  268. TCHAR szName[MAX_PATH];
  269. LoadString(g_hInst, IDS_PSTORE_TITLE, szName, sizeof(szName));
  270. m_pSFParent->GetPidlFullText(m_pidl, szName + lstrlen(szName), sizeof(szName) - lstrlen(szName));
  271. LRESULT lResult;
  272. int nPartArray[1] = {-1};
  273. //set the number of parts
  274. m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, 1, (LPARAM)nPartArray, &lResult);
  275. //set the text for the parts
  276. m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 0, (LPARAM)szName, &lResult);
  277. */
  278. }
  279. return S_OK;
  280. }
  281. HMENU
  282. CShellView::BuildMenu(
  283. void
  284. )
  285. {
  286. HMENU hSubMenu = CreatePopupMenu();
  287. if(hSubMenu == NULL)
  288. return NULL;
  289. TCHAR szText[MAX_PATH];
  290. MENUITEMINFO mii;
  291. int nButtons, i;
  292. //
  293. // get the number of items in our global array
  294. //
  295. for(nButtons = 0; g_Buttons[nButtons].idCommand != -1; nButtons++) {
  296. ;
  297. }
  298. //
  299. // add the menu items
  300. //
  301. for(i = 0; i < nButtons; i++) {
  302. LoadString(g_hInst, g_Buttons[i].idMenuString, szText, sizeof(szText));
  303. ZeroMemory(&mii, sizeof(mii));
  304. mii.cbSize = sizeof(mii);
  305. mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  306. if(TBSTYLE_SEP != g_Buttons[i].bStyle) {
  307. mii.fType = MFT_STRING;
  308. mii.fState = MFS_ENABLED;
  309. mii.dwTypeData = szText;
  310. mii.wID = g_Buttons[i].idCommand;
  311. } else {
  312. mii.fType = MFT_SEPARATOR;
  313. }
  314. //
  315. // tack this item onto the end of the menu
  316. //
  317. InsertMenuItem(hSubMenu, (UINT)-1, TRUE, &mii);
  318. }
  319. //
  320. // add a couple more that aren't in the button array
  321. //
  322. LoadString(g_hInst, IDS_MI_VIEW_ISTB, szText, sizeof(szText));
  323. ZeroMemory(&mii, sizeof(mii));
  324. mii.cbSize = sizeof(mii);
  325. mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  326. mii.fType = MFT_STRING;
  327. mii.fState = MFS_ENABLED;
  328. mii.dwTypeData = szText;
  329. mii.wID = IDM_VIEW_ISTB;
  330. //
  331. // tack this item onto the end of the menu
  332. //
  333. InsertMenuItem(hSubMenu, (UINT)-1, TRUE, &mii);
  334. LoadString(g_hInst, IDS_MI_VIEW_IETB, szText, sizeof(szText));
  335. ZeroMemory(&mii, sizeof(mii));
  336. mii.cbSize = sizeof(mii);
  337. mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  338. mii.fType = MFT_STRING;
  339. mii.fState = MFS_ENABLED;
  340. mii.dwTypeData = szText;
  341. mii.wID = IDM_VIEW_IETB;
  342. //
  343. // tack this item onto the end of the menu
  344. //
  345. InsertMenuItem(hSubMenu, (UINT)-1, TRUE, &mii);
  346. return hSubMenu;
  347. }
  348. STDMETHODIMP
  349. CShellView::Refresh(
  350. void
  351. )
  352. /*++
  353. IShellView::Refresh
  354. --*/
  355. {
  356. //
  357. // empty the list
  358. //
  359. ListView_DeleteAllItems(m_hwndList);
  360. //
  361. // refill the list
  362. //
  363. FillList();
  364. return S_OK;
  365. }
  366. STDMETHODIMP
  367. CShellView::CreateViewWindow(
  368. LPSHELLVIEW pPrevView,
  369. LPCFOLDERSETTINGS lpfs,
  370. LPSHELLBROWSER psb,
  371. LPRECT prcView,
  372. HWND *phWnd
  373. )
  374. /*++
  375. CreateViewWindow creates a view window. This can be either the right pane
  376. of the Explorer or the client window of a folder window.
  377. --*/
  378. {
  379. WNDCLASS wc;
  380. *phWnd = NULL;
  381. //
  382. // if our window class has not been registered, then do so
  383. //
  384. if(!GetClassInfo(g_hInst, NS_CLASS_NAME, &wc)) {
  385. ZeroMemory(&wc, sizeof(wc));
  386. wc.style = CS_HREDRAW | CS_VREDRAW;
  387. wc.lpfnWndProc = WndProc;
  388. wc.cbClsExtra = 0;
  389. wc.cbWndExtra = 0;
  390. wc.hInstance = g_hInst;
  391. wc.hIcon = NULL;
  392. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  393. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  394. wc.lpszMenuName = NULL;
  395. wc.lpszClassName = NS_CLASS_NAME;
  396. if(!RegisterClass(&wc))
  397. return E_FAIL;
  398. }
  399. //
  400. // set up the member variables
  401. //
  402. m_pShellBrowser = psb;
  403. m_FolderSettings.ViewMode = lpfs->ViewMode;
  404. m_FolderSettings.fFlags = lpfs->fFlags;
  405. //
  406. // get our parent window
  407. //
  408. m_pShellBrowser->GetWindow(&m_hwndParent);
  409. GetSettings();
  410. *phWnd = CreateWindowEx( 0,
  411. NS_CLASS_NAME,
  412. NULL,
  413. WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
  414. prcView->left,
  415. prcView->top,
  416. prcView->right - prcView->left,
  417. prcView->bottom - prcView->top,
  418. m_hwndParent,
  419. NULL,
  420. g_hInst,
  421. (LPVOID)this);
  422. if(*phWnd == NULL)
  423. return E_FAIL;
  424. //
  425. // addref the IShellBrowser interface to allow communication with Explorer
  426. //
  427. m_pShellBrowser->AddRef();
  428. return S_OK;
  429. }
  430. STDMETHODIMP
  431. CShellView::DestroyViewWindow(
  432. void
  433. )
  434. /*++
  435. The Explorer calls this method when a folder window or the Explorer
  436. is being closed.
  437. --*/
  438. {
  439. if(m_hMenu)
  440. DestroyMenu(m_hMenu);
  441. DestroyWindow(m_hWnd);
  442. //
  443. // release the shell browser object
  444. //
  445. m_pShellBrowser->Release();
  446. return S_OK;
  447. }
  448. STDMETHODIMP
  449. CShellView::GetCurrentInfo(
  450. LPFOLDERSETTINGS lpfs
  451. )
  452. /*++
  453. The Explorer uses GetCurrentInfo to query the view for standard settings.
  454. --*/
  455. {
  456. // TODO, check proper approach.
  457. *lpfs = m_FolderSettings;
  458. // lpfs->ViewMode = m_FolderSettings.ViewMode;
  459. // lpfs->fFlags = m_FolderSettings.fFlags;
  460. return NOERROR;
  461. }
  462. STDMETHODIMP
  463. CShellView::AddPropertySheetPages(
  464. DWORD dwReserved,
  465. LPFNADDPROPSHEETPAGE lpfn,
  466. LPARAM lParam
  467. )
  468. /*++
  469. The Explorer calls this method when it is opening the View.Options...
  470. property sheet. Views can add pages by creating them and calling the
  471. callback function with the page handles.
  472. --*/
  473. {
  474. OutputDebugStringA("IShellView::AddPropertySheetPages\n");
  475. return E_NOTIMPL;
  476. }
  477. STDMETHODIMP
  478. CShellView::SaveViewState(
  479. void
  480. )
  481. /*++
  482. IShellView::SaveViewState
  483. --*/
  484. {
  485. SaveSettings();
  486. return S_OK;
  487. }
  488. STDMETHODIMP
  489. CShellView::SelectItem(
  490. LPCITEMIDLIST pidlItem,
  491. UINT uFlags
  492. )
  493. /*++
  494. IShellView::SelectItem
  495. --*/
  496. {
  497. return E_NOTIMPL;
  498. }
  499. STDMETHODIMP
  500. CShellView::GetItemObject(
  501. UINT uItem,
  502. REFIID riid,
  503. LPVOID *ppvOut
  504. )
  505. /*++
  506. Used by the common dialogs to get the selected items from the view.
  507. --*/
  508. {
  509. return E_NOTIMPL;
  510. }
  511. LRESULT
  512. CALLBACK
  513. CShellView::WndProc(
  514. HWND hWnd,
  515. UINT uMessage,
  516. WPARAM wParam,
  517. LPARAM lParam
  518. )
  519. {
  520. CShellView *pThis = (CShellView*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  521. switch (uMessage)
  522. {
  523. case WM_NCCREATE:
  524. {
  525. LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
  526. pThis = (CShellView*)(lpcs->lpCreateParams);
  527. SetWindowLongPtr(hWnd, GWLP_USERDATA, (LPARAM)pThis);
  528. //set the window handle
  529. pThis->m_hWnd = hWnd;
  530. break;
  531. }
  532. case WM_SIZE:
  533. return pThis->OnSize(LOWORD(lParam), HIWORD(lParam));
  534. case WM_CREATE:
  535. return pThis->OnCreate();
  536. case WM_SETFOCUS:
  537. return pThis->OnSetFocus();
  538. case WM_ACTIVATE:
  539. return pThis->OnActivate(wParam, lParam);
  540. case WM_COMMAND:
  541. return pThis->OnCommand( GET_WM_COMMAND_ID(wParam, lParam),
  542. GET_WM_COMMAND_CMD(wParam, lParam),
  543. GET_WM_COMMAND_HWND(wParam, lParam));
  544. case WM_INITMENUPOPUP:
  545. return pThis->UpdateMenu((HMENU)wParam);
  546. case WM_NOTIFY:
  547. return pThis->OnNotify((UINT)wParam, (LPNMHDR)lParam);
  548. }
  549. return DefWindowProc(hWnd, uMessage, wParam, lParam);
  550. }
  551. LRESULT
  552. CShellView::OnSetFocus(
  553. void
  554. )
  555. {
  556. //
  557. // tell the browser we got the focus
  558. //
  559. m_pShellBrowser->OnViewWindowActive(this);
  560. return 0;
  561. }
  562. LRESULT
  563. CShellView::OnActivate(
  564. WPARAM wParam,
  565. LPARAM lParam
  566. )
  567. {
  568. //
  569. // tell the browser we got the focus
  570. //
  571. if(wParam)
  572. m_pShellBrowser->OnViewWindowActive(this);
  573. return 0;
  574. }
  575. LRESULT
  576. CShellView::OnCommand(
  577. DWORD dwCmdID,
  578. DWORD dwCmd,
  579. HWND hwndCmd
  580. )
  581. {
  582. switch(dwCmdID)
  583. {
  584. case IDM_MESSAGE1:
  585. MessageBox(m_hWnd, TEXT("Message 1 was selected"), TEXT("Notice"), MB_OK | MB_ICONEXCLAMATION);
  586. break;
  587. case IDM_MESSAGE2:
  588. MessageBox(m_hWnd, TEXT("Message 2 was selected"), TEXT("Notice"), MB_OK | MB_ICONEXCLAMATION);
  589. break;
  590. case IDM_VIEW_ISTB:
  591. m_bShowISTB = ! m_bShowISTB;
  592. UpdateToolbar();
  593. break;
  594. case IDM_VIEW_IETB:
  595. m_bShowIETB = ! m_bShowIETB;
  596. UpdateToolbar();
  597. break;
  598. }
  599. return 0;
  600. }
  601. HRESULT
  602. CShellView::SaveSettings(
  603. void
  604. )
  605. /*++
  606. Called by IShellView::SaveViewState to store the relevant setting data
  607. to the browser stream.
  608. --*/
  609. {
  610. HRESULT hr;
  611. LPSTREAM pStream;
  612. hr = m_pShellBrowser->GetViewStateStream(STGM_WRITE, &pStream);
  613. if(SUCCEEDED(hr))
  614. {
  615. ULONG uWritten;
  616. pStream->Write(&m_bShowISTB, sizeof(m_bShowISTB), &uWritten);
  617. pStream->Write(&m_bShowIETB, sizeof(m_bShowIETB), &uWritten);
  618. pStream->Write(&m_nColumn1, sizeof(m_nColumn1), &uWritten);
  619. pStream->Write(&m_nColumn2, sizeof(m_nColumn2), &uWritten);
  620. pStream->Release();
  621. }
  622. return hr;
  623. }
  624. HRESULT
  625. CShellView::GetSettings(
  626. void
  627. )
  628. {
  629. HRESULT hr;
  630. LPSTREAM pStream;
  631. hr = m_pShellBrowser->GetViewStateStream(STGM_READ, &pStream);
  632. if(SUCCEEDED(hr)) {
  633. ULONG uRead;
  634. if(S_OK != pStream->Read(&m_bShowISTB, sizeof(m_bShowISTB), &uRead))
  635. m_bShowISTB = FALSE;
  636. if(S_OK != pStream->Read(&m_bShowIETB, sizeof(m_bShowIETB), &uRead))
  637. m_bShowIETB = FALSE;
  638. if(S_OK != pStream->Read(&m_nColumn1, sizeof(m_nColumn1), &uRead))
  639. m_nColumn1 = INITIAL_COLUMN_POS;
  640. if(S_OK != pStream->Read(&m_nColumn2, sizeof(m_nColumn2), &uRead))
  641. m_nColumn2 = INITIAL_COLUMN_POS;
  642. pStream->Release();
  643. }
  644. return hr;
  645. }
  646. LRESULT
  647. CShellView::UpdateMenu(
  648. HMENU hMenu
  649. )
  650. {
  651. return 0;
  652. }
  653. void
  654. CShellView::UpdateToolbar()
  655. {
  656. // nothing to update yet
  657. }
  658. LRESULT
  659. CShellView::OnNotify(
  660. UINT CtlID,
  661. LPNMHDR pNotify
  662. )
  663. {
  664. LPNM_LISTVIEW pNotifyLV = (LPNM_LISTVIEW)pNotify;
  665. LV_DISPINFO *pNotifyDI = (LV_DISPINFO *)pNotify;
  666. LPTBNOTIFY pNotifyTB = (LPTBNOTIFY)pNotify;
  667. LPTOOLTIPTEXT pNotifyTT = (LPTOOLTIPTEXT)pNotify;
  668. switch(pNotify->code)
  669. {
  670. //
  671. // HDN_BEGINTRACK
  672. // HDN_DIVIDERDBLCLICK
  673. // HDN_ENDTRACK
  674. // HDN_ITEMCHANGED
  675. // HDN_ITEMCHANGING
  676. // HDN_ITEMCLICK
  677. // HDN_ITEMDBLCLICK
  678. // HDN_TRACK
  679. //
  680. case HDN_ENDTRACK:
  681. {
  682. m_nColumn1 = ListView_GetColumnWidth(m_hwndList, 0);
  683. m_nColumn2 = ListView_GetColumnWidth(m_hwndList, 1);
  684. break;
  685. }
  686. //
  687. // LVN_BEGINDRAG
  688. // LVN_BEGINLABELEDIT
  689. // LVN_BEGINRDRAG
  690. // LVN_COLUMNCLICK
  691. // LVN_DELETEALLITEMS
  692. // LVN_DELETEITEM
  693. // LVN_ENDLABELEDIT
  694. // LVN_GETDISPINFO
  695. // LVN_INSERTITEM
  696. // LVN_ITEMCHANGED
  697. // LVN_ITEMCHANGING
  698. // LVN_KEYDOWN
  699. // LVN_SETDISPINFO
  700. //
  701. case LVN_DELETEITEM:
  702. {
  703. LPITEMIDLIST pidl = (LPITEMIDLIST)(pNotifyLV->lParam);
  704. //
  705. // free the memory for the pidl associated with this item.
  706. //
  707. if(pidl != NULL)
  708. FreePidl(pidl);
  709. break;
  710. }
  711. // NM_CLICK
  712. // NM_DBLCLK
  713. // NM_KILLFOCUS
  714. // NM_LISTVIEW
  715. // NM_OUTOFMEMORY
  716. // NM_RCLICK
  717. // NM_RDBLCLK
  718. // NM_RETURN
  719. // NM_SETFOCUS
  720. // NM_TREEVIEW
  721. // NM_UPDOWN
  722. //
  723. case NM_RETURN:
  724. case NM_DBLCLK:
  725. {
  726. UINT wFlags = SBSP_RELATIVE | SBSP_DEFMODE;
  727. int iItem = -1;
  728. //
  729. // if we are in explorer mode, start out in DEFBROWSER mode,
  730. // otherwise, start in NEWBROWSER mode.
  731. //
  732. HWND hwnd = NULL;
  733. m_pShellBrowser->GetControlWindow(FCW_TREE, &hwnd);
  734. if(hwnd != NULL) {
  735. wFlags |= SBSP_DEFBROWSER;
  736. } else {
  737. wFlags |= SBSP_NEWBROWSER;
  738. }
  739. //
  740. // loop through all the selected items.
  741. // TODO: if more than two are selected, we only get to view
  742. // two.
  743. //
  744. do {
  745. LV_ITEM item;
  746. iItem = ListView_GetNextItem(m_hwndList, iItem, LVNI_SELECTED | LVNI_ALL);
  747. ZeroMemory(&item, sizeof(item));
  748. item.mask = LVIF_PARAM;
  749. item.iItem = iItem;
  750. if(!ListView_GetItem(m_hwndList, &item))
  751. break;
  752. LPCITEMIDLIST pidl = (LPCITEMIDLIST)(item.lParam);
  753. if(pidl != NULL) {
  754. //
  755. // don't browse into items.
  756. //
  757. if(GetLastPidlType(pidl) > PIDL_TYPE_SUBTYPE)
  758. break;
  759. m_pShellBrowser->BrowseObject(pidl, wFlags);
  760. }
  761. //
  762. // if multiple items selected, bring up a new browser
  763. //
  764. wFlags &= ~SBSP_DEFBROWSER;
  765. wFlags |= SBSP_NEWBROWSER;
  766. } while (iItem != -1);
  767. }
  768. //
  769. // TBN_BEGINADJUST
  770. // TBN_BEGINDRAG
  771. // TBN_CUSTHELP
  772. // TBN_ENDADJUST
  773. // TBN_ENDDRAG
  774. // TBN_GETBUTTONINFO
  775. // TBN_QUERYDELETE
  776. // TBN_QUERYINSERT
  777. // TBN_RESET
  778. // TBN_TOOLBARCHANGE
  779. //
  780. case TBN_BEGINDRAG:
  781. default:
  782. return 0;
  783. }
  784. return 0;
  785. }
  786. LRESULT
  787. CShellView::OnSize(
  788. WORD wWidth,
  789. WORD wHeight
  790. )
  791. {
  792. //
  793. // resize the ListView to fit our window
  794. //
  795. if(m_hwndList)
  796. MoveWindow(m_hwndList, 0, 0, wWidth, wHeight, TRUE);
  797. return 0;
  798. }
  799. LRESULT
  800. CShellView::OnCreate(
  801. void
  802. )
  803. {
  804. //
  805. // create the ListView
  806. //
  807. if(CreateList())
  808. {
  809. if(InitList())
  810. {
  811. FillList();
  812. }
  813. }
  814. return 0;
  815. }
  816. BOOL
  817. CShellView::CreateList(
  818. void
  819. )
  820. {
  821. DWORD dwStyle;
  822. //
  823. // fetch the prior listview style and use
  824. // that as the new listview style.
  825. //
  826. switch (m_FolderSettings.ViewMode) {
  827. case FVM_ICON:
  828. dwStyle = LVS_ICON;
  829. break;
  830. case FVM_SMALLICON:
  831. dwStyle = LVS_SMALLICON;
  832. break;
  833. case FVM_LIST:
  834. dwStyle = LVS_LIST;
  835. break;
  836. case FVM_DETAILS:
  837. dwStyle = LVS_REPORT;
  838. break;
  839. default:
  840. dwStyle = LVS_ICON;
  841. break;
  842. }
  843. m_hwndList = CreateWindowEx(
  844. WS_EX_CLIENTEDGE,
  845. WC_LISTVIEW,
  846. NULL,
  847. WS_TABSTOP |
  848. WS_VISIBLE |
  849. WS_CHILD |
  850. WS_BORDER |
  851. LVS_SORTASCENDING |
  852. dwStyle |
  853. LVS_NOSORTHEADER |
  854. 0,
  855. 0,
  856. 0,
  857. 0,
  858. 0,
  859. m_hWnd,
  860. (HMENU)ID_LISTVIEW,
  861. g_hInst,
  862. NULL
  863. );
  864. return (BOOL)(NULL != m_hwndList);
  865. }
  866. BOOL
  867. CShellView::InitList(
  868. void
  869. )
  870. {
  871. LV_COLUMN lvColumn;
  872. HIMAGELIST himlSmall;
  873. HIMAGELIST himlLarge;
  874. RECT rc;
  875. TCHAR szString[MAX_PATH];
  876. //
  877. // empty the list
  878. //
  879. ListView_DeleteAllItems(m_hwndList);
  880. //
  881. // initialize the columns
  882. //
  883. lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  884. lvColumn.fmt = LVCFMT_LEFT;
  885. lvColumn.pszText = szString;
  886. lvColumn.cx = m_nColumn1;
  887. LoadString(g_hInst, IDS_COLUMN1, szString, sizeof(szString));
  888. ListView_InsertColumn(m_hwndList, 0, &lvColumn);
  889. GetClientRect(m_hWnd, &rc);
  890. lvColumn.cx = m_nColumn2;
  891. LoadString(g_hInst, IDS_COLUMN2, szString, sizeof(szString));
  892. ListView_InsertColumn(m_hwndList, 1, &lvColumn);
  893. int cxSmall;
  894. int cySmall;
  895. int cxLarge;
  896. int cyLarge;
  897. SHFILEINFO sfi;
  898. HIMAGELIST himl;
  899. //
  900. // get large and small icon size info from shell
  901. //
  902. himl = (HIMAGELIST)SHGetFileInfo(
  903. NULL,
  904. 0,
  905. &sfi,
  906. sizeof(sfi),
  907. SHGFI_LARGEICON | SHGFI_SYSICONINDEX
  908. );
  909. if(!ImageList_GetIconSize(himl, &cxLarge, &cyLarge)) {
  910. cxLarge = GetSystemMetrics(SM_CXICON);
  911. cyLarge = GetSystemMetrics(SM_CYICON);
  912. }
  913. himl = (HIMAGELIST)SHGetFileInfo(
  914. NULL,
  915. 0,
  916. &sfi,
  917. sizeof(sfi),
  918. SHGFI_SMALLICON | SHGFI_SYSICONINDEX
  919. );
  920. if(!ImageList_GetIconSize(himl, &cxSmall, &cySmall)) {
  921. cxSmall = GetSystemMetrics(SM_CXSMICON);
  922. cySmall = GetSystemMetrics(SM_CYSMICON);
  923. }
  924. //
  925. // Create the full-sized and small icon image lists.
  926. //
  927. himlLarge = ImageList_Create(
  928. cxLarge,
  929. cyLarge,
  930. ILC_COLORDDB | ILC_MASK,
  931. 4, // initial image count
  932. 0
  933. );
  934. himlSmall = ImageList_Create(
  935. cxSmall,
  936. cySmall,
  937. ILC_COLORDDB | ILC_MASK,
  938. 4, // initial image count
  939. 0
  940. );
  941. //
  942. // Add icons to each image list.
  943. // TODO cache icons
  944. //
  945. HICON hIconSmall;
  946. HICON hIconLarge;
  947. // icon 0: Provider icon
  948. hIconSmall = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_PROVIDER), IMAGE_ICON, cxSmall, cySmall, LR_DEFAULTCOLOR | LR_SHARED);
  949. hIconLarge = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_PROVIDER), IMAGE_ICON, cxLarge, cyLarge, LR_DEFAULTCOLOR | LR_SHARED);
  950. ImageList_AddIcon(himlSmall, hIconSmall);
  951. ImageList_AddIcon(himlLarge, hIconLarge);
  952. // icon 1: type icon
  953. hIconSmall = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_FOLDER), IMAGE_ICON, cxSmall, cySmall, LR_DEFAULTCOLOR | LR_SHARED);
  954. hIconLarge = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_FOLDER), IMAGE_ICON, cxLarge, cyLarge, LR_DEFAULTCOLOR | LR_SHARED);
  955. ImageList_AddIcon(himlSmall, hIconSmall);
  956. ImageList_AddIcon(himlLarge, hIconLarge);
  957. // icon 2: item icon
  958. hIconSmall = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_ITEM), IMAGE_ICON, cxSmall, cySmall, LR_DEFAULTCOLOR | LR_SHARED);
  959. hIconLarge = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_ITEM), IMAGE_ICON, cxLarge, cyLarge, LR_DEFAULTCOLOR | LR_SHARED);
  960. ImageList_AddIcon(himlSmall, hIconSmall);
  961. ImageList_AddIcon(himlLarge, hIconLarge);
  962. // icon 3: global type
  963. hIconSmall = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_GLOBAL), IMAGE_ICON, cxSmall, cySmall, LR_DEFAULTCOLOR | LR_SHARED);
  964. hIconLarge = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_GLOBAL), IMAGE_ICON, cxLarge, cyLarge, LR_DEFAULTCOLOR | LR_SHARED);
  965. ImageList_AddIcon(himlSmall, hIconSmall);
  966. ImageList_AddIcon(himlLarge, hIconLarge);
  967. //
  968. // Assign the image lists to the list view control.
  969. //
  970. ListView_SetImageList(m_hwndList, himlLarge, LVSIL_NORMAL);
  971. ListView_SetImageList(m_hwndList, himlSmall, LVSIL_SMALL);
  972. return TRUE;
  973. }
  974. BOOL
  975. CShellView::FillList(
  976. void
  977. )
  978. {
  979. LPENUMIDLIST pEnumIDList;
  980. ULONG ulFetched;
  981. LPITEMIDLIST pidl = NULL;
  982. pEnumIDList = new CEnumIDList(m_pidl, TRUE);
  983. if(pEnumIDList == NULL)
  984. return FALSE;
  985. //
  986. // enumerate the sub folders or items, based on the parent m_pidl.
  987. // note that storage is allocated for the pidlNew, which is a copy
  988. // of the current path + pidl - that storage is later freed during
  989. // the processing of LVN_DELETEITEM
  990. //
  991. while( NOERROR == pEnumIDList->Next(1, &pidl, &ulFetched) ) {
  992. LPCWSTR szText = GetPidlText(pidl);
  993. PST_KEY KeyType = GetPidlKeyType(pidl);
  994. DWORD dwPidlType = GetPidlType(pidl);
  995. //
  996. // make a fully qualified (absolute) pidl
  997. //
  998. // LPITEMIDLIST pidlNew = CopyCatPidl(m_pidl, pidl);
  999. //
  1000. // free pidl associated with Next enumeration
  1001. //
  1002. // FreePidl(pidl);
  1003. //
  1004. // add item with absolute pidl to listview
  1005. //
  1006. AddListItem(m_hwndList, dwPidlType, KeyType, szText, pidl);
  1007. }
  1008. pEnumIDList->Release();
  1009. return TRUE;
  1010. }
  1011. BOOL
  1012. AddListItem(
  1013. HWND hWnd,
  1014. DWORD dwType,
  1015. PST_KEY KeyType,
  1016. LPCWSTR szName,
  1017. LPITEMIDLIST pidl
  1018. )
  1019. /*++
  1020. This function is a temporary hack to support image list add/set data.
  1021. This will be replaced by an Unicode interface that operates on WinNT and
  1022. Win95 in the near future.
  1023. --*/
  1024. {
  1025. LVITEM lvItem;
  1026. int nIndex;
  1027. DWORD dwIconIndex;
  1028. //
  1029. // determine which icon to use.
  1030. // when PST_KEY is not PST_KEY_LOCAL_MACHINE, use a different folder
  1031. // icon at the type and subtype level.
  1032. //
  1033. switch(dwType) {
  1034. case PIDL_TYPE_PROVIDER:
  1035. dwIconIndex = 0;
  1036. break;
  1037. case PIDL_TYPE_TYPE:
  1038. case PIDL_TYPE_SUBTYPE:
  1039. if(KeyType == PST_KEY_CURRENT_USER)
  1040. dwIconIndex = 1;
  1041. else
  1042. dwIconIndex = 3; // global (shared) icon
  1043. break;
  1044. case PIDL_TYPE_ITEM:
  1045. dwIconIndex = 2;
  1046. break;
  1047. default:
  1048. dwIconIndex = 0;
  1049. }
  1050. ZeroMemory(&lvItem, sizeof(lvItem));
  1051. lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  1052. lvItem.iItem = 0;
  1053. lvItem.lParam = (LPARAM)pidl;
  1054. lvItem.pszText = (LPTSTR)szName;
  1055. lvItem.iImage = dwIconIndex; // image index
  1056. nIndex = ListView_InsertItemU(hWnd, &lvItem);
  1057. // ListView_SetItemTextU(hWnd, nIndex, 1, (LPWSTR)szValue);
  1058. return TRUE;
  1059. }