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 / strmvwr.cxx < prev    next >
C/C++ Source or Header  |  1995-02-13  |  13KB  |  373 lines

  1. //+---------------------------------------------------------------------------
  2. //
  3. //  Microsoft Windows
  4. //  Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. //  File:       stmvwr.cxx
  7. //
  8. //  Contents:   implementation for the stream viewer window class
  9. //
  10. //  Classes:    CStreamView
  11. //
  12. //  Functions:
  13. //
  14. //  History:    6-27-94   stevebl   Created
  15. //
  16. //----------------------------------------------------------------------------
  17.  
  18. #include <windows.h>
  19. #include <ole2.h>
  20. #include "strmvwr.h"
  21.  
  22. #define BYTESPERLINE 16
  23. #define DIVISIONPOINTS 8
  24.  
  25. //+---------------------------------------------------------------------------
  26. //
  27. //  Member:     CStreamView::CStreamView
  28. //
  29. //  Synopsis:   constructor
  30. //
  31. //  Arguments:  [hlb]    - handle to CMainWindow's listbox
  32. //              [ple]    - pointer to the LISTBOXELEMENT structure for this
  33. //                         stream
  34. //
  35. //  History:    6-27-94   stevebl   Created
  36. //
  37. //----------------------------------------------------------------------------
  38.  
  39. CStreamView::CStreamView(HWND hlb, LISTBOXELEMENT * ple)
  40. {
  41.     _hlbParent = hlb;
  42.     _ple = ple;
  43.     _hfListBox = NULL;
  44. }
  45.  
  46. //+---------------------------------------------------------------------------
  47. //
  48. //  Member:     CStreamView::~CStreamView
  49. //
  50. //  Synopsis:   destructor
  51. //
  52. //  History:    6-27-94   stevebl   Created
  53. //
  54. //----------------------------------------------------------------------------
  55.  
  56. CStreamView::~CStreamView()
  57. {
  58.     _ple->fOpen = FALSE;
  59.     if (_hfListBox)
  60.     {
  61.         DeleteObject(_hfListBox);
  62.     }
  63.     InvalidateRect(_hlbParent, NULL, FALSE);
  64. }
  65.  
  66. //+---------------------------------------------------------------------------
  67. //
  68. //  Member:     CStreamView::InitInstance
  69. //
  70. //  Synopsis:   creates and shows the stream viewer window
  71. //
  72. //  Arguments:  [hInstance] - the application's instance handle
  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:      must only be called once immediately after class construction
  81. //
  82. //----------------------------------------------------------------------------
  83.  
  84. BOOL CStreamView::InitInstance(HINSTANCE hInstance, int nCmdShow)
  85. {
  86.     IStream * pstm = (IStream * ) _ple->pInterface;
  87.     STATSTG statstg;
  88.     HRESULT hr = pstm->Stat(&statstg, STATFLAG_NONAME);
  89.     if (FAILED(hr))
  90.     {
  91.         MessageBoxFromStringIdsAndArgs(
  92.             _hwnd,
  93.             _hInstance,
  94.             IDS_STMSTATFAILED,
  95.             IDS_ERROR,
  96.             MB_OK | MB_ICONEXCLAMATION,
  97.             hr
  98.             );
  99.         return(FALSE);
  100.     }
  101.     _cbSize = statstg.cbSize.LowPart;
  102.  
  103.     TCHAR szStreamTitleText[MAX_STRING_LENGTH];
  104.     if (!LoadString(_hInstance, IDS_STMTITLETEXT, szStreamTitleText, MAX_STRING_LENGTH))
  105.     {
  106.         lstrcpy(szStreamTitleText, TEXT(""));
  107.     }
  108.  
  109.     TCHAR * szTitle = new TCHAR[lstrlen(TEXT("  [0x00000000 bytes]"))
  110.         + lstrlen(szStreamTitleText) + wcslen(_ple->pwcsName) + 1];
  111.     if (szTitle)
  112.     {
  113.         wsprintf(szTitle, TEXT("%s %ws [0x%08X bytes]"), szStreamTitleText, _ple->pwcsName, _cbSize);
  114.     }
  115.     // Note, the Create method sets the _hwnd member for me so I don't
  116.     // need to set it myself.
  117.     HWND hwnd = Create(
  118.         TEXT(STREAM_VIEW_CLASS_NAME),
  119.         szTitle,
  120.         WS_OVERLAPPED
  121.             | WS_MINIMIZEBOX
  122.             | WS_MAXIMIZEBOX
  123.             | WS_SYSMENU
  124.             | WS_THICKFRAME,
  125.         CW_USEDEFAULT,
  126.         CW_USEDEFAULT,
  127.         CW_USEDEFAULT,
  128.         CW_USEDEFAULT,
  129.         NULL,
  130.         NULL,
  131.         hInstance);
  132.     delete[] szTitle;
  133.     if (!hwnd)
  134.     {
  135.         return(FALSE);
  136.     }
  137.     ShowWindow(hwnd, nCmdShow);
  138.     UpdateWindow(hwnd);
  139.     return(TRUE);
  140. }
  141.  
  142. //+---------------------------------------------------------------------------
  143. //
  144. //  Member:     CStreamView::WindowProc
  145. //
  146. //  Synopsis:   window procedure for the stream viewer window
  147. //
  148. //  Arguments:  [uMsg]   - Window's message
  149. //              [wParam] - first message parameter
  150. //              [lParam] - second message parameter
  151. //
  152. //  History:    6-27-94   stevebl   Created
  153. //
  154. //----------------------------------------------------------------------------
  155.  
  156. LRESULT CStreamView::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  157. {
  158.     switch (uMsg)
  159.     {
  160.     case WM_CREATE:
  161.         {
  162.             RECT rc;
  163.             GetClientRect(_hwnd, &rc);
  164.             // record the width before we create the list box
  165.             _wWidth = (WORD) rc.right;
  166.  
  167.             HDC hdc = GetDC(_hwnd);
  168.             LOGFONT lf;
  169.             memset(&lf, 0, sizeof(LOGFONT));
  170.  
  171.             // Get an 8 point Courier font.
  172.             lf.lfHeight = -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72);
  173.             lstrcpy(lf.lfFaceName, TEXT("Courier"));
  174.             _hfListBox = CreateFontIndirect(&lf);
  175.             HFONT hfOld = (HFONT) SelectObject(hdc, _hfListBox);
  176.             GetTextMetrics(hdc, &_tm);
  177.             SelectObject(hdc, hfOld);
  178.             ReleaseDC(_hwnd, hdc);
  179.  
  180.             // create the child listbox
  181.             _hlb = CreateWindow(
  182.                 TEXT("listbox"),
  183.                 TEXT(""),
  184.                 LBS_OWNERDRAWFIXED |
  185.                     WS_CHILD |
  186.                     WS_VISIBLE |
  187.                     WS_VSCROLL |
  188.                     LBS_NOINTEGRALHEIGHT |
  189.                     LBS_NODATA,
  190.                 0,
  191.                 0,
  192.                 rc.right,
  193.                 rc.bottom,
  194.                 _hwnd,
  195.                 (HMENU) IDC_LISTBOX,
  196.                 _hInstance,
  197.                 NULL);
  198.             if (NULL == _hlb)
  199.             {
  200.                 // abort window creation
  201.                 return(-1);
  202.             }
  203.             SetFocus(_hlb);
  204.  
  205.             SendMessage(
  206.                 _hlb,
  207.                 LB_SETCOUNT,
  208.                 (WPARAM)((_cbSize / BYTESPERLINE) + (_cbSize % BYTESPERLINE ? 1 : 0)),
  209.                 0);
  210.             SendMessage(_hlb, WM_SETFONT, (WPARAM) _hfListBox, 0);
  211.             SendMessage(_hlb, LB_SETCURSEL, 0, 0);
  212.             _crTextHigh = GetSysColor(COLOR_HIGHLIGHTTEXT);
  213.             _crTextNorm = GetSysColor(COLOR_WINDOWTEXT);
  214.             _crBkHigh = GetSysColor(COLOR_HIGHLIGHT);
  215.             _crBkNorm = GetSysColor(COLOR_WINDOW);
  216.         }
  217.         break;
  218.     case WM_SETFOCUS:
  219.         {
  220.             if (_hlb)
  221.             {
  222.                 SetFocus(_hlb);
  223.             }
  224.         break;
  225.         }
  226.     case WM_MEASUREITEM:
  227.         {
  228.             LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT) lParam;
  229.             lpmis->itemHeight = _tm.tmHeight + _tm.tmExternalLeading;
  230.             lpmis->itemWidth = _wWidth;
  231.             return(TRUE);
  232.         }
  233.     case WM_DRAWITEM:
  234.         {
  235.             LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) lParam;
  236.             if (-1 == lpdis->itemID)
  237.             {
  238.                 // no items in the listbox
  239.                 break;
  240.             }
  241.             // draw the item
  242.             switch (lpdis->itemAction)
  243.             {
  244.             case ODA_SELECT:
  245.             case ODA_DRAWENTIRE:
  246.                 {
  247.                     // draw the listbox item
  248.                     LONG lStartByte = lpdis->itemID * BYTESPERLINE;
  249.  
  250.                     // NOTE:  The following string is actually a bit larger
  251.                     // than it has to be.  The minimum size for this string
  252.                     // is acutally somewhere between 5 and 6 bytes for each
  253.                     // byte (plus 12) in the stream that is to be displayed.
  254.                     // Doing it this way wastes a little space but it's much
  255.                     // simpler, it's faster, and it's less prone to error
  256.                     // than dynamically computing it each time.
  257.                     TCHAR szLine[BYTESPERLINE * 6 + 12];
  258.  
  259.                     unsigned cch;
  260.                     wsprintf(szLine, TEXT("0x%08X:"), lStartByte);
  261.                     for (cch = BYTESPERLINE * 6 + 12; (unsigned) lstrlen(TEXT("0x12345678:")) < cch--; )
  262.                     {
  263.                         szLine[cch] = TEXT(' ');
  264.                     }
  265.  
  266.                     IStream * pstm = (IStream *) _ple->pInterface;
  267.                     BYTE rgb[BYTESPERLINE];
  268.                     LARGE_INTEGER dlibMove;
  269.                     dlibMove.HighPart = 0;
  270.                     // If we ever get a stream that's big enough to require
  271.                     // that the HiPart get set, then nobody would want to
  272.                     // browse that much data anyway!
  273.                     dlibMove.LowPart = lStartByte;
  274.  
  275.                     HRESULT hr = pstm->Seek(dlibMove, STREAM_SEEK_SET, NULL);
  276.                     if (FAILED(hr))
  277.                     {
  278.                         MessageBoxFromStringIdsAndArgs(
  279.                             _hwnd,
  280.                             _hInstance,
  281.                             IDS_STMSEEKFAILED,
  282.                             IDS_ERROR,
  283.                             MB_OK | MB_ICONEXCLAMATION,
  284.                             hr
  285.                             );
  286.                         return(FALSE);
  287.                     }
  288.                     ULONG cbRead;
  289.                     hr = pstm->Read(rgb, BYTESPERLINE, &cbRead);
  290.                     if (FAILED(hr))
  291.                     {
  292.                         MessageBoxFromStringIdsAndArgs(
  293.                             _hwnd,
  294.                             _hInstance,
  295.                             IDS_STMREADFAILED,
  296.                             IDS_ERROR,
  297.                             MB_OK | MB_ICONEXCLAMATION,
  298.                             hr
  299.                             );
  300.                         return(FALSE);
  301.                     }
  302.  
  303.                     for (cch = 0; cch < cbRead; cch++)
  304.                     {
  305.                         TCHAR szTemp[3];
  306.                         wsprintf(szTemp, TEXT("%02X"), rgb[cch]);
  307.                         szLine[cch * 3 + cch / DIVISIONPOINTS + 12] = szTemp[0];
  308.                         szLine[cch * 3 + cch / DIVISIONPOINTS + 13] = szTemp[1];
  309.                         char ch = rgb[cch];
  310.                         if (ch < ' ')
  311.                         {
  312.                             ch = '.';
  313.                         }
  314.                         // this is a little trick to get the character in the
  315.                         // correct type of string (UNICODE or not)
  316.                         wsprintf(szTemp, TEXT("%c"), ch);
  317.                         szLine[cch + 13 + cch / DIVISIONPOINTS + 3 * BYTESPERLINE + BYTESPERLINE / DIVISIONPOINTS] = szTemp[0];
  318.                     }
  319.                     szLine[cch + 13 + cch / DIVISIONPOINTS + 3 * BYTESPERLINE + BYTESPERLINE / DIVISIONPOINTS] = 0;
  320.  
  321.                     SIZE sizeText;
  322.                     RECT rcItem = lpdis->rcItem;
  323.  
  324.                     GetTextExtentPoint32(
  325.                         lpdis->hDC,
  326.                         szLine,
  327.                         lstrlen(szLine),
  328.                         &sizeText);
  329.                     rcItem.right = rcItem.left + sizeText.cx;
  330.                     COLORREF crOldText = SetTextColor(
  331.                         lpdis->hDC,
  332.                         (lpdis->itemState & ODS_SELECTED) ? _crTextHigh : _crTextNorm);
  333.                     COLORREF crOldBack = SetBkColor(
  334.                         lpdis->hDC,
  335.                         (lpdis->itemState & ODS_SELECTED) ? _crBkHigh : _crBkNorm);
  336.                     ExtTextOut(
  337.                         lpdis->hDC,
  338.                         rcItem.left,
  339.                         rcItem.top,
  340.                         ETO_OPAQUE | ETO_CLIPPED,
  341.                         &rcItem,
  342.                         szLine,
  343.                         lstrlen(szLine),
  344.                         NULL);
  345.                     SetTextColor(lpdis->hDC, crOldText);
  346.                     SetBkColor(lpdis->hDC, crOldBack);
  347.                 }
  348.                 break;
  349.             case ODA_FOCUS:
  350.                 break;
  351.             }
  352.             return(TRUE);
  353.         }
  354.     case WM_SIZE:
  355.         {
  356.             _wWidth = LOWORD(lParam);
  357.             WORD wHeight = HIWORD(lParam);
  358.             if (_hlb)
  359.             {
  360.                 SetWindowPos(_hlb, NULL, 0, 0, _wWidth, wHeight, SWP_NOMOVE | SWP_NOZORDER);
  361.             }
  362.             break;
  363.         }
  364.     case WM_COMMAND:
  365.     case WM_QUIT:
  366.     case WM_CLOSE:
  367.     default:
  368.         return(DefWindowProc(_hwnd, uMsg, wParam, lParam));
  369.     }
  370.     return(FALSE);
  371. }
  372.  
  373.