MWCLASS.CXX
//+--------------------------------------------------------------------------- 
// 
//  Microsoft Windows 
//  Copyright 1992 - 1998 Microsoft Corporation. 
// 
//  File:       mwclass.cxx 
// 
//  Contents:   implementation for the main window class 
// 
//  Classes:    CMainWindow 
// 
//  Functions:  Exists 
// 
//  History:    6-08-94   stevebl   Created 
// 
//---------------------------------------------------------------------------- 
 
#include "dfv.h" 
#include "mwclass.h" 
#include "about.h" 
#include "bitmaps.h" 
#include "strmvwr.h" 
#include <assert.h> 
 
#define BITMAPWIDTH 16 
#define BITMAPHEIGHT 16 
#define INDENT BITMAPWIDTH 
#define ROOTSTGSTR OLESTR(" \\ - ") 
 
//+--------------------------------------------------------------------------- 
// 
//  Member:     CMainWindow::CMainWindow 
// 
//  Synopsis:   constructor 
// 
//  History:    6-27-94   stevebl   Created 
// 
//---------------------------------------------------------------------------- 
 
CMainWindow::CMainWindow() 
{ 
    _hlb = NULL; 
    _hbmpStorage = _hbmpStream = NULL; 
} 
 
//+--------------------------------------------------------------------------- 
// 
//  Member:     CMainWindow::~CMainWindow 
// 
//  Synopsis:   destructor 
// 
//  History:    6-27-94   stevebl   Created 
// 
//  Notes:      Destruction of the main window indicates that the app should 
//              quit. 
// 
//---------------------------------------------------------------------------- 
 
CMainWindow::~CMainWindow() 
{ 
    DeleteObject(_hbmpStorage); 
    DeleteObject(_hbmpStream); 
    PostQuitMessage(0); 
} 
 
//+--------------------------------------------------------------------------- 
// 
//  Member:     CMainWindow::InitInstance 
// 
//  Synopsis:   Instantiates an instance of the docfile viewer window. 
// 
//  Arguments:  [hInstance] - instance of the app 
//              [nCmdShow]  - command to pass to ShowWindow 
// 
//  Returns:    TRUE on success 
//              FALSE on failure 
// 
//  History:    6-27-94   stevebl   Created 
// 
//  Notes:      This method must be called only once, immediately after 
//              class construction. 
// 
//---------------------------------------------------------------------------- 
 
BOOL CMainWindow::InitInstance(HINSTANCE hInstance, int nCmdShow) 
{ 
    // Note, the Create method sets the _hwnd member for me so I don't 
    // need to set it myself. 
    if (!Create( 
        TEXT(MAIN_WINDOW_CLASS_NAME), 
        TEXT(VER_INTERNALNAME_STR), 
        WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX 
            | WS_MAXIMIZEBOX | WS_THICKFRAME, 
        CW_USEDEFAULT, 
        CW_USEDEFAULT, 
        CW_USEDEFAULT, 
        CW_USEDEFAULT, 
        NULL, 
        NULL, 
        hInstance)) 
    { 
        return(FALSE); 
    } 
 
    ShowWindow(_hwnd, nCmdShow); 
    UpdateWindow(_hwnd); 
 
    // build a path to where the help file should be 
    // (it should be in the same directory as the .EXE) 
    // first get the exe's path 
    DWORD cch = GetModuleFileName(hInstance, _szHelpFile, MAX_PATH); 
    // then back up past the name of the application 
    while (cch > 0 && 
        _szHelpFile[cch - 1] != TEXT('\\') && 
        _szHelpFile[cch - 1] != TEXT('/') && 
        _szHelpFile[cch - 1] != TEXT(':')) 
    { 
        cch--; 
    } 
    // finally copy the help file's name at the end of the path 
    lstrcpy(&_szHelpFile[cch], TEXT(HELPFILE_STR)); 
    return(TRUE); 
} 
 
//+--------------------------------------------------------------------------- 
// 
//  Member:     CMainWindow::WindowProc 
// 
//  Synopsis:   main window procedure 
// 
//  Arguments:  [uMsg]   - Windows message 
//              [wParam] - first message parameter 
//              [lParam] - second message parameter 
// 
//  History:    6-27-94   stevebl   Created 
// 
//  Notes:      See CHlprWindow for a description of how this method gets 
//              called by the global WinProc. 
// 
//---------------------------------------------------------------------------- 
 
LRESULT CMainWindow::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    switch (uMsg) 
    { 
    case WM_CREATE: 
        { 
            RECT rc; 
            GetClientRect(_hwnd, &rc); 
            // record the width before we create the list box 
            _wWidth = (WORD) rc.right; 
 
            HDC hdc = GetDC(_hwnd); 
            GetTextMetrics(hdc, &_tm); 
            ReleaseDC(_hwnd, hdc); 
 
            // create the child listbox 
            _hlb = CreateWindow( 
                TEXT("listbox"), 
                TEXT(""), 
                LBS_OWNERDRAWFIXED | 
                    WS_CHILD | 
                    WS_VISIBLE | 
                    WS_VSCROLL | 
                    LBS_NOTIFY | 
                    LBS_NOINTEGRALHEIGHT | 
                    LBS_WANTKEYBOARDINPUT, 
                0, 
                0, 
                rc.right, 
                rc.bottom, 
                _hwnd, 
                (HMENU) IDC_LISTBOX, 
                _hInstance, 
                NULL); 
            if (NULL == _hlb) 
            { 
                // abort window creation 
                return(-1); 
            } 
            SetFocus(_hlb); 
 
            if (!LoadBitmaps()) 
            { 
                MessageBoxFromStringIds( 
                    _hwnd, 
                    _hInstance, 
                    IDS_LOADBITMAPSFAILED, 
                    IDS_ERROR, 
                    MB_OK | MB_ICONEXCLAMATION); 
                return(-1); 
            } 
            _crTextHigh = GetSysColor(COLOR_HIGHLIGHTTEXT); 
            _crTextNorm = GetSysColor(COLOR_WINDOWTEXT); 
            _crBkHigh = GetSysColor(COLOR_HIGHLIGHT); 
            _crBkNorm = GetSysColor(COLOR_WINDOW); 
 
            // Fill in the File's OPENFILENAME structure 
            _szFileName[0] = 0; 
            _szFileTitle[0] = 0; 
            _ofnFile.lStructSize = sizeof(OPENFILENAME); 
            _ofnFile.hwndOwner = _hwnd; 
            _ofnFile.lpstrFilter = TEXT("All Files (*.*)\0*.*\0Doc Files (*.DFL;*.OL?)\0*.DFL;*.OL;\0"); 
            _ofnFile.lpstrCustomFilter = NULL; 
            _ofnFile.nMaxCustFilter = 0; 
            _ofnFile.nFilterIndex = 1; 
            _ofnFile.lpstrFile = _szFileName; 
            _ofnFile.nMaxFile = MAX_PATH; 
            _ofnFile.lpstrInitialDir = NULL; 
            _ofnFile.lpstrFileTitle = _szFileTitle; 
            _ofnFile.nMaxFileTitle = MAX_PATH; 
            _ofnFile.lpstrTitle = TEXT("Open DocFile"); 
            _ofnFile.lpstrDefExt = NULL; 
            _ofnFile.Flags = OFN_HIDEREADONLY; 
        } 
        break; 
    case WM_SETFOCUS: 
        { 
            if (_hlb) 
            { 
                SetFocus(_hlb); 
            } 
        break; 
        } 
    case WM_MEASUREITEM: 
        { 
            LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT) lParam; 
            if (BITMAPHEIGHT < _tm.tmHeight + _tm.tmExternalLeading) 
            { 
                lpmis->itemHeight = _tm.tmHeight + _tm.tmExternalLeading; 
            } 
            else 
            { 
                lpmis->itemHeight = BITMAPHEIGHT; 
            } 
            lpmis->itemWidth = _wWidth; 
            return(TRUE); 
        } 
    case WM_DELETEITEM: 
        if (IDC_LISTBOX == wParam) 
        { 
            DeleteElement((LISTBOXELEMENT *)((LPDELETEITEMSTRUCT)lParam)->itemData); 
        } 
        break; 
    case WM_DRAWITEM: 
        { 
            LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) lParam; 
            if (-1 == lpdis->itemID) 
            { 
                // no items in the listbox 
                break; 
            } 
            // draw the item 
            switch (lpdis->itemAction) 
            { 
            case ODA_SELECT: 
            case ODA_DRAWENTIRE: 
                { 
                    // draw the listbox item 
 
                    LISTBOXELEMENT * plbe = (LISTBOXELEMENT *) lpdis->itemData; 
                    assert(plbe); 
 
                    // compute the starting point 
                    int x = lpdis->rcItem.left + plbe->uIndent * INDENT; 
                    int y = lpdis->rcItem.top; 
 
                    // paint the bitmap 
                    HDC hMemDC = CreateCompatibleDC(lpdis->hDC); 
                    HBITMAP hbmp; 
                    switch (plbe->uType) 
                    { 
                    case LBE_STORAGE: 
                        hbmp = _hbmpStorage; 
                        break; 
                    case LBE_STREAM: 
                        hbmp = _hbmpStream; 
                        break; 
                    default: 
                        assert(!"Unsupported type"); 
                        hbmp = _hbmpStream; 
                        break; 
                    } 
                    HBITMAP hbmpOld = (HBITMAP) SelectObject(hMemDC, hbmp); 
                    int nBitmap = ((lpdis->itemState & ODS_SELECTED) ? 0 : 2) + 
                        plbe->fOpen; 
                    BitBlt( 
                        lpdis->hDC, 
                        x, 
                        y, 
                        BITMAPWIDTH, 
                        _cyBitmap, 
                        hMemDC, 
                        nBitmap * BITMAPWIDTH, 0, SRCCOPY); 
                    SelectObject(hMemDC, hbmpOld); 
                    DeleteDC(hMemDC); 
                    x += BITMAPWIDTH; 
 
                    // paint the text 
                    SIZE sizeText; 
                    RECT rcItem = lpdis->rcItem; 
                    rcItem.left = x; 
 
                    // Note that pwcsName is an OLEStr and 
                    // is therefore always wide under WIN32. 
                    GetTextExtentPoint32W( 
                        lpdis->hDC, 
                        plbe->pwcsName, 
                        wcslen(plbe->pwcsName), 
                        &sizeText); 
                    rcItem.right = x + sizeText.cx; 
                    COLORREF crOldText = SetTextColor( 
                        lpdis->hDC, 
                        (lpdis->itemState & ODS_SELECTED) ? _crTextHigh : _crTextNorm); 
                    COLORREF crOldBack = SetBkColor( 
                        lpdis->hDC, 
                        (lpdis->itemState & ODS_SELECTED) ? _crBkHigh : _crBkNorm); 
                    ExtTextOutW( 
                        lpdis->hDC, 
                        x, 
                        y, 
                        ETO_OPAQUE | ETO_CLIPPED, 
                        &rcItem, 
                        plbe->pwcsName, 
                        wcslen(plbe->pwcsName), 
                        NULL); 
                    SetTextColor(lpdis->hDC, crOldText); 
                    SetBkColor(lpdis->hDC, crOldBack); 
                } 
                break; 
            case ODA_FOCUS: 
                break; 
            } 
            return(TRUE); 
        } 
    case WM_VKEYTOITEM: 
        if ((HWND)lParam == _hlb) 
        { 
            if (LOWORD(wParam) == VK_RETURN) 
            { 
                if(SendMessage(_hlb, LB_GETCOUNT, 0, 0)) 
                { 
                    Toggle(SendMessage(_hlb, LB_GETCURSEL, 0, 0)); 
                    InvalidateRect(_hlb, NULL, FALSE); 
                } 
                return(-2); 
            } 
            return(-1); 
        } 
        break; 
    case WM_SIZE: 
        { 
            _wWidth = LOWORD(lParam); 
            WORD wHeight = HIWORD(lParam); 
            if (_hlb) 
            { 
                SetWindowPos(_hlb, NULL, 0, 0, _wWidth, wHeight, SWP_NOMOVE | SWP_NOZORDER); 
            } 
            break; 
        } 
    case WM_COMMAND: 
        if ((LOWORD(wParam) == IDC_LISTBOX) && ((HWND) lParam == _hlb)) 
        { 
            switch (HIWORD(wParam)) 
            { 
                case LBN_DBLCLK: 
                    { 
                        if(SendMessage(_hlb, LB_GETCOUNT, 0, 0)) 
                        { 
                            Toggle(SendMessage(_hlb, LB_GETCURSEL, 0, 0)); 
                            InvalidateRect(_hlb, NULL, FALSE); 
                        } 
                    } 
                    break; 
                default: 
                    break; 
            } 
        } 
        return DoMenu(wParam, lParam); 
    case WM_QUIT: 
    case WM_CLOSE: 
    default: 
        return(DefWindowProc(_hwnd, uMsg, wParam, lParam)); 
    } 
    return(FALSE); 
} 
 
//+--------------------------------------------------------------------------- 
// 
//  Member:     CMainWindow::DoMenu 
// 
//  Synopsis:   implements the main menu commands 
// 
//  Arguments:  [wParam] - first window parameter 
//              [lParam] - second window parameter 
// 
//  History:    6-23-94   stevebl   Created 
// 
//---------------------------------------------------------------------------- 
 
LRESULT CMainWindow::DoMenu(WPARAM wParam, LPARAM lParam) 
{ 
    switch (LOWORD(wParam)) 
    { 
    case IDM_OPEN: 
        if (!GetOpenFileName((LPOPENFILENAME)&_ofnFile)) 
        { 
            return(FALSE); 
        } 
        OpenFile(); 
        break; 
    case IDM_CLOSE: 
        SendMessage(_hlb, LB_RESETCONTENT, 0, 0); 
        break; 
    case IDM_EXPAND: 
        if(SendMessage(_hlb, LB_GETCOUNT, 0, 0)) 
        { 
            Expand(SendMessage(_hlb, LB_GETCURSEL, 0, 0)); 
            InvalidateRect(_hlb, NULL, FALSE); 
        } 
        break; 
    case IDM_EXPANDBRANCH: 
        if(SendMessage(_hlb, LB_GETCOUNT, 0, 0)) 
        { 
            ExpandAll(SendMessage(_hlb, LB_GETCURSEL, 0, 0)); 
            InvalidateRect(_hlb, NULL, FALSE); 
        } 
        break; 
    case IDM_EXPANDALL: 
        if(SendMessage(_hlb, LB_GETCOUNT, 0, 0)) 
        { 
            ExpandAll(0); 
            InvalidateRect(_hlb, NULL, FALSE); 
        } 
        break; 
    case IDM_COLLAPSE: 
        if(SendMessage(_hlb, LB_GETCOUNT, 0, 0)) 
        { 
            Collapse(SendMessage(_hlb, LB_GETCURSEL, 0, 0)); 
            InvalidateRect(_hlb, NULL, FALSE); 
        } 
        break; 
    case IDM_COLLAPSEALL: 
        if(SendMessage(_hlb, LB_GETCOUNT, 0, 0)) 
        { 
            Collapse(0); 
            SendMessage(_hlb, LB_SETCURSEL, 0, 0); 
            InvalidateRect(_hlb, NULL, FALSE); 
        } 
        break; 
    case IDM_TOGGLE: 
        if (SendMessage(_hlb, LB_GETCOUNT, 0, 0)) 
        { 
            Toggle(SendMessage(_hlb, LB_GETCURSEL, 0, 0)); 
            InvalidateRect(_hlb, NULL, FALSE); 
        } 
    case IDM_EXIT: 
        SendMessage(_hwnd, WM_CLOSE, 0, 0); 
        break; 
    case IDM_HELP: 
        if (!Exists(_szHelpFile)) 
        { 
            MessageBoxFromStringIds( 
                _hwnd, 
                _hInstance, 
                IDS_NOHELPFILE, 
                IDS_ERROR, 
                MB_OK | MB_ICONEXCLAMATION); 
        } 
        else 
        { 
            WinHelp(_hwnd, _szHelpFile, HELP_CONTEXT, 3); 
        } 
        break; 
    case IDM_ABOUT: 
        { 
            CAbout dlgAbout; 
            dlgAbout.ShowDialog(_hInstance, MAKEINTRESOURCE(IDM_ABOUT), _hwnd); 
        } 
        break; 
    default: 
        return(DefWindowProc(_hwnd, WM_COMMAND, wParam, lParam)); 
    } 
    return(FALSE); 
} 
 
//+--------------------------------------------------------------------------- 
// 
//  Member:     CMainWindow::Expand 
// 
//  Synopsis:   Expands a level of the tree. 
// 
//  Arguments:  [lIndex] - index of the item that needs to be expanded 
// 
//  History:    6-23-94   stevebl   Created 
// 
//---------------------------------------------------------------------------- 
 
void CMainWindow::Expand(long lIndex) 
{ 
    LISTBOXELEMENT * pElement = (LISTBOXELEMENT *) SendMessage(_hlb, LB_GETITEMDATA, lIndex, 0); 
    if (pElement->fOpen) 
    { 
        // this element has already been expanded 
        return; 
    } 
    SendMessage(_hlb, WM_SETREDRAW, FALSE, 0); 
    switch (pElement->uType) 
    { 
    case LBE_STORAGE: 
        { 
            // create entries for all of its children 
            IStorage * pstg = (IStorage *) pElement->pInterface; 
            IEnumSTATSTG * penumStatStg; 
            STATSTG statstg; 
            HRESULT hr = pstg->EnumElements(0, NULL, 0, &penumStatStg); 
            if (SUCCEEDED(hr)) 
            { 
                pElement->fOpen = TRUE; 
                pElement->nChildren = 0; 
                while (hr != S_FALSE) 
                { 
                    hr = penumStatStg->Next(1, &statstg, NULL); 
                    if (FAILED(hr)) 
                    { 
                        MessageBoxFromStringIdsAndArgs( 
                            _hwnd, 
                            _hInstance, 
                            IDS_ENUMSTATSTGFAILED, 
                            IDS_ERROR, 
                            MB_OK | MB_ICONEXCLAMATION, 
                            hr); 
                    } 
                    else if (S_OK == hr) 
                    { 
                        // retrieved another member from the list 
                        LISTBOXELEMENT * plbe; 
                        switch (statstg.type) 
                        { 
                        case STGTY_STORAGE: 
                            { 
                                IStorage * pstg2; 
                                hr = pstg->OpenStorage( 
                                    statstg.pwcsName, 
                                    NULL, 
                                    STGM_READ | STGM_SHARE_EXCLUSIVE, 
                                    NULL, 
                                    0, 
                                    &pstg2); 
                                if (SUCCEEDED(hr)) 
                                { 
                                    plbe = CreateStorageElement(pstg2); 
                                } 
                                else 
                                { 
                                    MessageBoxFromStringIdsAndArgs( 
                                        _hwnd, 
                                        _hInstance, 
                                        IDS_OPENSTORAGEFAILED, 
                                        IDS_ERROR, 
                                        MB_OK | MB_ICONEXCLAMATION, 
                                        hr); 
                                    plbe = NULL; 
                                } 
                            } 
                            break; 
                        case STGTY_STREAM: 
                            { 
                                IStream * pstm; 
                                hr = pstg->OpenStream( 
                                    statstg.pwcsName, 
                                    0, 
                                    STGM_READ | STGM_SHARE_EXCLUSIVE, 
                                    0, 
                                    &pstm); 
                                if (SUCCEEDED(hr)) 
                                { 
                                    plbe = CreateStreamElement(pstm); 
                                } 
                                else 
                                { 
                                    MessageBoxFromStringIdsAndArgs( 
                                        _hwnd, 
                                        _hInstance, 
                                        IDS_OPENSTREAMFAILED, 
                                        IDS_ERROR, 
                                        MB_OK | MB_ICONEXCLAMATION, 
                                        hr); 
                                    plbe = NULL; 
                                } 
                            } 
                            break; 
                        } 
                        if (plbe) 
                        { 
                            plbe->pwcsName = statstg.pwcsName; 
                            plbe->uIndent = pElement->uIndent + 1; 
                            pElement->nChildren++; 
                            if (SendMessage(_hlb, LB_INSERTSTRING, lIndex + pElement->nChildren, (LPARAM) plbe) == LB_ERRSPACE) 
                            { 
                                MessageBoxFromStringIds( 
                                    _hwnd, 
                                    _hInstance, 
                                    IDS_INSERTSTRINGFAILED, 
                                    IDS_ERROR, 
                                    MB_OK | MB_ICONEXCLAMATION); 
                                DeleteElement(plbe); 
                                pElement->nChildren--; 
                            } 
                        } 
                    } 
                } 
                penumStatStg->Release(); 
            } 
            else 
            { 
                MessageBoxFromStringIdsAndArgs( 
                    _hwnd, 
                    _hInstance, 
                    IDS_ENUMELEMENTSFAILED, 
                    IDS_ERROR, 
                    MB_OK | MB_ICONEXCLAMATION, 
                    hr); 
            } 
        } 
        break; 
    case LBE_STREAM: 
        // streams are only expanded if they are the currently selected list item 
        if (SendMessage(_hlb, LB_GETCURSEL, 0, 0) == lIndex) 
        { 
            // open stream 
            CStreamView * psv = new CStreamView(_hlb, pElement); 
            if (psv) 
            { 
                pElement->fOpen = psv->InitInstance(_hInstance, SW_SHOWNORMAL); 
                if (pElement->fOpen) 
                { 
                    pElement->hwndView = psv->GetHwnd(); 
                    SetFocus(pElement->hwndView); 
                } 
            } 
        } 
        break; 
    } 
    SendMessage(_hlb, WM_SETREDRAW, TRUE, 0); 
} 
 
//+--------------------------------------------------------------------------- 
// 
//  Member:     CMainWindow::Collapse 
// 
//  Synopsis:   collapses a level of the tree 
// 
//  Arguments:  [lIndex] - index of the item to be collapsed 
// 
//  History:    6-23-94   stevebl   Created 
// 
//---------------------------------------------------------------------------- 
 
void CMainWindow::Collapse(long lIndex) 
{ 
    LISTBOXELEMENT * pElement = (LISTBOXELEMENT *) SendMessage(_hlb, LB_GETITEMDATA, lIndex, 0); 
    if (pElement->fOpen) 
    { 
        switch (pElement->uType) 
        { 
        case LBE_STORAGE: 
            while (pElement->nChildren--) 
            { 
                Collapse(lIndex + 1); 
                SendMessage(_hlb, LB_DELETESTRING, lIndex + 1, 0); 
            } 
            break; 
        case LBE_STREAM: 
            if (pElement->fOpen) 
            { 
                DestroyWindow(pElement->hwndView); 
            } 
            break; 
        } 
        pElement->fOpen = FALSE; 
    } 
} 
 
//+--------------------------------------------------------------------------- 
// 
//  Member:     CMainWindow::ExpandAll 
// 
//  Synopsis:   expands the current item and all its children 
// 
//  Arguments:  [lIndex] - index of the item to be expanded 
// 
//  History:    6-23-94   stevebl   Created 
// 
//---------------------------------------------------------------------------- 
 
void CMainWindow::ExpandAll(long lIndex) 
{ 
    LISTBOXELEMENT * pElement = (LISTBOXELEMENT *) SendMessage(_hlb, LB_GETITEMDATA, lIndex, 0); 
    Expand(lIndex); 
    if (pElement->uType == LBE_STORAGE) 
    { 
        unsigned nChildren = pElement->nChildren; 
        while (nChildren--) 
        { 
            ExpandAll(lIndex + 1 + nChildren); 
        } 
    } 
} 
 
//+--------------------------------------------------------------------------- 
// 
//  Member:     CMainWindow::Toggle 
// 
//  Synopsis:   toggles a node - expanding or collapsing as appropriate 
// 
//  Arguments:  [lIndex] - index of the node 
// 
//  History:    6-25-94   stevebl   Created 
// 
//---------------------------------------------------------------------------- 
 
void CMainWindow::Toggle(long lIndex) 
{ 
    LISTBOXELEMENT * pElement = (LISTBOXELEMENT *) SendMessage(_hlb, LB_GETITEMDATA, lIndex, 0); 
    if (pElement->fOpen) 
    { 
        Collapse(lIndex); 
    } 
    else 
    { 
        Expand(lIndex); 
    } 
} 
 
//+--------------------------------------------------------------------------- 
// 
//  Member:     CMainWindow::CreateStreamElement 
// 
//  Synopsis:   turns an IStream pointer into a listbox element 
// 
//  Arguments:  [pstm] - IStream pointer 
// 
//  Returns:    pointer to the newly created element 
//              (NULL on failure) 
// 
//  History:    6-23-94   stevebl   Created 
// 
//---------------------------------------------------------------------------- 
 
LISTBOXELEMENT * CMainWindow::CreateStreamElement(IStream * pstm) 
{ 
    LISTBOXELEMENT * plbe = new LISTBOXELEMENT; 
    if (plbe) 
    { 
        plbe->uType = LBE_STREAM; 
        plbe->fOpen = FALSE; 
        plbe->pInterface = (void *) pstm; 
        plbe->uIndent = 0; 
        plbe->hwndView = NULL; 
    } 
    else 
    { 
        MessageBoxFromStringIds( 
            _hwnd, 
            _hInstance, 
            IDS_OUTOFMEMORY, 
            IDS_ERROR, 
            MB_OK | MB_ICONEXCLAMATION); 
    } 
    return(plbe); 
} 
 
//+--------------------------------------------------------------------------- 
// 
//  Member:     CMainWindow::CreateStorageElement 
// 
//  Synopsis:   turns an IStorage pointer into a listbox element 
// 
//  Arguments:  [pstg] - IStorage pointer 
// 
//  Returns:    pointer to the newly created element 
//              (NULL on failure) 
// 
//  History:    6-23-94   stevebl   Created 
// 
//---------------------------------------------------------------------------- 
 
LISTBOXELEMENT * CMainWindow::CreateStorageElement(IStorage * pstg) 
{ 
    LISTBOXELEMENT * plbe = new LISTBOXELEMENT; 
    if (plbe) 
    { 
        plbe->uType = LBE_STORAGE; 
        plbe->fOpen = FALSE; 
        plbe->pInterface = (void *) pstg; 
        plbe->uIndent = 0; 
        plbe->nChildren = 0; 
    } 
    else 
    { 
        MessageBoxFromStringIds( 
            _hwnd, 
            _hInstance, 
            IDS_OUTOFMEMORY, 
            IDS_ERROR, 
            MB_OK | MB_ICONEXCLAMATION); 
    } 
    return(plbe); 
} 
 
//+--------------------------------------------------------------------------- 
// 
//  Member:     CMainWindow::DeleteElement 
// 
//  Synopsis:   deletes a listbox element and it's associated data 
// 
//  Arguments:  [plbe] - pointer to the element 
// 
//  History:    6-23-94   stevebl   Created 
// 
//  Notes:      This doesn't remove it from the list, it just frees up 
//              the LISTBOXELEMENT pointer and it's data. 
// 
//---------------------------------------------------------------------------- 
 
void CMainWindow::DeleteElement(LISTBOXELEMENT * plbe) 
{ 
 
    switch (plbe->uType) 
    { 
    case LBE_STORAGE: 
        ((IStorage *) plbe->pInterface)->Release(); 
        break; 
    case LBE_STREAM: 
        if (plbe->fOpen) 
        { 
            DestroyWindow(plbe->hwndView); 
        } 
        ((IStream *) plbe->pInterface)->Release(); 
        break; 
    } 
    LPMALLOC pMalloc; 
    CoGetMalloc(MEMCTX_TASK, &pMalloc); 
    pMalloc->Free(plbe->pwcsName); 
    pMalloc->Release(); 
    delete(plbe); 
} 
 
//+--------------------------------------------------------------------------- 
// 
//  Member:     CMainWindow::LoadBitmaps 
// 
//  Synopsis:   loads the Storage and Stream bitmap arrays 
// 
//  Returns:    TRUE on success 
//              FALSE on failure 
// 
//  Modifies:   _hbmpStorage and _hbmpStream 
// 
//  History:    6-24-94   stevebl   Created from code used in original DFView 
// 
//---------------------------------------------------------------------------- 
 
BOOL CMainWindow::LoadBitmaps(void) 
{ 
    // 
    // Get some metrics/info 
    // 
    UINT cxBitmap = BITMAPWIDTH; 
    _cyBitmap = BITMAPHEIGHT; 
    if (_cyBitmap < (UINT) _tm.tmHeight + _tm.tmExternalLeading) 
    { 
        _cyBitmap = _tm.tmHeight + _tm.tmExternalLeading; 
    } 
    UINT crHigh   = (COLORREF) GetSysColor(COLOR_HIGHLIGHT); 
    UINT crNorm   = (COLORREF) GetSysColor(COLOR_WINDOW); 
 
    HDC hdc = CreateCompatibleDC(NULL); 
    if (!hdc) 
    { 
        goto ERRLOADBITMAP; 
    } 
    _hbmpStorage = CreateBitmap( 
        4 * cxBitmap, 
        _cyBitmap, 
        GetDeviceCaps(hdc, PLANES), 
        GetDeviceCaps(hdc, BITSPIXEL), 
        NULL); 
    _hbmpStream = CreateBitmap( 
        4 * cxBitmap, 
        _cyBitmap, 
        GetDeviceCaps(hdc, PLANES), 
        GetDeviceCaps (hdc, BITSPIXEL), 
        NULL); 
   DeleteDC(hdc); 
   if (!_hbmpStorage || !_hbmpStream) 
   { 
        goto ERRLOADBITMAP; 
   } 
 
    // 
    //  Load our bitmaps, and munge them to create 
    //  our 4-bitmap "arrays".  Anything RED in the loaded 
    //  bitmap will be considered clear. 
    // 
    if (!LoadAndStretch( 
        _hInstance, 
        _hbmpStorage, 
        MAKEINTRESOURCE(BMP_STORAGE), 
        cxBitmap, 
        _cyBitmap, 
crHigh, 
        crNorm)) 
    { 
        goto ERRLOADBITMAP; 
    } 
    if (!LoadAndStretch( 
        _hInstance, 
        _hbmpStream, 
        MAKEINTRESOURCE(BMP_STREAM), 
        cxBitmap, 
        _cyBitmap, 
        crHigh, 
        crNorm)) 
    { 
        goto ERRLOADBITMAP; 
    } 
    return TRUE; 
 
ERRLOADBITMAP: 
    // 
    // Bitmap loading error. 
    // 
    DeleteObject(_hbmpStorage); 
    DeleteObject(_hbmpStream); 
    _hbmpStorage = NULL; 
    _hbmpStream = NULL; 
 
    return FALSE; 
} 
 
//+--------------------------------------------------------------------------- 
// 
//  Member:     CMainWindow::OpenFile 
// 
//  Synopsis:   attempts to open whatever docfile is named by _szFileName; 
// 
//  History:    6-24-94   stevebl   Created 
// 
//---------------------------------------------------------------------------- 
 
void CMainWindow::OpenFile(void) 
{ 
    SendMessage(_hlb, LB_RESETCONTENT, 0, 0); 
    IStorage * pstg; 
#ifndef UNICODE 
    // convert file name to a wide string 
    OLECHAR wszFileName[MAX_PATH]; 
    mbstowcs(wszFileName, _szFileName, MAX_PATH); 
#endif 
    // get IStorage 
    HRESULT hr = StgOpenStorage( 
#ifdef UNICODE 
        _szFileName, 
#else 
        wszFileName, 
#endif 
        NULL, 
        STGM_TRANSACTED | STGM_READ | STGM_SHARE_DENY_WRITE, 
        NULL, 
        0, 
        &pstg); 
    if (FAILED(hr)) 
    { 
        MessageBoxFromStringIdsAndArgs( 
            _hwnd, 
            _hInstance, 
            IDS_STGOPENSTORAGEFAILED, 
            IDS_ERROR, 
            MB_OK | MB_ICONEXCLAMATION, 
#ifdef UNICODE 
            _szFileName 
#else 
            wszFileName 
#endif 
            ); 
        return; 
    } 
    // Storage was opened successfully. 
    LISTBOXELEMENT * plbe = CreateStorageElement(pstg); 
    if (plbe) 
    { 
        IMalloc * pMalloc; 
        CoGetMalloc(MEMCTX_TASK, &pMalloc); 
        plbe->pwcsName = (LPOLESTR) pMalloc->Alloc(sizeof(OLECHAR) *  (lstrlen(_szFileName) + wcslen(ROOTSTGSTR) + 1)); 
        pMalloc->Release(); 
        if (plbe->pwcsName) 
        { 
            wcscpy(plbe->pwcsName, ROOTSTGSTR); 
#ifdef UNICODE 
            wcscpy(&plbe->pwcsName[wcslen(ROOTSTGSTR)], _szFileName); 
#else 
            mbstowcs(&plbe->pwcsName[wcslen(ROOTSTGSTR)], _szFileName, strlen(_szFileName) + 1); 
#endif 
        } 
        if (SendMessage(_hlb, LB_INSERTSTRING, 0, (LPARAM) plbe) == LB_ERRSPACE) 
        { 
            MessageBoxFromStringIds( 
                _hwnd, 
                _hInstance, 
                IDS_INSERTSTRINGFAILED, 
                IDS_ERROR, 
                MB_OK | MB_ICONEXCLAMATION); 
            DeleteElement(plbe); 
        } 
        else 
        { 
            SendMessage(_hlb, LB_SETCURSEL, 0, 0); 
        } 
    } 
} 
 
//+--------------------------------------------------------------------------- 
// 
//  Function:   Exists 
// 
//  Synopsis:   simple function to test for the existance of a file 
// 
//  History:    6-16-93   stevebl   Created 
// 
//---------------------------------------------------------------------------- 
 
int Exists(TCHAR *sz) 
{ 
    HANDLE h; 
    h = CreateFile(sz, 
        GENERIC_READ, 
        FILE_SHARE_READ | FILE_SHARE_WRITE, 
        NULL, 
        OPEN_EXISTING, 
        0, 
        0); 
    if (h != INVALID_HANDLE_VALUE) 
    { 
        CloseHandle(h); 
        return(1); 
    } 
    return (0); 
}