home *** CD-ROM | disk | FTP | other *** search
/ Mastering MFC Development / MMD.ISO / labs / c07 / lab03 / ex01 / textview.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-20  |  6.5 KB  |  263 lines

  1. // TextView.cpp : implementation of the CTextView class
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "Text.h"
  6.  
  7. #include "TextDoc.h"
  8. #include "TextView.h"
  9.  
  10. #ifdef _DEBUG
  11. #define new DEBUG_NEW
  12. #undef THIS_FILE
  13. static char THIS_FILE[] = __FILE__;
  14. #endif
  15.  
  16. /////////////////////////////////////////////////////////////////////////////
  17. // CTextView
  18.  
  19. IMPLEMENT_DYNCREATE(CTextView, CScrollView)
  20.  
  21. BEGIN_MESSAGE_MAP(CTextView, CScrollView)
  22.     //{{AFX_MSG_MAP(CTextView)
  23.         // NOTE - the ClassWizard will add and remove mapping macros here.
  24.         //    DO NOT EDIT what you see in these blocks of generated code!
  25.     //}}AFX_MSG_MAP
  26.     // Standard printing commands
  27.     ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)
  28.     ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint)
  29.     ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)
  30. END_MESSAGE_MAP()
  31.  
  32. /////////////////////////////////////////////////////////////////////////////
  33. // CTextView construction/destruction
  34.  
  35. CTextView::CTextView()
  36.         :    m_ViewCharSize(0,0),
  37.             m_DocSize(0,0)
  38.  
  39. {
  40.     m_pFont = NULL;
  41. }
  42.  
  43. CTextView::~CTextView()
  44. {
  45. }
  46.  
  47. BOOL CTextView::PreCreateWindow(CREATESTRUCT& cs)
  48. {
  49.     // TODO: Modify the Window class or styles here by modifying
  50.     //  the CREATESTRUCT cs
  51.  
  52.     return CScrollView::PreCreateWindow(cs);
  53. }
  54.  
  55. /////////////////////////////////////////////////////////////////////////////
  56. // CTextView drawing
  57.  
  58. void CTextView::OnDraw(CDC* pDC)
  59. {
  60.     int nFirstLn, nLastLn;
  61.  
  62.     ComputeVisibleLines(pDC, nFirstLn, nLastLn);
  63.  
  64.     int nYPos = - nFirstLn * GetCharSize().cy;
  65.     int nXPos = 4 * GetCharSize().cx;
  66.     OnDraw(pDC, nFirstLn, nLastLn,nXPos,nYPos);
  67. }
  68.  
  69. void CTextView::OnDraw(CDC* pDC, int nFirstLn, int nLastLn, 
  70.                         int nXPos /*= 0*/, int nYPos /*= 0*/)
  71. {
  72.     //     Select specified font
  73.     CFont* pPreviousFont = pDC->SelectObject(GetFont());
  74.  
  75.     //    Needed for height of each line
  76.     CSize CharSize = GetCharSize();
  77.  
  78.     //    Get list of strings from the document
  79.     //    and output them to the display context
  80.     CStringList *pLineList = GetDocument()->GetLineList();
  81.  
  82.     CString     strLine;
  83.     POSITION     pos;
  84.     while (nFirstLn <= nLastLn)
  85.     {
  86.         if( ( pos = pLineList->FindIndex( nFirstLn )) != NULL )
  87.         {
  88.             strLine = pLineList->GetAt(pos); 
  89.             pDC->TabbedTextOut(nXPos, nYPos, strLine, 0, NULL, 0);
  90.             nYPos -= CharSize.cy;
  91.             nFirstLn++;
  92.         }
  93.     }
  94.  
  95.     //    Cleanup and restore original GDI Objects
  96.     if(pPreviousFont)
  97.     {
  98.         pDC->SelectObject(pPreviousFont);
  99.     }
  100. }
  101.  
  102. /*
  103. void CTextView::OnInitialUpdate()
  104. {
  105.     CScrollView::OnInitialUpdate();
  106.     CSize sizeTotal;
  107.     // TODO: calculate the total size of this view
  108.     sizeTotal.cx = sizeTotal.cy = 100;
  109.     SetScrollSizes(MM_TEXT, sizeTotal);
  110. }
  111. */
  112.  
  113. CFont *    CTextView::GetFont()
  114. {
  115.     if(m_pFont == NULL)
  116.     {
  117.         m_pFont = new CFont;
  118.         if(m_pFont)
  119.         {
  120.             //    Default to 9 pt Arial
  121.             m_pFont->CreatePointFont(90, "Arial");
  122.         }
  123.     }
  124.     return m_pFont;
  125. }
  126.  
  127. void CTextView::ComputeViewMetrics()
  128. {
  129.     // get a CDC* for the screen
  130.     CDC* pDC = CDC::FromHandle(::GetDC(NULL));
  131.     int nSaveDC = pDC->SaveDC();
  132.  
  133.     // select mapping mode
  134.     pDC->SetMapMode(MM_LOENGLISH); 
  135.  
  136.     // select the font and get its metrics
  137.     CFont* pPreviousFont = pDC->SelectObject(GetFont());
  138.     TEXTMETRIC tm;
  139.     pDC->GetTextMetrics(&tm);
  140.  
  141.     //    Calculate view character size
  142.     m_ViewCharSize.cy = tm.tmHeight + tm.tmExternalLeading;
  143.     m_ViewCharSize.cx = tm.tmAveCharWidth;
  144.  
  145.     // convert to device units to minimize round off error
  146.     pDC->LPtoDP(&m_ViewCharSize);
  147.  
  148.     //    Calculate document size
  149.     CTextDoc* pDoc = GetDocument();
  150.     m_DocSize.cx = 0;
  151.     m_DocSize.cy = m_ViewCharSize.cy * 
  152.                     pDoc->GetLineList()->GetCount();
  153.  
  154.     // loop through the document and find the longest line
  155.     CString    Line;
  156.     CSize size;
  157.     POSITION pos = pDoc->GetLineList()->GetHeadPosition();
  158.     while( pos != NULL )
  159.     {
  160.         Line = pDoc->GetLineList()->GetNext( pos );
  161.         size = pDC->GetTextExtent(Line, Line.GetLength());
  162.         m_DocSize.cx = max(size.cx, m_DocSize.cx);
  163.     }
  164.  
  165.     //    Account for our simple margin
  166.     m_DocSize.cx += 4 * m_ViewCharSize.cx;
  167.  
  168.     // clean up
  169.     if(pPreviousFont)
  170.     {
  171.         pDC->SelectObject(pPreviousFont);
  172.     }
  173.     pDC->RestoreDC(nSaveDC);
  174.     ::ReleaseDC(NULL,pDC->GetSafeHdc());
  175. }
  176.  
  177. void CTextView::ComputeVisibleLines(CDC* pDC, int& nFirst, int& nLast)
  178. {
  179.     int nLineCount = GetDocument()->GetLineList()->GetCount();
  180.  
  181.     // Get the viewport origin, convert to logical coordinates
  182.     CPoint pt = pDC->GetViewportOrg();
  183.     pDC->DPtoLP(&pt,1);
  184.  
  185.     // Get the clipping region, in logical coordinates
  186.     CRect rc;
  187.     pDC->GetClipBox(&rc);
  188.  
  189.     // Get the logical line height
  190.     CSize CharSize = GetCharSize();
  191.  
  192.     // Compute the first visible line
  193.     // The algorithm for the first visible line is
  194.     //    ╖ Calculate the distance from the top of the viewport to the top of clipping region
  195.     //    ╖ Divide this distance by the height of a line, giving the number of lines
  196.     //    ╖ Ensure that at least one line will be show
  197.  
  198.     nFirst = min(abs((rc.top - pt.y)/CharSize.cy),
  199.                 nLineCount-1);
  200.  
  201.     // compute the last visible line
  202.     // The algorithm for the last visible line is
  203.     //    ╖ Calculate the number of lines that will fit into the clipping region
  204.     //    ╖ Add that to the starting line
  205.     //    ╖ Add one more line to make sure that partial lines are displayed
  206.     //    ╖ Make sure that this is less than the total number of lines
  207.  
  208.     nLast = min(abs(rc.Height())/CharSize.cy + nFirst + 1,
  209.                 nLineCount-1);
  210. }
  211.  
  212.  
  213. /////////////////////////////////////////////////////////////////////////////
  214. // CTextView printing
  215.  
  216. BOOL CTextView::OnPreparePrinting(CPrintInfo* pInfo)
  217. {
  218.     // default preparation
  219.     return DoPreparePrinting(pInfo);
  220. }
  221.  
  222. void CTextView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  223. {
  224.     // TODO: add extra initialization before printing
  225. }
  226.  
  227. void CTextView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  228. {
  229.     // TODO: add cleanup after printing
  230. }
  231.  
  232. /////////////////////////////////////////////////////////////////////////////
  233. // CTextView diagnostics
  234.  
  235. #ifdef _DEBUG
  236. void CTextView::AssertValid() const
  237. {
  238.     CScrollView::AssertValid();
  239. }
  240.  
  241. void CTextView::Dump(CDumpContext& dc) const
  242. {
  243.     CScrollView::Dump(dc);
  244. }
  245.  
  246. CTextDoc* CTextView::GetDocument() // non-debug version is inline
  247. {
  248.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTextDoc)));
  249.     return (CTextDoc*)m_pDocument;
  250. }
  251. #endif //_DEBUG
  252.  
  253. /////////////////////////////////////////////////////////////////////////////
  254. // CTextView message handlers
  255.  
  256. void CTextView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
  257. {
  258.     ComputeViewMetrics();
  259.  
  260.     SetScrollSizes(MM_LOENGLISH, GetDocSize());
  261.     Invalidate();
  262. }
  263.