home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 18.ddi / MFC / SAMPLES / CHKBOOK / ROWVIEW.CP_ / ROWVIEW.CP
Encoding:
Text File  |  1993-02-08  |  10.3 KB  |  363 lines

  1. // rowview.cpp : implementation of the CRowView class
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and Microsoft
  9. // QuickHelp and/or WinHelp documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13.  
  14. #include "stdafx.h"
  15. #include "chkbook.h"
  16. #include <stdlib.h>
  17. #include <limits.h> // for INT_MAX
  18.  
  19. #ifdef _DEBUG
  20. #undef THIS_FILE
  21. static char BASED_CODE THIS_FILE[] = __FILE__;
  22. #endif
  23.  
  24. IMPLEMENT_DYNAMIC(CRowView, CScrollView)
  25.  
  26. /////////////////////////////////////////////////////////////////////////////
  27. // CRowView
  28.  
  29. BEGIN_MESSAGE_MAP(CRowView, CScrollView)
  30.     //{{AFX_MSG_MAP(CRowView)
  31.     ON_WM_KEYDOWN()
  32.     ON_WM_SIZE()
  33.     ON_WM_LBUTTONDOWN()
  34.     //}}AFX_MSG_MAP
  35.     // Standard printing commands
  36.     ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
  37.     ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
  38. END_MESSAGE_MAP()
  39.  
  40. /////////////////////////////////////////////////////////////////////////////
  41. // CRowView construction, initialization, and destruction
  42.  
  43. CRowView::CRowView()
  44. {
  45.     m_nPrevSelectedRow = 0;
  46. }
  47.  
  48. CRowView::~CRowView()
  49. {
  50. }
  51.  
  52. /////////////////////////////////////////////////////////////////////////////
  53. // CRowView updating and drawing
  54.  
  55. void CRowView::OnInitialUpdate()
  56. {
  57.     m_nPrevRowCount = GetRowCount();
  58.     m_nPrevSelectedRow = GetActiveRow();
  59. }
  60.  
  61. void CRowView::UpdateRow(int nInvalidRow)
  62. {
  63.     int nRowCount = GetRowCount();
  64.     // If the number of rows has changed, then adjust the scrolling range.
  65.     if (nRowCount != m_nPrevRowCount)
  66.     {
  67.         UpdateScrollSizes();
  68.         m_nPrevRowCount = nRowCount;
  69.     }
  70.  
  71.     // When the currently selected row changes:
  72.     // scroll the view so that the newly selected row is visible, and
  73.     // ask the derived class to repaint the selected and previously
  74.     // selected rows.
  75.  
  76.     CClientDC dc(this);
  77.     OnPrepareDC(&dc);
  78.  
  79.     // Determine the range of the rows that are currently fully visible
  80.     // in the window.  We want to do discrete scrolling by so that
  81.     // the next or previous row is always fully visible.
  82.     int nFirstRow, nLastRow;
  83.     CRect rectClient;
  84.     GetClientRect(&rectClient);
  85.     dc.DPtoLP(&rectClient);
  86.     RectLPtoRowRange(rectClient, nFirstRow, nLastRow, FALSE);
  87.  
  88.     // If necessary, scroll the window so the newly selected row is
  89.     // visible.
  90.     POINT pt;
  91.     pt.x = 0;
  92.     BOOL bNeedToScroll = TRUE;
  93.     if (nInvalidRow < nFirstRow)
  94.     {
  95.         // The newly selected row is above those currently visible
  96.         // in the window.  Scroll so the newly selected row is at the
  97.         // very top of the window.  The last row in the window might
  98.         // be only partially visible.
  99.         pt.y = RowToYPos(nInvalidRow);
  100.     }
  101.     else if (nInvalidRow > nLastRow)
  102.     {
  103.         // The newly selected row is below those currently visible
  104.         // in the window.  Scroll so the newly selected row is at the
  105.         // very bottom of the window.  The first row in the window might
  106.         // be only partially visible.
  107.         pt.y = max(0, RowToYPos(nInvalidRow+1) - rectClient.Height());
  108.     }
  109.     else
  110.     {
  111.         bNeedToScroll = FALSE;
  112.     }
  113.     if (bNeedToScroll)
  114.     {
  115.         ScrollToDevicePosition(pt);
  116.         // Scrolling will cause the newly selected row to be
  117.         // redrawn in the invalidated area of the window.
  118.  
  119.         OnPrepareDC(&dc);  // Need to prepare the DC again because
  120.             // ScrollToDevicePosition() will have changed the viewport
  121.             // origin.  The DC is used some more below.
  122.     }
  123.  
  124.     CRect rectInvalid = RowToWndRect(&dc, nInvalidRow);
  125.     InvalidateRect(&rectInvalid);
  126.  
  127.     // Give the derived class an opportunity to repaint the
  128.     // previously selected row, perhaps to un-highlight it.
  129.  
  130.     int nSelectedRow = GetActiveRow();
  131.     if (m_nPrevSelectedRow != nSelectedRow)
  132.     {
  133.         CRect rectOldSelection = RowToWndRect(&dc, m_nPrevSelectedRow);
  134.         InvalidateRect(&rectOldSelection);
  135.         m_nPrevSelectedRow = nSelectedRow;
  136.     }
  137.  
  138.  
  139. }
  140.  
  141. void CRowView::UpdateScrollSizes()
  142. {
  143.     // UpdateScrollSizes() is called when it is necessary to adjust the
  144.     // scrolling range or page/line sizes.  There are two occassions
  145.     // where this is necessary:  (1) when a new row is added-- see
  146.     // UpdateRow()-- and (2) when the window size changes-- see OnSize().
  147.  
  148.     CRect rectClient;
  149.     GetClientRect(&rectClient);
  150.  
  151.     CClientDC dc(this);
  152.     CalculateRowMetrics(&dc);
  153.  
  154.     // The vert scrolling range is the total display height of all
  155.     // of the rows.
  156.     CSize sizeTotal(m_nRowWidth, 
  157.         m_nRowHeight * (min(GetRowCount(), LastViewableRow())));
  158.  
  159.     // The vertical per-page scrolling distance is equal to the
  160.     // how many rows can be displayed in the current window, less
  161.     // one row for paging overlap.
  162.     CSize sizePage(m_nRowWidth/5,
  163.             max(m_nRowHeight,
  164.                 ((rectClient.bottom/m_nRowHeight)-1)*m_nRowHeight));
  165.  
  166.     // The vertical per-line scrolling distance is equal to the
  167.         // height of the row.
  168.     CSize sizeLine(m_nRowWidth/20, m_nRowHeight);
  169.  
  170.     SetScrollSizes(MM_TEXT, sizeTotal, sizePage, sizeLine);
  171. }
  172.  
  173.  
  174. void CRowView::OnDraw(CDC* pDC)
  175. {
  176.     if (GetRowCount() == 0)
  177.         return;
  178.  
  179.     // The window has been invalidated and needs to be repainted;
  180.     // or a page needs to be printed (or previewed).
  181.     // First, determine the range of rows that need to be displayed or
  182.     // printed.
  183.  
  184.     int nFirstRow, nLastRow;
  185.     CRect rectClip;
  186.     pDC->GetClipBox(&rectClip); // Get the invalidated region.
  187.     RectLPtoRowRange(rectClip, nFirstRow, nLastRow, TRUE);
  188.  
  189.     // Draw each row in the invalidated region of the window,
  190.     // or on the printed (previewed) page.
  191.     int nActiveRow = GetActiveRow();
  192.     int nRow, y;
  193.     int nLastViewableRow = LastViewableRow();
  194.     for (nRow = nFirstRow,
  195.             y = m_nRowHeight * nFirstRow;
  196.             nRow <= nLastRow;
  197.             nRow++, y += m_nRowHeight)
  198.     {
  199.         if (nRow > nLastViewableRow)
  200.         {
  201.             CString strWarning;
  202.             strWarning.LoadString(IDS_TOO_MANY_ROWS);
  203.             pDC->TextOut(0, y, strWarning);
  204.             break;
  205.         }
  206.         OnDrawRow(pDC, nRow, y, nRow == nActiveRow);
  207.     }
  208. }
  209.  
  210.  
  211. /////////////////////////////////////////////////////////////////////////////
  212. // Implementation
  213.  
  214. int CRowView::RowToYPos(int nRow)
  215. {
  216.     return (nRow * m_nRowHeight);
  217. }
  218.  
  219. CRect CRowView::RowToWndRect(CDC* pDC, int nRow)
  220. {
  221.     int nHorzRes = pDC->GetDeviceCaps(HORZRES);;
  222.     CRect rect(0, nRow * m_nRowHeight, 
  223.         nHorzRes, (nRow + 1) * m_nRowHeight);
  224.     pDC->LPtoDP(&rect);
  225.     return rect;
  226. }
  227.  
  228.  
  229. int CRowView::LastViewableRow()
  230. {
  231.     return (INT_MAX / m_nRowHeight - 1);
  232. }
  233.  
  234. void CRowView::RectLPtoRowRange(const CRect& rect,
  235.             int& nFirstRow, int& nLastRow,
  236.             BOOL bIncludePartiallyShownRows)
  237. {
  238.     int nRounding = bIncludePartiallyShownRows? 0 : (m_nRowHeight - 1);
  239.     nFirstRow = (rect.top + nRounding) / m_nRowHeight;
  240.     nLastRow = min( (rect.bottom - nRounding) / m_nRowHeight,
  241.         GetRowCount() - 1);
  242. }
  243.  
  244. void CRowView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
  245. {
  246.     // The size of text that is displayed, printed or previewed changes
  247.     // depending on the DC.  We explicitly call OnPrepareDC() to prepare
  248.     // CClientDC objects used for calculating text positions and to
  249.     // prepare the text metric member variables of the CRowView object.
  250.     // The framework also calls OnPrepareDC() before passing the DC to
  251.     // OnDraw().
  252.  
  253.     CScrollView::OnPrepareDC(pDC, pInfo);
  254.     CalculateRowMetrics(pDC);
  255. }
  256.  
  257. /////////////////////////////////////////////////////////////////////////////
  258. // Overrides of CView for implementing printing.
  259.  
  260. BOOL CRowView::OnPreparePrinting(CPrintInfo* pInfo)
  261. {
  262.     return DoPreparePrinting(pInfo);
  263. }
  264.  
  265. void CRowView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
  266. {
  267.     // OnBeginPrinting() is called after the user has committed to
  268.     // printing by OK'ing the Print dialog, and after the framework
  269.     // has created a CDC object for the printer or the preview view.
  270.  
  271.     // This is the right opportunity to set up the page range.
  272.     // Given the CDC object, we can determine how many rows will
  273.     // fit on a page, so we can in turn determine how many printed
  274.     // pages represent the entire document.
  275.  
  276.     int nPageHeight = pDC->GetDeviceCaps(VERTRES);
  277.     CalculateRowMetrics(pDC);
  278.     m_nRowsPerPrintedPage = nPageHeight / m_nRowHeight;
  279.     int nPrintableRowCount = LastViewableRow() + 1;
  280.     if (GetRowCount() < nPrintableRowCount)
  281.         nPrintableRowCount = GetRowCount();
  282.     pInfo->SetMaxPage((nPrintableRowCount + m_nRowsPerPrintedPage - 1)
  283.         / m_nRowsPerPrintedPage);
  284.     pInfo->m_nCurPage = 1;  // start previewing at page# 1
  285. }
  286.  
  287. void CRowView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
  288. {
  289.     // Print the rows for the current page.
  290.  
  291.     int yTopOfPage = (pInfo->m_nCurPage -1) * m_nRowsPerPrintedPage
  292.         * m_nRowHeight;
  293.  
  294.     // Orient the viewport so that the first row to be printed
  295.     // has a viewport coordinate of (0,0).
  296.     pDC->SetViewportOrg(0, -yTopOfPage);
  297.  
  298.     // Draw as many rows as will fit on the printed page.
  299.     // Clip the printed page so that there is no partially shown
  300.     // row at the bottom of the page (the same row which will be fully
  301.     // shown at the top of the next page).
  302.  
  303.     int nPageWidth = pDC->GetDeviceCaps(HORZRES);
  304.     CRect rectClip = CRect(0, yTopOfPage, nPageWidth, 
  305.          yTopOfPage + m_nRowsPerPrintedPage * m_nRowHeight);
  306.     pDC->IntersectClipRect(&rectClip);
  307.     OnDraw(pDC);
  308. }
  309.  
  310. /////////////////////////////////////////////////////////////////////////////
  311. // CRowView commands
  312.  
  313.  
  314. void CRowView::OnSize(UINT nType, int cx, int cy)
  315. {
  316.     UpdateScrollSizes();
  317.     CScrollView::OnSize(nType, cx, cy);
  318. }
  319.  
  320. void CRowView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  321. {
  322.     switch (nChar)
  323.     {
  324.         case VK_HOME:
  325.             ChangeSelectionToRow(0);
  326.             break;
  327.         case VK_END:
  328.             ChangeSelectionToRow(GetRowCount() - 1);
  329.             break;
  330.         case VK_UP:
  331.             ChangeSelectionNextRow(FALSE);
  332.             break;
  333.         case VK_DOWN:
  334.             ChangeSelectionNextRow(TRUE);
  335.             break;
  336.         case VK_PRIOR:
  337.             OnVScroll(SB_PAGEUP,
  338.                 0,  // nPos not used for PAGEUP
  339.                 GetScrollBarCtrl(SB_VERT));
  340.             break;
  341.         case VK_NEXT:
  342.             OnVScroll(SB_PAGEDOWN,
  343.                 0,  // nPos not used for PAGEDOWN
  344.                 GetScrollBarCtrl(SB_VERT));
  345.             break;
  346.         default:
  347.             CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);
  348.     }
  349. }
  350.  
  351. void CRowView::OnLButtonDown(UINT, CPoint point)
  352. {
  353.     CClientDC dc(this);
  354.     OnPrepareDC(&dc);
  355.     dc.DPtoLP(&point);
  356.     CRect rect(point, CSize(1,1));
  357.     int nFirstRow, nLastRow;
  358.     RectLPtoRowRange(rect, nFirstRow, nLastRow, TRUE);
  359.     if (nFirstRow <= (GetRowCount() - 1))
  360.         ChangeSelectionToRow(nFirstRow);
  361. }
  362.  
  363.