home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / activedocument / dfv / mwclass.cxx < prev    next >
C/C++ Source or Header  |  1998-01-20  |  33KB  |  1,052 lines

  1. //+---------------------------------------------------------------------------
  2. //
  3. //  Microsoft Windows
  4. //  Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. //  File:       mwclass.cxx
  7. //
  8. //  Contents:   implementation for the main window class
  9. //
  10. //  Classes:    CMainWindow
  11. //
  12. //  Functions:  Exists
  13. //
  14. //  History:    6-08-94   stevebl   Created
  15. //
  16. //----------------------------------------------------------------------------
  17.  
  18. #include "dfv.h"
  19. #include "mwclass.h"
  20. #include "about.h"
  21. #include "bitmaps.h"
  22. #include "strmvwr.h"
  23. #include "assert.h"
  24.  
  25. #define BITMAPWIDTH 16
  26. #define BITMAPHEIGHT 16
  27. #define INDENT BITMAPWIDTH
  28. #define ROOTSTGSTR OLESTR(" \\ - ")
  29.  
  30. //+---------------------------------------------------------------------------
  31. //
  32. //  Member:     CMainWindow::CMainWindow
  33. //
  34. //  Synopsis:   constructor
  35. //
  36. //  History:    6-27-94   stevebl   Created
  37. //
  38. //----------------------------------------------------------------------------
  39.  
  40. CMainWindow::CMainWindow()
  41. {
  42.     _hlb = NULL;
  43.     _hbmpStorage = _hbmpStream = NULL;
  44. }
  45.  
  46. //+---------------------------------------------------------------------------
  47. //
  48. //  Member:     CMainWindow::~CMainWindow
  49. //
  50. //  Synopsis:   destructor
  51. //
  52. //  History:    6-27-94   stevebl   Created
  53. //
  54. //  Notes:      Destruction of the main window indicates that the app should
  55. //              quit.
  56. //
  57. //----------------------------------------------------------------------------
  58.  
  59. CMainWindow::~CMainWindow()
  60. {
  61.     DeleteObject(_hbmpStorage);
  62.     DeleteObject(_hbmpStream);
  63.     PostQuitMessage(0);
  64. }
  65.  
  66. //+---------------------------------------------------------------------------
  67. //
  68. //  Member:     CMainWindow::InitInstance
  69. //
  70. //  Synopsis:   Instantiates an instance of the docfile viewer window.
  71. //
  72. //  Arguments:  [hInstance] - instance of the app
  73. //              [nCmdShow]  - command to pass to ShowWindow
  74. //
  75. //  Returns:    TRUE on success
  76. //              FALSE on failure
  77. //
  78. //  History:    6-27-94   stevebl   Created
  79. //
  80. //  Notes:      This method must be called only once, immediately after
  81. //              class construction.
  82. //
  83. //----------------------------------------------------------------------------
  84.  
  85. BOOL CMainWindow::InitInstance(HINSTANCE hInstance, int nCmdShow)
  86. {
  87.     // Note, the Create method sets the _hwnd member for me so I don't
  88.     // need to set it myself.
  89.     if (!Create(
  90.         TEXT(MAIN_WINDOW_CLASS_NAME),
  91.         TEXT(VER_INTERNALNAME_STR),
  92.         WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
  93.             | WS_MAXIMIZEBOX | WS_THICKFRAME,
  94.         CW_USEDEFAULT,
  95.         CW_USEDEFAULT,
  96.         CW_USEDEFAULT,
  97.         CW_USEDEFAULT,
  98.         NULL,
  99.         NULL,
  100.         hInstance))
  101.     {
  102.         return(FALSE);
  103.     }
  104.  
  105.     ShowWindow(_hwnd, nCmdShow);
  106.     UpdateWindow(_hwnd);
  107.  
  108.     // build a path to where the help file should be
  109.     // (it should be in the same directory as the .EXE)
  110.     // first get the exe's path
  111.     DWORD cch = GetModuleFileName(hInstance, _szHelpFile, MAX_PATH);
  112.     // then back up past the name of the application
  113.     while (cch > 0 &&
  114.         _szHelpFile[cch - 1] != TEXT('\\') &&
  115.         _szHelpFile[cch - 1] != TEXT('/') &&
  116.         _szHelpFile[cch - 1] != TEXT(':'))
  117.     {
  118.         cch--;
  119.     }
  120.     // finally copy the help file's name at the end of the path
  121.     lstrcpy(&_szHelpFile[cch], TEXT(HELPFILE_STR));
  122.     return(TRUE);
  123. }
  124.  
  125. //+---------------------------------------------------------------------------
  126. //
  127. //  Member:     CMainWindow::WindowProc
  128. //
  129. //  Synopsis:   main window procedure
  130. //
  131. //  Arguments:  [uMsg]   - Windows message
  132. //              [wParam] - first message parameter
  133. //              [lParam] - second message parameter
  134. //
  135. //  History:    6-27-94   stevebl   Created
  136. //
  137. //  Notes:      See CHlprWindow for a description of how this method gets
  138. //              called by the global WinProc.
  139. //
  140. //----------------------------------------------------------------------------
  141.  
  142. LRESULT CMainWindow::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  143. {
  144.     switch (uMsg)
  145.     {
  146.     case WM_CREATE:
  147.         {
  148.             RECT rc;
  149.             GetClientRect(_hwnd, &rc);
  150.             // record the width before we create the list box
  151.             _wWidth = (WORD) rc.right;
  152.  
  153.             HDC hdc = GetDC(_hwnd);
  154.             GetTextMetrics(hdc, &_tm);
  155.             ReleaseDC(_hwnd, hdc);
  156.  
  157.             // create the child listbox
  158.             _hlb = CreateWindow(
  159.                 TEXT("listbox"),
  160.                 TEXT(""),
  161.                 LBS_OWNERDRAWFIXED |
  162.                     WS_CHILD |
  163.                     WS_VISIBLE |
  164.                     WS_VSCROLL |
  165.                     LBS_NOTIFY |
  166.                     LBS_NOINTEGRALHEIGHT |
  167.                     LBS_WANTKEYBOARDINPUT,
  168.                 0,
  169.                 0,
  170.                 rc.right,
  171.                 rc.bottom,
  172.                 _hwnd,
  173.                 (HMENU) IDC_LISTBOX,
  174.                 _hInstance,
  175.                 NULL);
  176.             if (NULL == _hlb)
  177.             {
  178.                 // abort window creation
  179.                 return(-1);
  180.             }
  181.             SetFocus(_hlb);
  182.  
  183.             if (!LoadBitmaps())
  184.             {
  185.                 MessageBoxFromStringIds(
  186.                     _hwnd,
  187.                     _hInstance,
  188.                     IDS_LOADBITMAPSFAILED,
  189.                     IDS_ERROR,
  190.                     MB_OK | MB_ICONEXCLAMATION);
  191.                 return(-1);
  192.             }
  193.             _crTextHigh = GetSysColor(COLOR_HIGHLIGHTTEXT);
  194.             _crTextNorm = GetSysColor(COLOR_WINDOWTEXT);
  195.             _crBkHigh = GetSysColor(COLOR_HIGHLIGHT);
  196.             _crBkNorm = GetSysColor(COLOR_WINDOW);
  197.  
  198.             // Fill in the File's OPENFILENAME structure
  199.             _szFileName[0] = 0;
  200.             _szFileTitle[0] = 0;
  201.             _ofnFile.lStructSize = sizeof(OPENFILENAME);
  202.             _ofnFile.hwndOwner = _hwnd;
  203.             _ofnFile.lpstrFilter = TEXT("All Files (*.*)\0*.*\0Doc Files (*.DFL;*.OL?)\0*.DFL;*.OL;\0");
  204.             _ofnFile.lpstrCustomFilter = NULL;
  205.             _ofnFile.nMaxCustFilter = 0;
  206.             _ofnFile.nFilterIndex = 1;
  207.             _ofnFile.lpstrFile = _szFileName;
  208.             _ofnFile.nMaxFile = MAX_PATH;
  209.             _ofnFile.lpstrInitialDir = NULL;
  210.             _ofnFile.lpstrFileTitle = _szFileTitle;
  211.             _ofnFile.nMaxFileTitle = MAX_PATH;
  212.             _ofnFile.lpstrTitle = TEXT("Open DocFile");
  213.             _ofnFile.lpstrDefExt = NULL;
  214.             _ofnFile.Flags = OFN_HIDEREADONLY;
  215.         }
  216.         break;
  217.     case WM_SETFOCUS:
  218.         {
  219.             if (_hlb)
  220.             {
  221.                 SetFocus(_hlb);
  222.             }
  223.         break;
  224.         }
  225.     case WM_MEASUREITEM:
  226.         {
  227.             LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT) lParam;
  228.             if (BITMAPHEIGHT < _tm.tmHeight + _tm.tmExternalLeading)
  229.             {
  230.                 lpmis->itemHeight = _tm.tmHeight + _tm.tmExternalLeading;
  231.             }
  232.             else
  233.             {
  234.                 lpmis->itemHeight = BITMAPHEIGHT;
  235.             }
  236.             lpmis->itemWidth = _wWidth;
  237.             return(TRUE);
  238.         }
  239.     case WM_DELETEITEM:
  240.         if (IDC_LISTBOX == wParam)
  241.         {
  242.             DeleteElement((LISTBOXELEMENT *)((LPDELETEITEMSTRUCT)lParam)->itemData);
  243.         }
  244.         break;
  245.     case WM_DRAWITEM:
  246.         {
  247.             LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) lParam;
  248.             if (-1 == lpdis->itemID)
  249.             {
  250.                 // no items in the listbox
  251.                 break;
  252.             }
  253.             // draw the item
  254.             switch (lpdis->itemAction)
  255.             {
  256.             case ODA_SELECT:
  257.             case ODA_DRAWENTIRE:
  258.                 {
  259.                     // draw the listbox item
  260.  
  261.                     LISTBOXELEMENT * plbe = (LISTBOXELEMENT *) lpdis->itemData;
  262.                     assert(plbe);
  263.  
  264.                     // compute the starting point
  265.                     int x = lpdis->rcItem.left + plbe->uIndent * INDENT;
  266.                     int y = lpdis->rcItem.top;
  267.  
  268.                     // paint the bitmap
  269.                     HDC hMemDC = CreateCompatibleDC(lpdis->hDC);
  270.                     HBITMAP hbmp;
  271.                     switch (plbe->uType)
  272.                     {
  273.                     case LBE_STORAGE:
  274.                         hbmp = _hbmpStorage;
  275.                         break;
  276.                     case LBE_STREAM:
  277.                         hbmp = _hbmpStream;
  278.                         break;
  279.                     default:
  280.                         assert(!"Unsupported type");
  281.                         hbmp = _hbmpStream;
  282.                         break;
  283.                     }
  284.                     HBITMAP hbmpOld = (HBITMAP) SelectObject(hMemDC, hbmp);
  285.                     int nBitmap = ((lpdis->itemState & ODS_SELECTED) ? 0 : 2) +
  286.                         plbe->fOpen;
  287.                     BitBlt(
  288.                         lpdis->hDC,
  289.                         x,
  290.                         y,
  291.                         BITMAPWIDTH,
  292.                         _cyBitmap,
  293.                         hMemDC,
  294.                         nBitmap * BITMAPWIDTH, 0, SRCCOPY);
  295.                     SelectObject(hMemDC, hbmpOld);
  296.                     DeleteDC(hMemDC);
  297.                     x += BITMAPWIDTH;
  298.  
  299.                     // paint the text
  300.                     SIZE sizeText;
  301.                     RECT rcItem = lpdis->rcItem;
  302.                     rcItem.left = x;
  303.  
  304.                     // Note that pwcsName is an OLEStr and
  305.                     // is therefore always wide under WIN32.
  306.                     GetTextExtentPoint32W(
  307.                         lpdis->hDC,
  308.                         plbe->pwcsName,
  309.                         wcslen(plbe->pwcsName),
  310.                         &sizeText);
  311.                     rcItem.right = x + sizeText.cx;
  312.                     COLORREF crOldText = SetTextColor(
  313.                         lpdis->hDC,
  314.                         (lpdis->itemState & ODS_SELECTED) ? _crTextHigh : _crTextNorm);
  315.                     COLORREF crOldBack = SetBkColor(
  316.                         lpdis->hDC,
  317.                         (lpdis->itemState & ODS_SELECTED) ? _crBkHigh : _crBkNorm);
  318.                     ExtTextOutW(
  319.                         lpdis->hDC,
  320.                         x,
  321.                         y,
  322.                         ETO_OPAQUE | ETO_CLIPPED,
  323.                         &rcItem,
  324.                         plbe->pwcsName,
  325.                         wcslen(plbe->pwcsName),
  326.                         NULL);
  327.                     SetTextColor(lpdis->hDC, crOldText);
  328.                     SetBkColor(lpdis->hDC, crOldBack);
  329.                 }
  330.                 break;
  331.             case ODA_FOCUS:
  332.                 break;
  333.             }
  334.             return(TRUE);
  335.         }
  336.     case WM_VKEYTOITEM:
  337.         if ((HWND)lParam == _hlb)
  338.         {
  339.             if (LOWORD(wParam) == VK_RETURN)
  340.             {
  341.                 if(SendMessage(_hlb, LB_GETCOUNT, 0, 0))
  342.                 {
  343.                     Toggle(SendMessage(_hlb, LB_GETCURSEL, 0, 0));
  344.                     InvalidateRect(_hlb, NULL, FALSE);
  345.                 }
  346.                 return(-2);
  347.             }
  348.             return(-1);
  349.         }
  350.         break;
  351.     case WM_SIZE:
  352.         {
  353.             _wWidth = LOWORD(lParam);
  354.             WORD wHeight = HIWORD(lParam);
  355.             if (_hlb)
  356.             {
  357.                 SetWindowPos(_hlb, NULL, 0, 0, _wWidth, wHeight, SWP_NOMOVE | SWP_NOZORDER);
  358.             }
  359.             break;
  360.         }
  361.     case WM_COMMAND:
  362.         if ((LOWORD(wParam) == IDC_LISTBOX) && ((HWND) lParam == _hlb))
  363.         {
  364.             switch (HIWORD(wParam))
  365.             {
  366.                 case LBN_DBLCLK:
  367.                     {
  368.                         if(SendMessage(_hlb, LB_GETCOUNT, 0, 0))
  369.                         {
  370.                             Toggle(SendMessage(_hlb, LB_GETCURSEL, 0, 0));
  371.                             InvalidateRect(_hlb, NULL, FALSE);
  372.                         }
  373.                     }
  374.                     break;
  375.                 default:
  376.                     break;
  377.             }
  378.         }
  379.         return DoMenu(wParam, lParam);
  380.     case WM_QUIT:
  381.     case WM_CLOSE:
  382.     default:
  383.         return(DefWindowProc(_hwnd, uMsg, wParam, lParam));
  384.     }
  385.     return(FALSE);
  386. }
  387.  
  388. //+---------------------------------------------------------------------------
  389. //
  390. //  Member:     CMainWindow::DoMenu
  391. //
  392. //  Synopsis:   implements the main menu commands
  393. //
  394. //  Arguments:  [wParam] - first window parameter
  395. //              [lParam] - second window parameter
  396. //
  397. //  History:    6-23-94   stevebl   Created
  398. //
  399. //----------------------------------------------------------------------------
  400.  
  401. LRESULT CMainWindow::DoMenu(WPARAM wParam, LPARAM lParam)
  402. {
  403.     switch (LOWORD(wParam))
  404.     {
  405.     case IDM_OPEN:
  406.         if (!GetOpenFileName((LPOPENFILENAME)&_ofnFile))
  407.         {
  408.             return(FALSE);
  409.         }
  410.         OpenFile();
  411.         break;
  412.     case IDM_CLOSE:
  413.         SendMessage(_hlb, LB_RESETCONTENT, 0, 0);
  414.         break;
  415.     case IDM_EXPAND:
  416.         if(SendMessage(_hlb, LB_GETCOUNT, 0, 0))
  417.         {
  418.             Expand(SendMessage(_hlb, LB_GETCURSEL, 0, 0));
  419.             InvalidateRect(_hlb, NULL, FALSE);
  420.         }
  421.         break;
  422.     case IDM_EXPANDBRANCH:
  423.         if(SendMessage(_hlb, LB_GETCOUNT, 0, 0))
  424.         {
  425.             ExpandAll(SendMessage(_hlb, LB_GETCURSEL, 0, 0));
  426.             InvalidateRect(_hlb, NULL, FALSE);
  427.         }
  428.         break;
  429.     case IDM_EXPANDALL:
  430.         if(SendMessage(_hlb, LB_GETCOUNT, 0, 0))
  431.         {
  432.             ExpandAll(0);
  433.             InvalidateRect(_hlb, NULL, FALSE);
  434.         }
  435.         break;
  436.     case IDM_COLLAPSE:
  437.         if(SendMessage(_hlb, LB_GETCOUNT, 0, 0))
  438.         {
  439.             Collapse(SendMessage(_hlb, LB_GETCURSEL, 0, 0));
  440.             InvalidateRect(_hlb, NULL, FALSE);
  441.         }
  442.         break;
  443.     case IDM_COLLAPSEALL:
  444.         if(SendMessage(_hlb, LB_GETCOUNT, 0, 0))
  445.         {
  446.             Collapse(0);
  447.             SendMessage(_hlb, LB_SETCURSEL, 0, 0);
  448.             InvalidateRect(_hlb, NULL, FALSE);
  449.         }
  450.         break;
  451.     case IDM_TOGGLE:
  452.         if (SendMessage(_hlb, LB_GETCOUNT, 0, 0))
  453.         {
  454.             Toggle(SendMessage(_hlb, LB_GETCURSEL, 0, 0));
  455.             InvalidateRect(_hlb, NULL, FALSE);
  456.         }
  457.     case IDM_EXIT:
  458.         SendMessage(_hwnd, WM_CLOSE, 0, 0);
  459.         break;
  460.     case IDM_HELP:
  461.         if (!Exists(_szHelpFile))
  462.         {
  463.             MessageBoxFromStringIds(
  464.                 _hwnd,
  465.                 _hInstance,
  466.                 IDS_NOHELPFILE,
  467.                 IDS_ERROR,
  468.                 MB_OK | MB_ICONEXCLAMATION);
  469.         }
  470.         else
  471.         {
  472.             WinHelp(_hwnd, _szHelpFile, HELP_CONTEXT, 3);
  473.         }
  474.         break;
  475.     case IDM_ABOUT:
  476.         {
  477.             CAbout dlgAbout;
  478.             dlgAbout.ShowDialog(_hInstance, MAKEINTRESOURCE(IDM_ABOUT), _hwnd);
  479.         }
  480.         break;
  481.     default:
  482.         return(DefWindowProc(_hwnd, WM_COMMAND, wParam, lParam));
  483.     }
  484.     return(FALSE);
  485. }
  486.  
  487. //+---------------------------------------------------------------------------
  488. //
  489. //  Member:     CMainWindow::Expand
  490. //
  491. //  Synopsis:   Expands a level of the tree.
  492. //
  493. //  Arguments:  [lIndex] - index of the item that needs to be expanded
  494. //
  495. //  History:    6-23-94   stevebl   Created
  496. //
  497. //----------------------------------------------------------------------------
  498.  
  499. void CMainWindow::Expand(long lIndex)
  500. {
  501.     LISTBOXELEMENT * pElement = (LISTBOXELEMENT *) SendMessage(_hlb, LB_GETITEMDATA, lIndex, 0);
  502.     if (pElement->fOpen)
  503.     {
  504.         // this element has already been expanded
  505.         return;
  506.     }
  507.     SendMessage(_hlb, WM_SETREDRAW, FALSE, 0);
  508.     switch (pElement->uType)
  509.     {
  510.     case LBE_STORAGE:
  511.         {
  512.             // create entries for all of its children
  513.             IStorage * pstg = (IStorage *) pElement->pInterface;
  514.             IEnumSTATSTG * penumStatStg;
  515.             STATSTG statstg;
  516.             HRESULT hr = pstg->EnumElements(0, NULL, 0, &penumStatStg);
  517.             if (SUCCEEDED(hr))
  518.             {
  519.                 pElement->fOpen = TRUE;
  520.                 pElement->nChildren = 0;
  521.                 while (hr != S_FALSE)
  522.                 {
  523.                     hr = penumStatStg->Next(1, &statstg, NULL);
  524.                     if (FAILED(hr))
  525.                     {
  526.                         MessageBoxFromStringIdsAndArgs(
  527.                             _hwnd,
  528.                             _hInstance,
  529.                             IDS_ENUMSTATSTGFAILED,
  530.                             IDS_ERROR,
  531.                             MB_OK | MB_ICONEXCLAMATION,
  532.                             hr);
  533.                     }
  534.                     else if (S_OK == hr)
  535.                     {
  536.                         // retrieved another member from the list
  537.                         LISTBOXELEMENT * plbe;
  538.                         switch (statstg.type)
  539.                         {
  540.                         case STGTY_STORAGE:
  541.                             {
  542.                                 IStorage * pstg2;
  543.                                 hr = pstg->OpenStorage(
  544.                                     statstg.pwcsName,
  545.                                     NULL,
  546.                                     STGM_READ | STGM_SHARE_EXCLUSIVE,
  547.                                     NULL,
  548.                                     0,
  549.                                     &pstg2);
  550.                                 if (SUCCEEDED(hr))
  551.                                 {
  552.                                     plbe = CreateStorageElement(pstg2);
  553.                                 }
  554.                                 else
  555.                                 {
  556.                                     MessageBoxFromStringIdsAndArgs(
  557.                                         _hwnd,
  558.                                         _hInstance,
  559.                                         IDS_OPENSTORAGEFAILED,
  560.                                         IDS_ERROR,
  561.                                         MB_OK | MB_ICONEXCLAMATION,
  562.                                         hr);
  563.                                     plbe = NULL;
  564.                                 }
  565.                             }
  566.                             break;
  567.                         case STGTY_STREAM:
  568.                             {
  569.                                 IStream * pstm;
  570.                                 hr = pstg->OpenStream(
  571.                                     statstg.pwcsName,
  572.                                     0,
  573.                                     STGM_READ | STGM_SHARE_EXCLUSIVE,
  574.                                     0,
  575.                                     &pstm);
  576.                                 if (SUCCEEDED(hr))
  577.                                 {
  578.                                     plbe = CreateStreamElement(pstm);
  579.                                 }
  580.                                 else
  581.                                 {
  582.                                     MessageBoxFromStringIdsAndArgs(
  583.                                         _hwnd,
  584.                                         _hInstance,
  585.                                         IDS_OPENSTREAMFAILED,
  586.                                         IDS_ERROR,
  587.                                         MB_OK | MB_ICONEXCLAMATION,
  588.                                         hr);
  589.                                     plbe = NULL;
  590.                                 }
  591.                             }
  592.                             break;
  593.                         }
  594.                         if (plbe)
  595.                         {
  596.                             plbe->pwcsName = statstg.pwcsName;
  597.                             plbe->uIndent = pElement->uIndent + 1;
  598.                             pElement->nChildren++;
  599.                             if (SendMessage(_hlb, LB_INSERTSTRING, lIndex + pElement->nChildren, (LPARAM) plbe) == LB_ERRSPACE)
  600.                             {
  601.                                 MessageBoxFromStringIds(
  602.                                     _hwnd,
  603.                                     _hInstance,
  604.                                     IDS_INSERTSTRINGFAILED,
  605.                                     IDS_ERROR,
  606.                                     MB_OK | MB_ICONEXCLAMATION);
  607.                                 DeleteElement(plbe);
  608.                                 pElement->nChildren--;
  609.                             }
  610.                         }
  611.                     }
  612.                 }
  613.                 penumStatStg->Release();
  614.             }
  615.             else
  616.             {
  617.                 MessageBoxFromStringIdsAndArgs(
  618.                     _hwnd,
  619.                     _hInstance,
  620.                     IDS_ENUMELEMENTSFAILED,
  621.                     IDS_ERROR,
  622.                     MB_OK | MB_ICONEXCLAMATION,
  623.                     hr);
  624.             }
  625.         }
  626.         break;
  627.     case LBE_STREAM:
  628.         // streams are only expanded if they are the currently selected list item
  629.         if (SendMessage(_hlb, LB_GETCURSEL, 0, 0) == lIndex)
  630.         {
  631.             // open stream
  632.             CStreamView * psv = new CStreamView(_hlb, pElement);
  633.             if (psv)
  634.             {
  635.                 pElement->fOpen = psv->InitInstance(_hInstance, SW_SHOWNORMAL);
  636.                 if (pElement->fOpen)
  637.                 {
  638.                     pElement->hwndView = psv->GetHwnd();
  639.                     SetFocus(pElement->hwndView);
  640.                 }
  641.             }
  642.         }
  643.         break;
  644.     }
  645.     SendMessage(_hlb, WM_SETREDRAW, TRUE, 0);
  646. }
  647.  
  648. //+---------------------------------------------------------------------------
  649. //
  650. //  Member:     CMainWindow::Collapse
  651. //
  652. //  Synopsis:   collapses a level of the tree
  653. //
  654. //  Arguments:  [lIndex] - index of the item to be collapsed
  655. //
  656. //  History:    6-23-94   stevebl   Created
  657. //
  658. //----------------------------------------------------------------------------
  659.  
  660. void CMainWindow::Collapse(long lIndex)
  661. {
  662.     LISTBOXELEMENT * pElement = (LISTBOXELEMENT *) SendMessage(_hlb, LB_GETITEMDATA, lIndex, 0);
  663.     if (pElement->fOpen)
  664.     {
  665.         switch (pElement->uType)
  666.         {
  667.         case LBE_STORAGE:
  668.             while (pElement->nChildren--)
  669.             {
  670.                 Collapse(lIndex + 1);
  671.                 SendMessage(_hlb, LB_DELETESTRING, lIndex + 1, 0);
  672.             }
  673.             break;
  674.         case LBE_STREAM:
  675.             if (pElement->fOpen)
  676.             {
  677.                 DestroyWindow(pElement->hwndView);
  678.             }
  679.             break;
  680.         }
  681.         pElement->fOpen = FALSE;
  682.     }
  683. }
  684.  
  685. //+---------------------------------------------------------------------------
  686. //
  687. //  Member:     CMainWindow::ExpandAll
  688. //
  689. //  Synopsis:   expands the current item and all its children
  690. //
  691. //  Arguments:  [lIndex] - index of the item to be expanded
  692. //
  693. //  History:    6-23-94   stevebl   Created
  694. //
  695. //----------------------------------------------------------------------------
  696.  
  697. void CMainWindow::ExpandAll(long lIndex)
  698. {
  699.     LISTBOXELEMENT * pElement = (LISTBOXELEMENT *) SendMessage(_hlb, LB_GETITEMDATA, lIndex, 0);
  700.     Expand(lIndex);
  701.     if (pElement->uType == LBE_STORAGE)
  702.     {
  703.         unsigned nChildren = pElement->nChildren;
  704.         while (nChildren--)
  705.         {
  706.             ExpandAll(lIndex + 1 + nChildren);
  707.         }
  708.     }
  709. }
  710.  
  711. //+---------------------------------------------------------------------------
  712. //
  713. //  Member:     CMainWindow::Toggle
  714. //
  715. //  Synopsis:   toggles a node - expanding or collapsing as appropriate
  716. //
  717. //  Arguments:  [lIndex] - index of the node
  718. //
  719. //  History:    6-25-94   stevebl   Created
  720. //
  721. //----------------------------------------------------------------------------
  722.  
  723. void CMainWindow::Toggle(long lIndex)
  724. {
  725.     LISTBOXELEMENT * pElement = (LISTBOXELEMENT *) SendMessage(_hlb, LB_GETITEMDATA, lIndex, 0);
  726.     if (pElement->fOpen)
  727.     {
  728.         Collapse(lIndex);
  729.     }
  730.     else
  731.     {
  732.         Expand(lIndex);
  733.     }
  734. }
  735.  
  736. //+---------------------------------------------------------------------------
  737. //
  738. //  Member:     CMainWindow::CreateStreamElement
  739. //
  740. //  Synopsis:   turns an IStream pointer into a listbox element
  741. //
  742. //  Arguments:  [pstm] - IStream pointer
  743. //
  744. //  Returns:    pointer to the newly created element
  745. //              (NULL on failure)
  746. //
  747. //  History:    6-23-94   stevebl   Created
  748. //
  749. //----------------------------------------------------------------------------
  750.  
  751. LISTBOXELEMENT * CMainWindow::CreateStreamElement(IStream * pstm)
  752. {
  753.     LISTBOXELEMENT * plbe = new LISTBOXELEMENT;
  754.     if (plbe)
  755.     {
  756.         plbe->uType = LBE_STREAM;
  757.         plbe->fOpen = FALSE;
  758.         plbe->pInterface = (void *) pstm;
  759.         plbe->uIndent = 0;
  760.         plbe->hwndView = NULL;
  761.     }
  762.     else
  763.     {
  764.         MessageBoxFromStringIds(
  765.             _hwnd,
  766.             _hInstance,
  767.             IDS_OUTOFMEMORY,
  768.             IDS_ERROR,
  769.             MB_OK | MB_ICONEXCLAMATION);
  770.     }
  771.     return(plbe);
  772. }
  773.  
  774. //+---------------------------------------------------------------------------
  775. //
  776. //  Member:     CMainWindow::CreateStorageElement
  777. //
  778. //  Synopsis:   turns an IStorage pointer into a listbox element
  779. //
  780. //  Arguments:  [pstg] - IStorage pointer
  781. //
  782. //  Returns:    pointer to the newly created element
  783. //              (NULL on failure)
  784. //
  785. //  History:    6-23-94   stevebl   Created
  786. //
  787. //----------------------------------------------------------------------------
  788.  
  789. LISTBOXELEMENT * CMainWindow::CreateStorageElement(IStorage * pstg)
  790. {
  791.     LISTBOXELEMENT * plbe = new LISTBOXELEMENT;
  792.     if (plbe)
  793.     {
  794.         plbe->uType = LBE_STORAGE;
  795.         plbe->fOpen = FALSE;
  796.         plbe->pInterface = (void *) pstg;
  797.         plbe->uIndent = 0;
  798.         plbe->nChildren = 0;
  799.     }
  800.     else
  801.     {
  802.         MessageBoxFromStringIds(
  803.             _hwnd,
  804.             _hInstance,
  805.             IDS_OUTOFMEMORY,
  806.             IDS_ERROR,
  807.             MB_OK | MB_ICONEXCLAMATION);
  808.     }
  809.     return(plbe);
  810. }
  811.  
  812. //+---------------------------------------------------------------------------
  813. //
  814. //  Member:     CMainWindow::DeleteElement
  815. //
  816. //  Synopsis:   deletes a listbox element and it's associated data
  817. //
  818. //  Arguments:  [plbe] - pointer to the element
  819. //
  820. //  History:    6-23-94   stevebl   Created
  821. //
  822. //  Notes:      This doesn't remove it from the list, it just frees up
  823. //              the LISTBOXELEMENT pointer and it's data.
  824. //
  825. //----------------------------------------------------------------------------
  826.  
  827. void CMainWindow::DeleteElement(LISTBOXELEMENT * plbe)
  828. {
  829.  
  830.     switch (plbe->uType)
  831.     {
  832.     case LBE_STORAGE:
  833.         ((IStorage *) plbe->pInterface)->Release();
  834.         break;
  835.     case LBE_STREAM:
  836.         if (plbe->fOpen)
  837.         {
  838.             DestroyWindow(plbe->hwndView);
  839.         }
  840.         ((IStream *) plbe->pInterface)->Release();
  841.         break;
  842.     }
  843.     LPMALLOC pMalloc;
  844.     CoGetMalloc(MEMCTX_TASK, &pMalloc);
  845.     pMalloc->Free(plbe->pwcsName);
  846.     pMalloc->Release();
  847.     delete(plbe);
  848. }
  849.  
  850. //+---------------------------------------------------------------------------
  851. //
  852. //  Member:     CMainWindow::LoadBitmaps
  853. //
  854. //  Synopsis:   loads the Storage and Stream bitmap arrays
  855. //
  856. //  Returns:    TRUE on success
  857. //              FALSE on failure
  858. //
  859. //  Modifies:   _hbmpStorage and _hbmpStream
  860. //
  861. //  History:    6-24-94   stevebl   Created from code used in original DFView
  862. //
  863. //----------------------------------------------------------------------------
  864.  
  865. BOOL CMainWindow::LoadBitmaps(void)
  866. {
  867.     //
  868.     // Get some metrics/info
  869.     //
  870.     UINT cxBitmap = BITMAPWIDTH;
  871.     _cyBitmap = BITMAPHEIGHT;
  872.     if (_cyBitmap < (UINT) _tm.tmHeight + _tm.tmExternalLeading)
  873.     {
  874.         _cyBitmap = _tm.tmHeight + _tm.tmExternalLeading;
  875.     }
  876.     UINT crHigh   = (COLORREF) GetSysColor(COLOR_HIGHLIGHT);
  877.     UINT crNorm   = (COLORREF) GetSysColor(COLOR_WINDOW);
  878.  
  879.     HDC hdc = CreateCompatibleDC(NULL);
  880.     if (!hdc)
  881.     {
  882.         goto ERRLOADBITMAP;
  883.     }
  884.     _hbmpStorage = CreateBitmap(
  885.         4 * cxBitmap,
  886.         _cyBitmap,
  887.         GetDeviceCaps(hdc, PLANES),
  888.         GetDeviceCaps(hdc, BITSPIXEL),
  889.         NULL);
  890.     _hbmpStream = CreateBitmap(
  891.         4 * cxBitmap,
  892.         _cyBitmap,
  893.         GetDeviceCaps(hdc, PLANES),
  894.         GetDeviceCaps (hdc, BITSPIXEL),
  895.         NULL);
  896.    DeleteDC(hdc);
  897.    if (!_hbmpStorage || !_hbmpStream)
  898.    {
  899.         goto ERRLOADBITMAP;
  900.    }
  901.  
  902.     //
  903.     //  Load our bitmaps, and munge them to create
  904.     //  our 4-bitmap "arrays".  Anything RED in the loaded
  905.     //  bitmap will be considered clear.
  906.     //
  907.     if (!LoadAndStretch(
  908.         _hInstance,
  909.         _hbmpStorage,
  910.         MAKEINTRESOURCE(BMP_STORAGE),
  911.         cxBitmap,
  912.         _cyBitmap,
  913.         crHigh,
  914.         crNorm))
  915.     {
  916.         goto ERRLOADBITMAP;
  917.     }
  918.     if (!LoadAndStretch(
  919.         _hInstance,
  920.         _hbmpStream,
  921.         MAKEINTRESOURCE(BMP_STREAM),
  922.         cxBitmap,
  923.         _cyBitmap,
  924.         crHigh,
  925.         crNorm))
  926.     {
  927.         goto ERRLOADBITMAP;
  928.     }
  929.     return TRUE;
  930.  
  931. ERRLOADBITMAP:
  932.     //
  933.     // Bitmap loading error.
  934.     //
  935.     DeleteObject(_hbmpStorage);
  936.     DeleteObject(_hbmpStream);
  937.     _hbmpStorage = NULL;
  938.     _hbmpStream = NULL;
  939.  
  940.     return FALSE;
  941. }
  942.  
  943. //+---------------------------------------------------------------------------
  944. //
  945. //  Member:     CMainWindow::OpenFile
  946. //
  947. //  Synopsis:   attempts to open whatever docfile is named by _szFileName;
  948. //
  949. //  History:    6-24-94   stevebl   Created
  950. //
  951. //----------------------------------------------------------------------------
  952.  
  953. void CMainWindow::OpenFile(void)
  954. {
  955.     SendMessage(_hlb, LB_RESETCONTENT, 0, 0);
  956.     IStorage * pstg;
  957. #ifndef UNICODE
  958.     // convert file name to a wide string
  959.     OLECHAR wszFileName[MAX_PATH];
  960.     mbstowcs(wszFileName, _szFileName, MAX_PATH);
  961. #endif
  962.     // get IStorage
  963.     HRESULT hr = StgOpenStorage(
  964. #ifdef UNICODE
  965.         _szFileName,
  966. #else
  967.         wszFileName,
  968. #endif
  969.         NULL,
  970.         STGM_TRANSACTED | STGM_READ | STGM_SHARE_DENY_WRITE,
  971.         NULL,
  972.         0,
  973.         &pstg);
  974.     if (FAILED(hr))
  975.     {
  976.         MessageBoxFromStringIdsAndArgs(
  977.             _hwnd,
  978.             _hInstance,
  979.             IDS_STGOPENSTORAGEFAILED,
  980.             IDS_ERROR,
  981.             MB_OK | MB_ICONEXCLAMATION,
  982. #ifdef UNICODE
  983.             _szFileName
  984. #else
  985.             wszFileName
  986. #endif
  987.             );
  988.         return;
  989.     }
  990.     // Storage was opened successfully.
  991.     LISTBOXELEMENT * plbe = CreateStorageElement(pstg);
  992.     if (plbe)
  993.     {
  994.         IMalloc * pMalloc;
  995.         CoGetMalloc(MEMCTX_TASK, &pMalloc);
  996.         plbe->pwcsName = (LPOLESTR) pMalloc->Alloc(sizeof(OLECHAR) *  (lstrlen(_szFileName) + wcslen(ROOTSTGSTR) + 1));
  997.         pMalloc->Release();
  998.         if (plbe->pwcsName)
  999.         {
  1000.             wcscpy(plbe->pwcsName, ROOTSTGSTR);
  1001. #ifdef UNICODE
  1002.             wcscpy(&plbe->pwcsName[wcslen(ROOTSTGSTR)], _szFileName);
  1003. #else
  1004.             mbstowcs(&plbe->pwcsName[wcslen(ROOTSTGSTR)], _szFileName, strlen(_szFileName) + 1);
  1005. #endif
  1006.         }
  1007.         if (SendMessage(_hlb, LB_INSERTSTRING, 0, (LPARAM) plbe) == LB_ERRSPACE)
  1008.         {
  1009.             MessageBoxFromStringIds(
  1010.                 _hwnd,
  1011.                 _hInstance,
  1012.                 IDS_INSERTSTRINGFAILED,
  1013.                 IDS_ERROR,
  1014.                 MB_OK | MB_ICONEXCLAMATION);
  1015.             DeleteElement(plbe);
  1016.         }
  1017.         else
  1018.         {
  1019.             SendMessage(_hlb, LB_SETCURSEL, 0, 0);
  1020.         }
  1021.     }
  1022. }
  1023.  
  1024. //+---------------------------------------------------------------------------
  1025. //
  1026. //  Function:   Exists
  1027. //
  1028. //  Synopsis:   simple function to test for the existance of a file
  1029. //
  1030. //  History:    6-16-93   stevebl   Created
  1031. //
  1032. //----------------------------------------------------------------------------
  1033.  
  1034. int Exists(TCHAR *sz)
  1035. {
  1036.     HANDLE h;
  1037.     h = CreateFile(sz,
  1038.         GENERIC_READ,
  1039.         FILE_SHARE_READ | FILE_SHARE_WRITE,
  1040.         NULL,
  1041.         OPEN_EXISTING,
  1042.         0,
  1043.         0);
  1044.     if (h != INVALID_HANDLE_VALUE)
  1045.     {
  1046.         CloseHandle(h);
  1047.         return(1);
  1048.     }
  1049.     return (0);
  1050. }
  1051.  
  1052.