SHLVIEW.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:35k
源码类别:

Windows编程

开发平台:

Visual C++

  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 1997 Microsoft Corporation.  All Rights Reserved.
  7. **************************************************************************/
  8. /**************************************************************************
  9.    File:          ShlView.cpp
  10.    
  11.    Description:   Implements IShellView.
  12. **************************************************************************/
  13. /**************************************************************************
  14.    #include statements
  15. **************************************************************************/
  16. #include "ShlView.h"
  17. #include "Guid.h"
  18. #include "resource.h"
  19. #include "tools.h"
  20. #define TOOLBAR_ID   (L"RegView")
  21. MYTOOLINFO g_Tools[] = 
  22.    {
  23.    IDM_VIEW_KEYS, 0, IDS_TB_VIEW_KEYS, IDS_MI_VIEW_KEYS, 0, TBSTATE_ENABLED,  TBSTYLE_BUTTON,
  24.    IDM_VIEW_IDW,  0, IDS_TB_VIEW_IDW,  IDS_MI_VIEW_IDW,  0, TBSTATE_ENABLED,  TBSTYLE_BUTTON,
  25.    -1, 0, 0, 0, 0,
  26.    };
  27. /**************************************************************************
  28.    CShellView::CShellView()
  29. **************************************************************************/
  30. CShellView::CShellView(CShellFolder *pFolder, LPCITEMIDLIST pidl)
  31. {
  32. #ifdef INITCOMMONCONTROLSEX
  33. INITCOMMONCONTROLSEX iccex;
  34. iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
  35. iccex.dwICC = ICC_LISTVIEW_CLASSES;
  36. InitCommonControlsEx(&iccex);
  37. #else
  38. InitCommonControls();
  39. #endif   //INITCOMMONCONTROLSEX
  40. m_hMenu = NULL;
  41. m_pDockingWindow = NULL;
  42. m_pPidlMgr = new CPidlMgr();
  43. if(!m_pPidlMgr)
  44.    {
  45.    delete this;
  46.    return;
  47.    }
  48. m_pSFParent = pFolder;
  49. if(m_pSFParent)
  50.    m_pSFParent->AddRef();
  51. //get the shell's IMalloc pointer
  52. //we'll keep this until we get destroyed
  53. if(FAILED(SHGetMalloc(&m_pMalloc)))
  54.    {
  55.    delete this;
  56.    return;
  57.    }
  58. m_pidl = m_pPidlMgr->Copy(pidl);
  59. m_uState = SVUIA_DEACTIVATE;
  60. m_ObjRefCount = 1;
  61. g_DllRefCount++;
  62. }
  63. /**************************************************************************
  64.    CShellView::~CShellView()
  65. **************************************************************************/
  66. CShellView::~CShellView()
  67. {
  68. if(m_pidl)
  69.    {
  70.    m_pPidlMgr->Delete(m_pidl);
  71.    m_pidl = NULL;
  72.    }
  73. if(m_pSFParent)
  74.    m_pSFParent->Release();
  75. if(m_pMalloc)
  76.    {
  77.    m_pMalloc->Release();
  78.    }
  79. if(m_pPidlMgr)
  80.    {
  81.    delete m_pPidlMgr;
  82.    }
  83. g_DllRefCount--;
  84. }
  85. ///////////////////////////////////////////////////////////////////////////
  86. //
  87. // IUnknown Implementation
  88. //
  89. /**************************************************************************
  90.    CShellView::QueryInterface
  91. **************************************************************************/
  92. STDMETHODIMP CShellView::QueryInterface(REFIID riid, LPVOID *ppReturn)
  93. {
  94. *ppReturn = NULL;
  95. //IUnknown
  96. if(IsEqualIID(riid, IID_IUnknown))
  97.    {
  98.    *ppReturn = this;
  99.    }
  100. //IOleWindow
  101. else if(IsEqualIID(riid, IID_IOleWindow))
  102.    {
  103.    *ppReturn = (IOleWindow*)this;
  104.    }
  105. //IShellView
  106. else if(IsEqualIID(riid, IID_IShellView))
  107.    {
  108.    *ppReturn = (IShellView*)this;
  109.    }   
  110. //IOleCommandTarget
  111. else if(IsEqualIID(riid, IID_IOleCommandTarget))
  112.    {
  113.    *ppReturn = (IOleCommandTarget*)this;
  114.    }   
  115. if(*ppReturn)
  116.    {
  117.    (*(LPUNKNOWN*)ppReturn)->AddRef();
  118.    return S_OK;
  119.    }
  120. return E_NOINTERFACE;
  121. }                                             
  122. /**************************************************************************
  123.    CShellView::AddRef
  124. **************************************************************************/
  125. STDMETHODIMP_(DWORD) CShellView::AddRef()
  126. {
  127. return ++m_ObjRefCount;
  128. }
  129. /**************************************************************************
  130.    CShellView::Release
  131. **************************************************************************/
  132. STDMETHODIMP_(DWORD) CShellView::Release()
  133. {
  134. if(--m_ObjRefCount == 0)
  135.    {
  136.    delete this;
  137.    return 0;
  138.    }
  139.    
  140. return m_ObjRefCount;
  141. }
  142. ///////////////////////////////////////////////////////////////////////////
  143. //
  144. // IOleWindow Implementation
  145. //
  146. /**************************************************************************
  147.    CShellView::GetWindow()
  148.    
  149. **************************************************************************/
  150. STDMETHODIMP CShellView::GetWindow(HWND *phWnd)
  151. {
  152. *phWnd = m_hWnd;
  153. return S_OK;
  154. }
  155. /**************************************************************************
  156.    CShellView::ContextSensitiveHelp()
  157.    
  158. **************************************************************************/
  159. STDMETHODIMP CShellView::ContextSensitiveHelp(BOOL fEnterMode)
  160. {
  161. return E_NOTIMPL;
  162. }
  163. ///////////////////////////////////////////////////////////////////////////
  164. //
  165. // IOleCommandTarget Implementation
  166. //
  167. /**************************************************************************
  168.    CShellView::QueryStatus()
  169.    
  170. **************************************************************************/
  171. STDMETHODIMP CShellView::QueryStatus(  const GUID *pguidCmdGroup, 
  172.                                        ULONG cCmds, 
  173.                                        OLECMD prgCmds[], 
  174.                                        OLECMDTEXT *pCmdText)
  175. {
  176. ULONG i;
  177. //only process the commands for our command group
  178. if(pguidCmdGroup && (*pguidCmdGroup != CLSID_CmdGrp))
  179.    return OLECMDERR_E_UNKNOWNGROUP;
  180. //make sure prgCmds is not NULL
  181. if(!prgCmds)
  182.    return E_POINTER;
  183. //run through all of the commands and supply the correct information
  184. for(i = 0; i < cCmds;i++)
  185.    {
  186.    switch(prgCmds[i].cmdID)
  187.       {
  188.       case IDM_VIEW_KEYS:
  189.          prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  190.          break;
  191.       }
  192.    }
  193. return S_OK;
  194. }
  195. /**************************************************************************
  196.    CShellView::Exec()
  197.    
  198. **************************************************************************/
  199. STDMETHODIMP CShellView::Exec(   const GUID *pguidCmdGroup, 
  200.                                  DWORD nCmdID, 
  201.                                  DWORD nCmdExecOpt, 
  202.                                  VARIANTARG *pvaIn, 
  203.                                  VARIANTARG *pvaOut)
  204. {
  205. //only process the commands for our command group
  206. if(pguidCmdGroup && (*pguidCmdGroup == CLSID_CmdGrp))
  207.    {
  208.    OnCommand(nCmdID, 0, NULL);
  209.    return S_OK;
  210.    }
  211. return OLECMDERR_E_UNKNOWNGROUP;
  212. }
  213. ///////////////////////////////////////////////////////////////////////////
  214. //
  215. // IShellView Implementation
  216. //
  217. /**************************************************************************
  218.    CShellView::TranslateAccelerator()
  219.    
  220. **************************************************************************/
  221. STDMETHODIMP CShellView::TranslateAccelerator(LPMSG pMsg)
  222. {
  223. return E_NOTIMPL;
  224. }
  225. /**************************************************************************
  226.    CShellView::EnableModeless()
  227.    
  228. **************************************************************************/
  229. STDMETHODIMP CShellView::EnableModeless(BOOL fEnable)
  230. {
  231. return E_NOTIMPL;
  232. }
  233. /**************************************************************************
  234.    CShellView::OnActivate()
  235.    
  236. **************************************************************************/
  237. LRESULT CShellView::OnActivate(UINT uState)
  238. {
  239. //don't do anything if the state isn't really changing
  240. if(m_uState == uState)
  241.    return S_OK;
  242. OnDeactivate();
  243. //only do this if we are active
  244. if(uState != SVUIA_DEACTIVATE)
  245.    {
  246.    //merge the menus
  247.    m_hMenu = CreateMenu();
  248.    
  249.    if(m_hMenu)
  250.       {
  251.     OLEMENUGROUPWIDTHS   omw = {0, 0, 0, 0, 0, 0};
  252.       MENUITEMINFO         mii;
  253.       TCHAR                szText[MAX_PATH];
  254.       m_pShellBrowser->InsertMenusSB(m_hMenu, &omw);
  255.       //build the top level menu
  256.       //get the menu item's text
  257.       LoadString(g_hInst, IDS_MI_REGISTRY, szText, sizeof(szText));
  258.       
  259.       ZeroMemory(&mii, sizeof(mii));
  260.       mii.cbSize = sizeof(mii);
  261.       mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
  262.       mii.fType = MFT_STRING;
  263.       mii.fState = MFS_ENABLED;
  264.       mii.dwTypeData = szText;
  265.       mii.hSubMenu = BuildRegistryMenu();
  266.       //insert our menu into the menu bar
  267.       if(mii.hSubMenu)
  268.          {
  269.          InsertMenuItem(m_hMenu, FCIDM_MENU_HELP, FALSE, &mii);
  270.          }
  271.       //get the view menu so we can merge with it
  272.       ZeroMemory(&mii, sizeof(mii));
  273.       mii.cbSize = sizeof(mii);
  274.       mii.fMask = MIIM_SUBMENU;
  275.       
  276.       if(GetMenuItemInfo(m_hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
  277.          {
  278.          MergeViewMenu(mii.hSubMenu);
  279.          }
  280.       //add the items that should only be added if we have the focus
  281.       if(SVUIA_ACTIVATE_FOCUS == uState)
  282.          {
  283.          //get the file menu so we can merge with it
  284.          ZeroMemory(&mii, sizeof(mii));
  285.          mii.cbSize = sizeof(mii);
  286.          mii.fMask = MIIM_SUBMENU;
  287.       
  288.          if(GetMenuItemInfo(m_hMenu, FCIDM_MENU_FILE, FALSE, &mii))
  289.             {
  290.             MergeFileMenu(mii.hSubMenu);
  291.             }
  292.          }
  293.       m_pShellBrowser->SetMenuSB(m_hMenu, NULL, m_hWnd);
  294.       }
  295.    }
  296. m_uState = uState;
  297. return 0;
  298. }
  299. /**************************************************************************
  300.    CShellView::OnDeactivate()
  301.    
  302. **************************************************************************/
  303. void CShellView::OnDeactivate(void)
  304. {
  305. if(m_uState != SVUIA_DEACTIVATE)
  306.    {
  307.    if(m_hMenu)
  308.       {
  309.       m_pShellBrowser->SetMenuSB(NULL, NULL, NULL);
  310.       m_pShellBrowser->RemoveMenusSB(m_hMenu);
  311.       DestroyMenu(m_hMenu);
  312.       m_hMenu = NULL;
  313.       }
  314.    m_uState = SVUIA_DEACTIVATE;
  315.    }
  316. }
  317. /**************************************************************************
  318.    CShellView::UIActivate()
  319.    This function activates the view window. Note that activating it 
  320.    will not change the focus, while setting the focus will activate it.
  321.    
  322. **************************************************************************/
  323. STDMETHODIMP CShellView::UIActivate(UINT uState)
  324. {
  325. //don't do anything if the state isn't really changing
  326. if(m_uState == uState)
  327.    return S_OK;
  328. //OnActivate handles the menu merging and internal state
  329. OnActivate(uState);
  330. //remove the docking window
  331. if(g_bShowIDW)
  332.    AddRemoveDockingWindow(FALSE);
  333. //only do this if we are active
  334. if(uState != SVUIA_DEACTIVATE)
  335.    {
  336.    TCHAR szName[MAX_PATH];
  337.    LRESULT  lResult;
  338.    int      nPartArray[1] = {-1};
  339.    
  340.    //update the status bar
  341.    LoadString(g_hInst, IDS_REGISTRY_TITLE, szName, sizeof(szName));
  342.    
  343.    m_pSFParent->GetFolderPath(szName + lstrlen(szName), sizeof(szName) - lstrlen(szName));
  344.    //set the number of parts
  345.    m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, 1, (LPARAM)nPartArray, &lResult);
  346.    //set the text for the parts
  347.    m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 0, (LPARAM)szName, &lResult);
  348.    //add the docking window if necessary
  349.    if(g_bShowIDW)
  350.       AddRemoveDockingWindow(TRUE);
  351.    }
  352. return S_OK;
  353. }
  354. /**************************************************************************
  355.    CShellView::BuildRegistryMenu()
  356.    
  357. **************************************************************************/
  358. HMENU CShellView::BuildRegistryMenu(void)
  359. {
  360. HMENU hSubMenu = CreatePopupMenu();
  361. if(hSubMenu)
  362.    {
  363.    TCHAR          szText[MAX_PATH];
  364.    MENUITEMINFO   mii;
  365.    int            nTools,
  366.                   i;
  367.    //get the number of items in our global array
  368.    for(nTools = 0; g_Tools[nTools].idCommand != -1; nTools++)
  369.       {
  370.       }
  371.    //add the menu items
  372.    for(i = 0; i < nTools; i++)
  373.       {
  374.       LoadString(g_hInst, g_Tools[i].idMenuString, szText, sizeof(szText));
  375.       
  376.       ZeroMemory(&mii, sizeof(mii));
  377.       mii.cbSize = sizeof(mii);
  378.       mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  379.       if(TBSTYLE_SEP != g_Tools[i].bStyle)
  380.          {
  381.          mii.fType = MFT_STRING;
  382.          mii.fState = MFS_ENABLED;
  383.          mii.dwTypeData = szText;
  384.          mii.wID = g_Tools[i].idCommand;
  385.          }
  386.       else
  387.          {
  388.          mii.fType = MFT_SEPARATOR;
  389.          }
  390.       
  391.       //tack this item onto the end of the menu
  392.       InsertMenuItem(hSubMenu, (UINT)-1, TRUE, &mii);
  393.       }
  394.    }
  395. return hSubMenu;
  396. }
  397. /**************************************************************************
  398.    CShellView::MergeFileMenu()
  399.    
  400. **************************************************************************/
  401. void CShellView::MergeFileMenu(HMENU hSubMenu)
  402. {
  403. if(hSubMenu)
  404.    {
  405.    MENUITEMINFO   mii;
  406.    TCHAR          szText[MAX_PATH];
  407.    ZeroMemory(&mii, sizeof(mii));
  408.    //add a separator
  409.    mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  410.    mii.fType = MFT_SEPARATOR;
  411.    mii.fState = MFS_ENABLED;
  412.    //insert this item at the beginning of the menu
  413.    InsertMenuItem(hSubMenu, 0, TRUE, &mii);
  414.    //add the file menu items
  415.    LoadString(g_hInst, IDS_MI_FILEITEM, szText, sizeof(szText));
  416.    mii.cbSize = sizeof(mii);
  417.    mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  418.    mii.fType = MFT_STRING;
  419.    mii.fState = MFS_ENABLED;
  420.    mii.dwTypeData = szText;
  421.    mii.wID = IDM_MYFILEITEM;
  422.    //insert this item at the beginning of the menu
  423.    InsertMenuItem(hSubMenu, 0, TRUE, &mii);
  424.    }
  425. }
  426. /**************************************************************************
  427.    CShellView::MergeViewMenu()
  428.    
  429. **************************************************************************/
  430. void CShellView::MergeViewMenu(HMENU hSubMenu)
  431. {
  432. if(hSubMenu)
  433.    {
  434.    MENUITEMINFO   mii;
  435.    TCHAR          szText[MAX_PATH];
  436.    ZeroMemory(&mii, sizeof(mii));
  437.    //add a separator at the correct position in the menu
  438.    mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  439.    mii.fType = MFT_SEPARATOR;
  440.    mii.fState = MFS_ENABLED;
  441.    InsertMenuItem(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
  442.    //add the view menu items at the correct position in the menu
  443.    LoadString(g_hInst, IDS_MI_VIEW_KEYS, szText, sizeof(szText));
  444.    mii.cbSize = sizeof(mii);
  445.    mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  446.    mii.fType = MFT_STRING;
  447.    mii.fState = MFS_ENABLED;
  448.    mii.dwTypeData = szText;
  449.    mii.wID = IDM_VIEW_KEYS;
  450.    InsertMenuItem(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
  451.    }
  452. }
  453. /**************************************************************************
  454.    CShellView::Refresh()
  455.    
  456. **************************************************************************/
  457. STDMETHODIMP CShellView::Refresh(void)
  458. {
  459. //empty the list
  460. ListView_DeleteAllItems(m_hwndList);
  461. //refill the list
  462. FillList();
  463. return S_OK;
  464. }
  465. /**************************************************************************
  466.    CShellView::CreateViewWindow()
  467.    
  468. **************************************************************************/
  469. STDMETHODIMP CShellView::CreateViewWindow(   LPSHELLVIEW pPrevView, 
  470.                                              LPCFOLDERSETTINGS lpfs, 
  471.                                              LPSHELLBROWSER psb, 
  472.                                              LPRECT prcView, 
  473.                                              HWND *phWnd)
  474. {
  475. WNDCLASS wc;
  476. *phWnd = NULL;
  477. //if our window class has not been registered, then do so
  478. if(!GetClassInfo(g_hInst, NS_CLASS_NAME, &wc))
  479.    {
  480.    ZeroMemory(&wc, sizeof(wc));
  481.    wc.style          = CS_HREDRAW | CS_VREDRAW;
  482.    wc.lpfnWndProc    = (WNDPROC)WndProc;
  483.    wc.cbClsExtra     = 0;
  484.    wc.cbWndExtra     = 0;
  485.    wc.hInstance      = g_hInst;
  486.    wc.hIcon          = NULL;
  487.    wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
  488.    wc.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  489.    wc.lpszMenuName   = NULL;
  490.    wc.lpszClassName  = NS_CLASS_NAME;
  491.    
  492.    if(!RegisterClass(&wc))
  493.       return E_FAIL;
  494.    }
  495. //set up the member variables
  496. m_pShellBrowser = psb;
  497. m_FolderSettings = *lpfs;
  498. //get our parent window
  499. m_pShellBrowser->GetWindow(&m_hwndParent);
  500. *phWnd = CreateWindowEx(   0,
  501.                            NS_CLASS_NAME,
  502.                            NULL,
  503.                            WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
  504.                            prcView->left,
  505.                            prcView->top,
  506.                            prcView->right - prcView->left,
  507.                            prcView->bottom - prcView->top,
  508.                            m_hwndParent,
  509.                            NULL,
  510.                            g_hInst,
  511.                            (LPVOID)this);
  512.                            
  513. if(!*phWnd)
  514.    return E_FAIL;
  515. m_pShellBrowser->AddRef();
  516. return S_OK;
  517. }
  518. /**************************************************************************
  519.    CShellView::DestroyViewWindow()
  520.    
  521. **************************************************************************/
  522. STDMETHODIMP CShellView::DestroyViewWindow(void)
  523. {
  524. //Make absolutely sure all our UI is cleaned up.
  525. UIActivate(SVUIA_DEACTIVATE);
  526. if(m_hMenu)
  527.    DestroyMenu(m_hMenu);
  528. DestroyWindow(m_hWnd);
  529. //release the shell browser object
  530. m_pShellBrowser->Release();
  531. return S_OK;
  532. }
  533. /**************************************************************************
  534.    CShellView::GetCurrentInfo()
  535.    
  536. **************************************************************************/
  537. STDMETHODIMP CShellView::GetCurrentInfo(LPFOLDERSETTINGS lpfs)
  538. {
  539. *lpfs = m_FolderSettings;
  540. return S_OK;
  541. }
  542. /**************************************************************************
  543.    CShellView::AddPropertySheetPages()
  544.    
  545. **************************************************************************/
  546. STDMETHODIMP CShellView::AddPropertySheetPages( DWORD dwReserved, 
  547.                                                 LPFNADDPROPSHEETPAGE lpfn, 
  548.                                                 LPARAM lParam)
  549. {
  550. return E_NOTIMPL;
  551. }
  552. /**************************************************************************
  553.    CShellView::SaveViewState()
  554.    
  555. **************************************************************************/
  556. STDMETHODIMP CShellView::SaveViewState(void)
  557. {
  558. return S_OK;
  559. }
  560. /**************************************************************************
  561.    CShellView::SelectItem()
  562.    
  563. **************************************************************************/
  564. STDMETHODIMP CShellView::SelectItem(LPCITEMIDLIST pidlItem, UINT uFlags)
  565. {
  566. return E_NOTIMPL;
  567. }
  568. /**************************************************************************
  569.    CShellView::GetItemObject()
  570.    
  571. **************************************************************************/
  572. STDMETHODIMP CShellView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut)
  573. {
  574. *ppvOut = NULL;
  575. return E_NOTIMPL;
  576. }
  577. /**************************************************************************
  578.    CShellView::WndProc()
  579.    
  580. **************************************************************************/
  581. LRESULT CALLBACK CShellView::WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
  582. {
  583. CShellView  *pThis = (CShellView*)GetWindowLong(hWnd, GWL_USERDATA);
  584. switch (uMessage)
  585.    {
  586.    case WM_NCCREATE:
  587.       {
  588.       LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
  589.       pThis = (CShellView*)(lpcs->lpCreateParams);
  590.       SetWindowLong(hWnd, GWL_USERDATA, (LONG)pThis);
  591.       //set the window handle
  592.       pThis->m_hWnd = hWnd;
  593.       }
  594.       break;
  595.    
  596.    case WM_SIZE:
  597.       return pThis->OnSize(LOWORD(lParam), HIWORD(lParam));
  598.    
  599.    case WM_CREATE:
  600.       return pThis->OnCreate();
  601.    
  602.    case WM_SETFOCUS:
  603.       return pThis->OnSetFocus();
  604.    
  605.    case WM_KILLFOCUS:
  606.       return pThis->OnKillFocus();
  607.    case WM_ACTIVATE:
  608.       return pThis->OnActivate(SVUIA_ACTIVATE_FOCUS);
  609.    
  610.    case WM_COMMAND:
  611.       return pThis->OnCommand(   GET_WM_COMMAND_ID(wParam, lParam), 
  612.                                  GET_WM_COMMAND_CMD(wParam, lParam), 
  613.                                  GET_WM_COMMAND_HWND(wParam, lParam));
  614.    
  615.    case WM_INITMENUPOPUP:
  616.       return pThis->UpdateMenu((HMENU)wParam);
  617.    
  618.    case WM_NOTIFY:
  619.       return pThis->OnNotify((UINT)wParam, (LPNMHDR)lParam);
  620.    
  621.    case WM_SETTINGCHANGE:
  622.       return pThis->OnSettingChange((LPCTSTR)lParam);
  623.    }
  624. return DefWindowProc(hWnd, uMessage, wParam, lParam);
  625. }
  626. /**************************************************************************
  627.    CShellView::OnSetFocus()
  628.    
  629. **************************************************************************/
  630. LRESULT CShellView::OnSetFocus(void)
  631. {
  632. /*
  633. Tell the browser one of our windows has received the focus. This should always 
  634. be done before merging menus (OnActivate merges the menus) if one of our 
  635. windows has the focus.
  636. */
  637. m_pShellBrowser->OnViewWindowActive(this);
  638. OnActivate(SVUIA_ACTIVATE_FOCUS);
  639. return 0;
  640. }
  641. /**************************************************************************
  642.    CShellView::OnKillFocus()
  643.    
  644. **************************************************************************/
  645. LRESULT CShellView::OnKillFocus(void)
  646. {
  647. OnActivate(SVUIA_ACTIVATE_NOFOCUS);
  648. return 0;
  649. }
  650. /**************************************************************************
  651.    CShellView::OnCommand()
  652.    
  653. **************************************************************************/
  654. LRESULT CShellView::OnCommand(DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
  655. {
  656. switch(dwCmdID)
  657.    {
  658.    case IDM_VIEW_KEYS:
  659.       g_bViewKeys = ! g_bViewKeys;
  660.       Refresh();
  661.       break;
  662.    case IDM_VIEW_IDW:
  663.       g_bShowIDW = ! g_bShowIDW;
  664.       AddRemoveDockingWindow(g_bShowIDW);
  665.       break;
  666.    
  667.    case IDM_MYFILEITEM:
  668.       MessageBeep(MB_OK);
  669.       break;
  670.    }
  671. return 0;
  672. }
  673. /**************************************************************************
  674.    CShellView::UpdateMenu()
  675.    
  676. **************************************************************************/
  677. LRESULT CShellView::UpdateMenu(HMENU hMenu)
  678. {
  679. CheckMenuItem(hMenu, IDM_VIEW_KEYS, MF_BYCOMMAND | (g_bViewKeys ? MF_CHECKED: MF_UNCHECKED));
  680. if(CanDoIDockingWindow())
  681.    {
  682.    EnableMenuItem(hMenu, IDM_VIEW_IDW, MF_BYCOMMAND | MF_ENABLED);
  683.    CheckMenuItem(hMenu, IDM_VIEW_IDW, MF_BYCOMMAND | (g_bShowIDW ? MF_CHECKED: MF_UNCHECKED));
  684.    }
  685. else
  686.    {
  687.    EnableMenuItem(hMenu, IDM_VIEW_IDW, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  688.    CheckMenuItem(hMenu, IDM_VIEW_IDW, MF_BYCOMMAND | MF_UNCHECKED);
  689.    }
  690. return 0;
  691. }
  692. /**************************************************************************
  693.    CShellView::OnNotify()
  694.    
  695. **************************************************************************/
  696. LRESULT CShellView::OnNotify(UINT CtlID, LPNMHDR lpnmh)
  697. {
  698. switch(lpnmh->code)
  699.    {
  700.    case NM_SETFOCUS:
  701.       OnSetFocus();
  702.       break;
  703.    case NM_KILLFOCUS:
  704.       OnDeactivate();
  705.       break;
  706.    case HDN_ENDTRACK:
  707.       {
  708.       g_nColumn1 = ListView_GetColumnWidth(m_hwndList, 0);
  709.       g_nColumn2 = ListView_GetColumnWidth(m_hwndList, 1);
  710.       }
  711.       return 0;
  712.    
  713.    case LVN_DELETEITEM:
  714.       {
  715.       NM_LISTVIEW *lpnmlv = (NM_LISTVIEW*)lpnmh;
  716.       
  717.       //delete the pidl because we made a copy of it
  718.       m_pPidlMgr->Delete((LPITEMIDLIST)lpnmlv->lParam);
  719.       }
  720.       break;
  721.    
  722. #ifdef LVN_ITEMACTIVATE
  723.    
  724.    case LVN_ITEMACTIVATE:
  725. #else    //LVN_ITEMACTIVATE
  726.    case NM_DBLCLK:
  727.    case NM_RETURN:
  728. #endif   //LVN_ITEMACTIVATE
  729.       {
  730.       LV_ITEM        lvItem;
  731.       ZeroMemory(&lvItem, sizeof(lvItem));
  732.       lvItem.mask = LVIF_PARAM;
  733. #ifdef LVN_ITEMACTIVATE
  734.       LPNMLISTVIEW   lpnmlv = (LPNMLISTVIEW)lpnmh;
  735.       lvItem.iItem = lpnmlv->iItem;
  736. #else    //LVN_ITEMACTIVATE
  737.       lvItem.iItem = -1;
  738.       //need to find the selected item
  739.       {
  740.       int   i;
  741.       for(i = 0; i < ListView_GetItemCount(m_hwndList); i++)
  742.          {
  743.          if(ListView_GetItemState(m_hwndList, i, LVIS_SELECTED))
  744.             {
  745.             lvItem.iItem = i;
  746.             break;
  747.             }
  748.          }
  749.       //we didn't find a selected item
  750.       if(-1 == lvItem.iItem)
  751.          return 0;
  752.       }
  753. #endif   //LVN_ITEMACTIVATE
  754.       if(ListView_GetItem(m_hwndList, &lvItem))
  755.          {
  756.          //only allow keys to be activated
  757.          if(!m_pPidlMgr->IsValue((LPITEMIDLIST)lvItem.lParam))
  758.             m_pShellBrowser->BrowseObject(   (LPITEMIDLIST)lvItem.lParam, 
  759.                                              SBSP_DEFBROWSER | SBSP_RELATIVE);
  760.          }
  761.       }
  762.       return 0;
  763.    
  764.    case LVN_GETDISPINFO:
  765.       {
  766.       LV_DISPINFO    *lpdi = (LV_DISPINFO *)lpnmh;
  767.       LPITEMIDLIST   pidl = (LPITEMIDLIST)lpdi->item.lParam;
  768.       //is the sub-item information being requested?
  769.       if(lpdi->item.iSubItem)
  770.          {
  771.          //is the text being requested?
  772.          if(lpdi->item.mask & LVIF_TEXT)
  773.             {
  774.             //is this a value or a key?
  775.             if(m_pPidlMgr->IsValue(pidl))
  776.                {
  777.                //get the item's value text
  778.                m_pPidlMgr->GetDataText(m_pidl, pidl, lpdi->item.pszText, lpdi->item.cchTextMax);
  779.                //if the data text is NULL, get the no value string
  780.                if(!*lpdi->item.pszText)
  781.                   LoadString(g_hInst, IDS_NODATA, lpdi->item.pszText, lpdi->item.cchTextMax);
  782.                }
  783.             //its a key
  784.             else
  785.                {
  786.                LoadString(g_hInst, IDS_KEY, lpdi->item.pszText, lpdi->item.cchTextMax);
  787.                }
  788.             }
  789.          }
  790.       //the item text is being requested
  791.       else
  792.          {
  793.          //is the text being requested?
  794.          if(lpdi->item.mask & LVIF_TEXT)
  795.             {
  796.             STRRET   str;
  797.             if(SUCCEEDED(m_pSFParent->GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &str)))
  798.                {
  799.                if(STRRET_WSTR == str.uType)
  800.                   {
  801.                   WideCharToLocal(lpdi->item.pszText, str.pOleStr, lpdi->item.cchTextMax);
  802.                   //delete the string buffer
  803.                   m_pMalloc->Free(str.pOleStr);
  804.                   }
  805.                }
  806.             }
  807.          //is the image being requested?
  808.          if(lpdi->item.mask & LVIF_IMAGE)
  809.             {
  810.             IExtractIcon   *pei;
  811.             if(SUCCEEDED(m_pSFParent->GetUIObjectOf(m_hWnd, 1, (LPCITEMIDLIST*)&pidl, IID_IExtractIcon, NULL, (LPVOID*)&pei)))
  812.                {
  813.                UINT  uFlags;
  814.                //GetIconLoaction will give us the index into our image list
  815.                pei->GetIconLocation(GIL_FORSHELL, NULL, 0, &lpdi->item.iImage, &uFlags);
  816.                pei->Release();
  817.                }
  818.             }
  819.          }
  820.       }
  821.       return 0;
  822.    }
  823. return 0;
  824. }
  825. /**************************************************************************
  826.    CShellView::OnSize()
  827.    
  828. **************************************************************************/
  829. LRESULT CShellView::OnSize(WORD wWidth, WORD wHeight)
  830. {
  831. //resize the ListView to fit our window
  832. if(m_hwndList)
  833.    {
  834.    MoveWindow(m_hwndList, 0, 0, wWidth, wHeight, TRUE);
  835.    }
  836. return 0;
  837. }
  838. /**************************************************************************
  839.    CShellView::OnCreate()
  840.    
  841. **************************************************************************/
  842. LRESULT CShellView::OnCreate(void)
  843. {
  844. //create the ListView
  845. if(CreateList())
  846.    {
  847.    if(InitList())
  848.       {
  849.       FillList();
  850.       }
  851.    }
  852. return 0;
  853. }
  854. /**************************************************************************
  855.    CShellView::CreateList()
  856.    
  857. **************************************************************************/
  858. BOOL CShellView::CreateList(void)
  859. {
  860. DWORD dwStyle;
  861. dwStyle =   WS_TABSTOP | 
  862.             WS_VISIBLE |
  863.             WS_CHILD | 
  864.             WS_BORDER | 
  865.             LVS_SINGLESEL |
  866.             LVS_REPORT | 
  867.             LVS_NOSORTHEADER |
  868.             LVS_SHAREIMAGELISTS;
  869. m_hwndList = CreateWindowEx(     WS_EX_CLIENTEDGE,
  870.                                  WC_LISTVIEW,
  871.                                  NULL,
  872.                                  dwStyle,
  873.                                  0,
  874.                                  0,
  875.                                  0,
  876.                                  0,
  877.                                  m_hWnd,
  878.                                  (HMENU)ID_LISTVIEW,
  879.                                  g_hInst,
  880.                                  NULL);
  881. if(!m_hwndList)
  882.    return FALSE;
  883. UpdateShellSettings();
  884. return TRUE;
  885. }
  886. /**************************************************************************
  887.    CShellView::InitList()
  888.    
  889. **************************************************************************/
  890. BOOL CShellView::InitList(void)
  891. {
  892. LV_COLUMN   lvColumn;
  893. RECT        rc;
  894. TCHAR       szString[MAX_PATH];
  895. //empty the list
  896. ListView_DeleteAllItems(m_hwndList);
  897. //initialize the columns
  898. lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  899. lvColumn.fmt = LVCFMT_LEFT;
  900. lvColumn.pszText = szString;
  901. lvColumn.cx = g_nColumn1;
  902. LoadString(g_hInst, IDS_COLUMN1, szString, sizeof(szString));
  903. ListView_InsertColumn(m_hwndList, 0, &lvColumn);
  904. GetClientRect(m_hWnd, &rc);
  905. lvColumn.cx = g_nColumn2;
  906. LoadString(g_hInst, IDS_COLUMN2, szString, sizeof(szString));
  907. ListView_InsertColumn(m_hwndList, 1, &lvColumn);
  908. ListView_SetImageList(m_hwndList, g_himlSmall, LVSIL_SMALL);
  909. return TRUE;
  910. }
  911. /**************************************************************************
  912.    CShellView::FillList()
  913.    
  914. **************************************************************************/
  915. void CShellView::FillList(void)
  916. {
  917. LPENUMIDLIST   pEnumIDList;
  918. if(SUCCEEDED(m_pSFParent->EnumObjects(m_hWnd, SHCONTF_NONFOLDERS | (g_bViewKeys ? SHCONTF_FOLDERS : 0), &pEnumIDList)))
  919.    {
  920.    LPITEMIDLIST   pidl;
  921.    DWORD          dwFetched;
  922.    //turn the listview's redrawing off
  923.    SendMessage(m_hwndList, WM_SETREDRAW, FALSE, 0);
  924.    while((S_OK == pEnumIDList->Next(1, &pidl, &dwFetched)) && dwFetched)
  925.       {
  926.       LV_ITEM  lvItem;
  927.       ZeroMemory(&lvItem, sizeof(lvItem));
  928.       //set the mask
  929.       lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  930.       //add the item to the end of the list
  931.       lvItem.iItem = ListView_GetItemCount(m_hwndList);
  932.       //set the item's data
  933.       lvItem.lParam = (LPARAM)m_pPidlMgr->Copy(pidl);
  934.       //get text on a callback basis
  935.       lvItem.pszText = LPSTR_TEXTCALLBACK;
  936.       //get the image on a callback basis
  937.       lvItem.iImage = I_IMAGECALLBACK;
  938.       //add the item
  939.       ListView_InsertItem(m_hwndList, &lvItem);
  940.       }
  941.    //sort the items
  942.    ListView_SortItems(m_hwndList, CompareItems, (LPARAM)m_pSFParent);
  943.    
  944.    //turn the listview's redrawing back on and force it to draw
  945.    SendMessage(m_hwndList, WM_SETREDRAW, TRUE, 0);
  946.    InvalidateRect(m_hwndList, NULL, TRUE);
  947.    UpdateWindow(m_hwndList);
  948.    pEnumIDList->Release();
  949.    }
  950. }
  951. /**************************************************************************
  952.    CShellView::CanDoIDockingWindow()
  953.    
  954. **************************************************************************/
  955. BOOL CShellView::CanDoIDockingWindow(void)
  956. {
  957. #if (_WIN32_IE < 0x0400)
  958. return FALSE;
  959. #else //(_WIN32_IE >= 0x0400)
  960. BOOL              bReturn = FALSE;
  961. HRESULT           hr;
  962. IServiceProvider  *pSP;
  963. //get the browser's IServiceProvider
  964. hr = m_pShellBrowser->QueryInterface((REFIID)IID_IServiceProvider, (LPVOID*)&pSP);
  965. if(SUCCEEDED(hr))
  966.    {
  967.    IDockingWindowFrame *pFrame;
  968.    //get the IDockingWindowFrame
  969.    hr = pSP->QueryService(SID_SShellBrowser, IID_IDockingWindowFrame, (LPVOID*)&pFrame);
  970.    if(SUCCEEDED(hr))
  971.       {
  972.       bReturn = TRUE;
  973.       pFrame->Release();
  974.       }
  975.    pSP->Release();
  976.    }
  977. return bReturn;
  978. #endif   //(_WIN32_IE >= 0x0400)
  979. }
  980. /**************************************************************************
  981.    CShellView::AddRemoveDockingWindow()
  982.    
  983. **************************************************************************/
  984. BOOL CShellView::AddRemoveDockingWindow(BOOL bAdd)
  985. {
  986. #if (_WIN32_IE < 0x0400)
  987. return FALSE;
  988. #else //(_WIN32_IE < 0x0400)
  989. BOOL              bReturn = FALSE;
  990. HRESULT           hr;
  991. IServiceProvider  *pSP;
  992. //get the browser's IServiceProvider
  993. hr = m_pShellBrowser->QueryInterface((REFIID)IID_IServiceProvider, (LPVOID*)&pSP);
  994. if(SUCCEEDED(hr))
  995.    {
  996.    IDockingWindowFrame *pFrame;
  997.    //get the IDockingWindowFrame pointer
  998.    hr = pSP->QueryService(SID_SShellBrowser, IID_IDockingWindowFrame, (LPVOID*)&pFrame);
  999.    if(SUCCEEDED(hr))
  1000.       {
  1001.       if(bAdd)
  1002.          {
  1003.          hr = S_OK;
  1004.          if(!m_pDockingWindow)
  1005.             {
  1006.             //create the toolbar object
  1007.             m_pDockingWindow = new CDockingWindow(this, m_hWnd);
  1008.             }
  1009.          if(m_pDockingWindow)
  1010.             {
  1011.             //add the toolbar object
  1012.             hr = pFrame->AddToolbar((IDockingWindow*)m_pDockingWindow, TOOLBAR_ID, 0);
  1013.             if(SUCCEEDED(hr))
  1014.                {
  1015.                bReturn = TRUE;
  1016.                }
  1017.             }
  1018.          }
  1019.       else
  1020.          {
  1021.          if(m_pDockingWindow)
  1022.             {
  1023.             hr = pFrame->RemoveToolbar((IDockingWindow*)m_pDockingWindow, DWFRF_NORMAL);
  1024.             if(SUCCEEDED(hr))
  1025.                {
  1026.                /*
  1027.                RemoveToolbar should release the toolbar object which will cause 
  1028.                it to destroy itself. Our toolbar object is no longer valid at 
  1029.                this point.
  1030.                */
  1031.                m_pDockingWindow = NULL;
  1032.                bReturn = TRUE;
  1033.                }
  1034.             }
  1035.          }
  1036.       pFrame->Release();
  1037.       }
  1038.    pSP->Release();
  1039.    }
  1040. return bReturn;
  1041. #endif   //(_WIN32_IE < 0x0400)
  1042. }
  1043. /**************************************************************************
  1044.    CShellView::UpdateShellSettings()
  1045.    
  1046. **************************************************************************/
  1047. typedef void (WINAPI *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
  1048. void CShellView::UpdateShellSettings(void)
  1049. {
  1050. #if (_WIN32_IE >= 0x0400)
  1051. SHELLFLAGSTATE       sfs;
  1052. HINSTANCE            hinstShell32;
  1053. /*
  1054. Since SHGetSettings is not implemented in all versions of the shell, get the 
  1055. function address manually at run time. This allows the extension to run on all 
  1056. platforms.
  1057. */
  1058. ZeroMemory(&sfs, sizeof(sfs));
  1059. /*
  1060. The default, in case any of the following steps fails, is classic Windows 95 
  1061. style.
  1062. */
  1063. sfs.fWin95Classic = TRUE;
  1064. hinstShell32 = LoadLibrary(TEXT("shell32.dll"));
  1065. if(hinstShell32)
  1066.    {
  1067.    PFNSHGETSETTINGSPROC pfnSHGetSettings;
  1068.    pfnSHGetSettings = (PFNSHGETSETTINGSPROC)GetProcAddress(hinstShell32, TEXT("SHGetSettings"));
  1069.    if(pfnSHGetSettings)
  1070.       {
  1071.       (*pfnSHGetSettings)(&sfs, SSF_DOUBLECLICKINWEBVIEW | SSF_WIN95CLASSIC);
  1072.       }
  1073.    FreeLibrary(hinstShell32);
  1074.    }
  1075. DWORD dwExStyles = 0;
  1076. if(!sfs.fWin95Classic && !sfs.fDoubleClickInWebView)
  1077.    dwExStyles |= LVS_EX_ONECLICKACTIVATE | 
  1078.                   LVS_EX_TRACKSELECT | 
  1079.                   LVS_EX_UNDERLINEHOT;
  1080. ListView_SetExtendedListViewStyle(m_hwndList, dwExStyles);
  1081. #endif   //(_WIN32_IE >= 0x0400)
  1082. }
  1083. /**************************************************************************
  1084.    CShellView::OnSettingChange()
  1085.    
  1086. **************************************************************************/
  1087. LRESULT CShellView::OnSettingChange(LPCTSTR lpszSection)
  1088. {
  1089. //if(0 == lstrcmpi(lpszSection, TEXT("ShellState")))
  1090.    {
  1091.    UpdateShellSettings();
  1092.    return 0;
  1093.    }
  1094. return 0;
  1095. }