home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / ole / wordpad / ruler.cpp < prev    next >
C/C++ Source or Header  |  1998-03-26  |  22KB  |  853 lines

  1. // ruler.cpp : implementation file
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1998 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 related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "stdafx.h"
  14. #include "wordpad.h"
  15. #include "ruler.h"
  16. #include "wordpvw.h"
  17. #include "wordpdoc.h"
  18. #include "strings.h"
  19. #include <memory.h>
  20.  
  21. #ifdef _DEBUG
  22. #undef THIS_FILE
  23. static char BASED_CODE THIS_FILE[] = __FILE__;
  24. #endif
  25.  
  26. #define HEIGHT 17
  27. #define RULERBARHEIGHT 17
  28.  
  29. CRulerItem::CRulerItem(UINT nBitmapID)
  30. {
  31.     m_nAlignment = TA_CENTER;
  32.     m_pDC = NULL;
  33.     m_bTrack = FALSE;
  34.     m_hbm = NULL;
  35.     m_hbmMask = NULL;
  36.     if (nBitmapID != 0)
  37.     {
  38.         m_hbmMask = ::LoadBitmap(
  39.             AfxFindResourceHandle(MAKEINTRESOURCE(nBitmapID+1), RT_BITMAP),
  40.             MAKEINTRESOURCE(nBitmapID+1));
  41.         ASSERT(m_hbmMask != NULL);
  42.         VERIFY(LoadMaskedBitmap(MAKEINTRESOURCE(nBitmapID)));
  43.         BITMAP bm;
  44.         ::GetObject(m_hbm, sizeof(BITMAP), &bm);
  45.         m_size = CSize(bm.bmWidth, bm.bmHeight);
  46.     }
  47. }
  48.  
  49. CRulerItem::~CRulerItem()
  50. {
  51.     if (m_hbm != NULL)
  52.         ::DeleteObject(m_hbm);
  53.     if (m_hbmMask != NULL)
  54.         ::DeleteObject(m_hbmMask);
  55. }
  56.  
  57. BOOL CRulerItem::LoadMaskedBitmap(LPCTSTR lpszResourceName)
  58. {
  59.     ASSERT(lpszResourceName != NULL);
  60.  
  61.     if (m_hbm != NULL)
  62.         ::DeleteObject(m_hbm);
  63.  
  64.     HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_BITMAP);
  65.     HRSRC hRsrc = ::FindResource(hInst, lpszResourceName, RT_BITMAP);
  66.     if (hRsrc == NULL)
  67.         return FALSE;
  68.  
  69.     m_hbm = AfxLoadSysColorBitmap(hInst, hRsrc);
  70.     return (m_hbm != NULL);
  71. }
  72.  
  73. void CRulerItem::SetHorzPosTwips(int nXPos)
  74. {
  75.     if (GetHorzPosTwips() != nXPos)
  76.     {
  77.         if (m_bTrack)
  78.             DrawFocusLine();
  79.         Invalidate();
  80.         m_nXPosTwips = nXPos;
  81.         Invalidate();
  82.         if (m_bTrack)
  83.             DrawFocusLine();
  84.     }
  85. }
  86.  
  87. void CRulerItem::TrackHorzPosTwips(int nXPos, BOOL /*bOnRuler*/)
  88. {
  89.     int nMin = GetMin();
  90.     int nMax = GetMax();
  91.     if (nXPos < nMin)
  92.         nXPos = nMin;
  93.     if (nXPos > nMax)
  94.         nXPos = nMax;
  95.     SetHorzPosTwips(nXPos);
  96. }
  97.  
  98. void CRulerItem::DrawFocusLine()
  99. {
  100.     if (GetHorzPosTwips() != 0)
  101.     {
  102.         m_rcTrack.left = m_rcTrack.right = GetHorzPosPix();
  103.         ASSERT(m_pDC != NULL);
  104.         int nLeft = m_pRuler->XRulerToClient(m_rcTrack.left);
  105.         m_pDC->MoveTo(nLeft, m_rcTrack.top);
  106.         m_pDC->LineTo(nLeft, m_rcTrack.bottom);
  107.     }
  108. }
  109.  
  110. void CRulerItem::SetTrack(BOOL b)
  111. {
  112.     m_bTrack = b;
  113.  
  114.     if (m_pDC != NULL) // just in case we lost focus Capture somewhere
  115.     {
  116.         DrawFocusLine();
  117.         m_pDC->RestoreDC(-1);
  118.         delete m_pDC ;
  119.         m_pDC = NULL;
  120.     }
  121.     if (m_bTrack)
  122.     {
  123.         CWordPadView* pView = (CWordPadView*)m_pRuler->GetView();
  124.         ASSERT(pView != NULL);
  125.         pView->GetClientRect(&m_rcTrack);
  126.         m_pDC = new CWindowDC(pView);
  127.         m_pDC->SaveDC();
  128.         m_pDC->SelectObject(&m_pRuler->penFocusLine);
  129.         m_pDC->SetROP2(R2_XORPEN);
  130.         DrawFocusLine();
  131.     }
  132. }
  133.  
  134. void CRulerItem::Invalidate()
  135. {
  136.     CRect rc = GetHitRectPix();
  137.     m_pRuler->RulerToClient(rc.TopLeft());
  138.     m_pRuler->RulerToClient(rc.BottomRight());
  139.     m_pRuler->InvalidateRect(rc);
  140. }
  141.  
  142. CRect CRulerItem::GetHitRectPix()
  143. {
  144.     int nx = GetHorzPosPix();
  145.     return CRect(
  146.         CPoint(
  147.             (m_nAlignment == TA_CENTER) ? (nx - m_size.cx/2) :
  148.             (m_nAlignment == TA_LEFT) ? nx : nx - m_size.cx
  149.             , m_nYPosPix
  150.             ),
  151.         m_size);
  152. }
  153.  
  154. void CRulerItem::Draw(CDC& dc)
  155. {
  156.     CDC dcBitmap;
  157.     dcBitmap.CreateCompatibleDC(&dc);
  158.     CPoint pt(GetHorzPosPix(), GetVertPosPix());
  159.  
  160.     HGDIOBJ hbm = ::SelectObject(dcBitmap.m_hDC, m_hbmMask);
  161.  
  162.     // do mask part
  163.     if (m_nAlignment == TA_CENTER)
  164.         dc.BitBlt(pt.x - m_size.cx/2, pt.y, m_size.cx, m_size.cy, &dcBitmap, 0, 0, SRCAND);
  165.     else if (m_nAlignment == TA_LEFT)
  166.         dc.BitBlt(pt.x, pt.y, m_size.cx, m_size.cy, &dcBitmap, 0, 0, SRCAND);
  167.     else // TA_RIGHT
  168.         dc.BitBlt(pt.x - m_size.cx, pt.y, m_size.cx, m_size.cy, &dcBitmap, 0, 0, SRCAND);
  169.  
  170.     // do image part
  171.     ::SelectObject(dcBitmap.m_hDC, m_hbm);
  172.  
  173.     if (m_nAlignment == TA_CENTER)
  174.         dc.BitBlt(pt.x - m_size.cx/2, pt.y, m_size.cx, m_size.cy, &dcBitmap, 0, 0, SRCINVERT);
  175.     else if (m_nAlignment == TA_LEFT)
  176.         dc.BitBlt(pt.x, pt.y, m_size.cx, m_size.cy, &dcBitmap, 0, 0, SRCINVERT);
  177.     else // TA_RIGHT
  178.         dc.BitBlt(pt.x - m_size.cx, pt.y, m_size.cx, m_size.cy, &dcBitmap, 0, 0, SRCINVERT);
  179.  
  180.     ::SelectObject(dcBitmap.m_hDC, hbm);
  181. }
  182.  
  183. CComboRulerItem::CComboRulerItem(UINT nBitmapID1, UINT nBitmapID2, CRulerItem& item)
  184.     : CRulerItem(nBitmapID1), m_secondary(nBitmapID2) , m_link(item)
  185. {
  186.     m_bHitPrimary = TRUE;
  187. }
  188.  
  189. BOOL CComboRulerItem::HitTestPix(CPoint pt)
  190. {
  191.     m_bHitPrimary = FALSE;
  192.     if (CRulerItem::GetHitRectPix().PtInRect(pt))
  193.         m_bHitPrimary = TRUE;
  194.     else
  195.         return m_secondary.HitTestPix(pt);
  196.     return TRUE;
  197. }
  198.  
  199. void CComboRulerItem::Draw(CDC& dc)
  200. {
  201.     CRulerItem::Draw(dc);
  202.     m_secondary.Draw(dc);
  203. }
  204.  
  205. void CComboRulerItem::SetHorzPosTwips(int nXPos)
  206. {
  207.     if (m_bHitPrimary) // only change linked items by delta
  208.         m_link.SetHorzPosTwips(m_link.GetHorzPosTwips() + nXPos - GetHorzPosTwips());
  209.     CRulerItem::SetHorzPosTwips(nXPos);
  210.     m_secondary.SetHorzPosTwips(nXPos);
  211. }
  212.  
  213. void CComboRulerItem::TrackHorzPosTwips(int nXPos, BOOL /*bOnRuler*/)
  214. {
  215.     int nMin = GetMin();
  216.     int nMax = GetMax();
  217.     if (nXPos < nMin)
  218.         nXPos = nMin;
  219.     if (nXPos > nMax)
  220.         nXPos = nMax;
  221.     SetHorzPosTwips(nXPos);
  222. }
  223.  
  224. void CComboRulerItem::SetVertPos(int nYPos)
  225. {
  226.     m_secondary.SetVertPos(nYPos);
  227.     nYPos += m_secondary.GetHitRectPix().Height();
  228.     CRulerItem::SetVertPos(nYPos);
  229. }
  230.  
  231. void CComboRulerItem::SetAlignment(int nAlign)
  232. {
  233.     CRulerItem::SetAlignment(nAlign);
  234.     m_secondary.SetAlignment(nAlign);
  235. }
  236.  
  237. void CComboRulerItem::SetRuler(CRulerBar* pRuler)
  238. {
  239.     m_pRuler = pRuler;
  240.     m_secondary.SetRuler(pRuler);
  241. }
  242.  
  243. void CComboRulerItem::SetBounds(int nMin, int nMax)
  244. {
  245.     CRulerItem::SetBounds(nMin, nMax);
  246.     m_secondary.SetBounds(nMin, nMax);
  247. }
  248.  
  249. int CComboRulerItem::GetMin()
  250. {
  251.     if (m_bHitPrimary)
  252.     {
  253.         int nPDist = GetHorzPosTwips() - CRulerItem::GetMin();
  254.         int nLDist = m_link.GetHorzPosTwips() - m_link.GetMin();
  255.         return GetHorzPosTwips() - min(nPDist, nLDist);
  256.     }
  257.     else
  258.         return CRulerItem::GetMin();
  259. }
  260.  
  261. int CComboRulerItem::GetMax()
  262. {
  263.     if (m_bHitPrimary)
  264.     {
  265.         int nPDist = CRulerItem::GetMax() - GetHorzPosTwips();
  266.         int nLDist = m_link.GetMax() - m_link.GetHorzPosTwips();
  267.         int nMinDist = (nPDist < nLDist) ? nPDist : nLDist;
  268.         return GetHorzPosTwips() + nMinDist;
  269.     }
  270.     else
  271.         return CRulerItem::GetMax();
  272. }
  273.  
  274. void CTabRulerItem::TrackHorzPosTwips(int nXPos, BOOL bOnRuler)
  275. {
  276.     if (bOnRuler)
  277.         CRulerItem::TrackHorzPosTwips(nXPos, bOnRuler);
  278.     else
  279.         CRulerItem::TrackHorzPosTwips(0, bOnRuler);
  280. }
  281.  
  282.  
  283. BEGIN_MESSAGE_MAP(CRulerBar, CControlBar)
  284.     //{{AFX_MSG_MAP(CRulerBar)
  285.     ON_WM_LBUTTONDOWN()
  286.     ON_WM_LBUTTONUP()
  287.     ON_WM_MOUSEMOVE()
  288.     ON_WM_SYSCOLORCHANGE()
  289.     ON_WM_WINDOWPOSCHANGING()
  290.     ON_WM_SHOWWINDOW()
  291.     ON_WM_WINDOWPOSCHANGED()
  292.     //}}AFX_MSG_MAP
  293.     ON_MESSAGE(WM_SIZEPARENT, OnSizeParent)
  294.     // Global help commands
  295. END_MESSAGE_MAP()
  296.  
  297. CRulerBar::CRulerBar(BOOL b3DExt) :
  298.     m_leftmargin(IDB_RULER_BLOCK, IDB_RULER_UP, m_indent),
  299.     m_indent(IDB_RULER_DOWN),
  300.     m_rightmargin(IDB_RULER_UP),
  301.     m_tabItem(IDB_RULER_TAB)
  302. {
  303.     m_bDeferInProgress = FALSE;
  304.     m_leftmargin.SetRuler(this);
  305.     m_indent.SetRuler(this);
  306.     m_rightmargin.SetRuler(this);
  307.  
  308.     // all of the tab stops share handles
  309.     for (int i=0;i<MAX_TAB_STOPS;i++)
  310.     {
  311.         m_pTabItems[i].m_hbm = m_tabItem.m_hbm;
  312.         m_pTabItems[i].m_hbmMask = m_tabItem.m_hbmMask;
  313.         m_pTabItems[i].m_size = m_tabItem.m_size;
  314.     }
  315.  
  316.     m_unit.m_nTPU = 0;
  317.     m_nScroll = 0;
  318.  
  319.     LOGFONT lf;
  320.     memcpy(&lf, &theApp.m_lf, sizeof(LOGFONT));
  321.     lf.lfHeight = -8;
  322.     lf.lfWidth = 0;
  323.     VERIFY(fnt.CreateFontIndirect(&lf));
  324.  
  325.     m_nTabs = 0;
  326.     m_leftmargin.SetVertPos(9);
  327.     m_indent.SetVertPos(-1);
  328.     m_rightmargin.SetVertPos(9);
  329.  
  330.     m_cxLeftBorder = 0;
  331.     if (!theApp.m_bWin4)
  332.         m_bDraw3DExt = FALSE;
  333.     else
  334.         m_bDraw3DExt = b3DExt;
  335.  
  336.     m_cyTopBorder = 4;
  337.     m_cyBottomBorder = 6;
  338.  
  339.     m_pSelItem = NULL;
  340.  
  341.     m_logx = theApp.m_dcScreen.GetDeviceCaps(LOGPIXELSX);
  342.  
  343.     CreateGDIObjects();
  344. }
  345.  
  346. CRulerBar::~CRulerBar()
  347. {
  348.     // set handles to NULL to avoid deleting twice
  349.     for (int i=0;i<MAX_TAB_STOPS;i++)
  350.     {
  351.         m_pTabItems[i].m_hbm = NULL;
  352.         m_pTabItems[i].m_hbmMask = NULL;
  353.     }
  354. }
  355.  
  356. void CRulerBar::CreateGDIObjects()
  357. {
  358.     penFocusLine.DeleteObject();
  359.     penBtnHighLight.DeleteObject();
  360.     penBtnShadow.DeleteObject();
  361.     penWindowFrame.DeleteObject();
  362.     penBtnText.DeleteObject();
  363.     penBtnFace.DeleteObject();
  364.     penWindowText.DeleteObject();
  365.     penWindow.DeleteObject();
  366.     brushWindow.DeleteObject();
  367.     brushBtnFace.DeleteObject();
  368.  
  369.     penFocusLine.CreatePen(PS_DOT, 1,GetSysColor(COLOR_WINDOWTEXT));
  370.     penBtnHighLight.CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNHIGHLIGHT));
  371.     penBtnShadow.CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNSHADOW));
  372.     penWindowFrame.CreatePen(PS_SOLID, 0, GetSysColor(COLOR_WINDOWFRAME));
  373.     penBtnText.CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNTEXT));
  374.     penBtnFace.CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNFACE));
  375.     penWindowText.CreatePen(PS_SOLID, 0, GetSysColor(COLOR_WINDOWTEXT));
  376.     penWindow.CreatePen(PS_SOLID, 0, GetSysColor(COLOR_WINDOW));
  377.     brushWindow.CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  378.     brushBtnFace.CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  379. }
  380.  
  381. void CRulerBar::OnUpdateCmdUI(CFrameWnd* /*pTarget*/, BOOL /*bDisableIfNoHndler*/)
  382. {
  383.     ASSERT_VALID(this);
  384.     //Get the page size and see if changed -- from document
  385.     //get margins and tabs and see if changed -- from view
  386.     if (m_pSelItem == NULL) // only update if not in middle of dragging
  387.     {
  388.         CWordPadView* pView = (CWordPadView*)GetView();
  389.         ASSERT(pView != NULL);
  390.         Update(pView->GetPaperSize(), pView->GetMargins());
  391.         Update(pView->GetParaFormatSelection());
  392.         CRect rect;
  393.         pView->GetRichEditCtrl().GetRect(&rect);
  394.         CPoint pt = rect.TopLeft();
  395.         pView->ClientToScreen(&pt);
  396.         ScreenToClient(&pt);
  397.         if (m_cxLeftBorder != pt.x)
  398.         {
  399.             m_cxLeftBorder = pt.x;
  400.             Invalidate();
  401.         }
  402.         int nScroll = pView->GetScrollPos(SB_HORZ);
  403.         if (nScroll != m_nScroll)
  404.         {
  405.             m_nScroll = nScroll;
  406.             Invalidate();
  407.         }
  408.     }
  409. }
  410.  
  411. CSize CRulerBar::GetBaseUnits()
  412. {
  413.     ASSERT(fnt.GetSafeHandle() != NULL);
  414.     CFont* pFont = theApp.m_dcScreen.SelectObject(&fnt);
  415.     TEXTMETRIC tm;
  416.     VERIFY(theApp.m_dcScreen.GetTextMetrics(&tm) == TRUE);
  417.     theApp.m_dcScreen.SelectObject(pFont);
  418. //  return CSize(tm.tmAveCharWidth, tm.tmHeight+tm.tmDescent);
  419.     return CSize(tm.tmAveCharWidth, tm.tmHeight);
  420. }
  421.  
  422. BOOL CRulerBar::Create(CWnd* pParentWnd, DWORD dwStyle, UINT nID)
  423. {
  424.     ASSERT_VALID(pParentWnd);   // must have a parent
  425.  
  426.     dwStyle |= WS_CLIPSIBLINGS;
  427.     // force WS_CLIPSIBLINGS (avoids SetWindowPos bugs)
  428.     m_dwStyle = (dwStyle & CBRS_ALL);
  429.  
  430.     // create the HWND
  431.     CRect rect;
  432.     rect.SetRectEmpty();
  433.     LPCTSTR lpszClass = AfxRegisterWndClass(0, ::LoadCursor(NULL, IDC_ARROW),
  434.         (HBRUSH)(COLOR_BTNFACE+1), NULL);
  435.  
  436.     if (!CWnd::Create(lpszClass, NULL, dwStyle, rect, pParentWnd, nID))
  437.         return FALSE;
  438.     // NOTE: Parent must resize itself for control bar to be resized
  439.  
  440.     int i;
  441.     int nMax = 100;
  442.     for (i=0;i<MAX_TAB_STOPS;i++)
  443.     {
  444.         m_pTabItems[i].SetRuler(this);
  445.         m_pTabItems[i].SetVertPos(8);
  446.         m_pTabItems[i].SetHorzPosTwips(0);
  447.         m_pTabItems[i].SetBounds(0, nMax);
  448.     }
  449.     return TRUE;
  450. }
  451.  
  452. CSize CRulerBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
  453. {
  454.     ASSERT(bHorz);
  455.     CSize m_size = CControlBar::CalcFixedLayout(bStretch, bHorz);
  456.     CRect rectSize;
  457.     rectSize.SetRectEmpty();
  458.     CalcInsideRect(rectSize, bHorz);       // will be negative size
  459.     m_size.cy = RULERBARHEIGHT - rectSize.Height();
  460.     return m_size;
  461. }
  462.  
  463. void CRulerBar::Update(const PARAFORMAT& pf)
  464. {
  465.     ASSERT(pf.cTabCount <= MAX_TAB_STOPS);
  466.  
  467.     m_leftmargin.SetHorzPosTwips((int)(pf.dxStartIndent + pf.dxOffset));
  468.     m_indent.SetHorzPosTwips((int)pf.dxStartIndent);
  469.     m_rightmargin.SetHorzPosTwips(PrintWidth() - (int) pf.dxRightIndent);
  470.  
  471.     int i = 0;
  472.     for (i=0;i<pf.cTabCount;i++)
  473.         m_pTabItems[i].SetHorzPosTwips((int)pf.rgxTabs[i]);
  474.     for ( ;i<MAX_TAB_STOPS; i++)
  475.         m_pTabItems[i].SetHorzPosTwips(0);
  476. }
  477.  
  478. void CRulerBar::Update(CSize sizePaper, const CRect& rectMargins)
  479. {
  480.     if ((sizePaper != m_sizePaper) || (rectMargins != m_rectMargin))
  481.     {
  482.         m_sizePaper = sizePaper;
  483.         m_rectMargin = rectMargins;
  484.         Invalidate();
  485.     }
  486.     if (m_unit.m_nTPU != theApp.GetTPU())
  487.     {
  488.         m_unit = theApp.GetUnit();
  489.         Invalidate();
  490.     }
  491. }
  492.  
  493. void CRulerBar::FillInParaFormat(PARAFORMAT& pf)
  494. {
  495.     pf.dwMask = PFM_STARTINDENT | PFM_RIGHTINDENT | PFM_OFFSET | PFM_TABSTOPS;
  496.     pf.dxStartIndent = m_indent.GetHorzPosTwips();
  497.     pf.dxOffset = m_leftmargin.GetHorzPosTwips() - pf.dxStartIndent;
  498.     pf.dxRightIndent = PrintWidth() - m_rightmargin.GetHorzPosTwips();
  499.     pf.cTabCount = 0L;
  500.     SortTabs();
  501.     int i, nPos = 0;
  502.     for (i=0;i<MAX_TAB_STOPS;i++)
  503.     {
  504.         // get rid of zeroes and multiples
  505.         // i.e. if we have 0,0,0,1,2,3,4,4,5
  506.         // we will get tabs at 1,2,3,4,5
  507.         if (nPos != m_pTabItems[i].GetHorzPosTwips())
  508.         {
  509.             nPos = m_pTabItems[i].GetHorzPosTwips();
  510.             pf.rgxTabs[pf.cTabCount++] = nPos;
  511.         }
  512.     }
  513. }
  514.  
  515. // simple bubble sort is adequate for small number of tabs
  516. void CRulerBar::SortTabs()
  517. {
  518.     int i,j, nPos;
  519.     for (i=0;i<MAX_TAB_STOPS - 1;i++)
  520.     {
  521.         for (j=i+1; j < MAX_TAB_STOPS;j++)
  522.         {
  523.             if (m_pTabItems[j].GetHorzPosTwips() < m_pTabItems[i].GetHorzPosTwips())
  524.             {
  525.                 nPos = m_pTabItems[j].GetHorzPosTwips();
  526.                 m_pTabItems[j].SetHorzPosTwips(m_pTabItems[i].GetHorzPosTwips());
  527.                 m_pTabItems[i].SetHorzPosTwips(nPos);
  528.             }
  529.         }
  530.     }
  531. }
  532.  
  533. void CRulerBar::DoPaint(CDC* pDC)
  534. {
  535.     CControlBar::DoPaint(pDC); // CControlBar::DoPaint -- draws border
  536.     if (m_unit.m_nTPU != 0)
  537.     {
  538.         pDC->SaveDC();
  539.         // offset coordinate system
  540.         CPoint pointOffset(0,0);
  541.         RulerToClient(pointOffset);
  542.         pDC->SetViewportOrg(pointOffset);
  543.  
  544.         DrawFace(*pDC);
  545.         DrawTickMarks(*pDC);
  546.  
  547.         DrawTabs(*pDC);
  548.         m_leftmargin.Draw(*pDC);
  549.         m_indent.Draw(*pDC);
  550.         m_rightmargin.Draw(*pDC);
  551.  
  552.         pDC->RestoreDC(-1);
  553.     }
  554.     // Do not call CControlBar::OnPaint() for painting messages
  555. }
  556.  
  557. void CRulerBar::DrawTabs(CDC& dc)
  558. {
  559.     int i;
  560.     int nPos = 0;
  561.     for (i=0;i<MAX_TAB_STOPS;i++)
  562.     {
  563.         if (m_pTabItems[i].GetHorzPosTwips() > nPos)
  564.             nPos = (m_pTabItems[i].GetHorzPosTwips());
  565.         m_pTabItems[i].Draw(dc);
  566.     }
  567.     int nPageWidth = PrintWidth();
  568.     nPos = nPos - nPos%720 + 720;
  569.     dc.SelectObject(&penBtnShadow);
  570.     for ( ; nPos < nPageWidth; nPos += 720)
  571.     {
  572.         int nx = XTwipsToRuler(nPos);
  573.         dc.MoveTo(nx, HEIGHT - 1);
  574.         dc.LineTo(nx, HEIGHT + 1);
  575.     }
  576. }
  577.  
  578. void CRulerBar::DrawFace(CDC& dc)
  579. {
  580.     int nPageWidth = XTwipsToRuler(PrintWidth());
  581.     int nPageEdge = XTwipsToRuler(PrintWidth() + m_rectMargin.right);
  582.  
  583.     dc.SaveDC();
  584.  
  585.     dc.SelectObject(&penBtnShadow);
  586.     dc.MoveTo(0,0);
  587.     dc.LineTo(nPageEdge - 1, 0);
  588.     dc.LineTo(nPageEdge - 1, HEIGHT - 2);
  589.     dc.LineTo(nPageWidth - 1, HEIGHT - 2);
  590.     dc.LineTo(nPageWidth - 1, 1);
  591.     dc.LineTo(nPageWidth, 1);
  592.     dc.LineTo(nPageWidth, HEIGHT -2);
  593.  
  594.     dc.SelectObject(&penBtnHighLight);
  595.     dc.MoveTo(nPageWidth, HEIGHT - 1);
  596.     dc.LineTo(nPageEdge, HEIGHT -1);
  597.     dc.MoveTo(nPageWidth + 1, HEIGHT - 3);
  598.     dc.LineTo(nPageWidth + 1, 1);
  599.     dc.LineTo(nPageEdge - 1, 1);
  600.  
  601.     dc.SelectObject(&penWindow);
  602.     dc.MoveTo(0, HEIGHT - 1);
  603.     dc.LineTo(nPageWidth, HEIGHT -1);
  604.  
  605.     dc.SelectObject(&penBtnFace);
  606.     dc.MoveTo(1, HEIGHT - 2);
  607.     dc.LineTo(nPageWidth - 1, HEIGHT - 2);
  608.  
  609.     dc.SelectObject(&penWindowFrame);
  610.     dc.MoveTo(0, HEIGHT - 2);
  611.     dc.LineTo(0, 1);
  612.     dc.LineTo(nPageWidth - 1, 1);
  613.  
  614.     dc.FillRect(CRect(1, 2, nPageWidth - 1, HEIGHT-2), &brushWindow);
  615.     dc.FillRect(CRect(nPageWidth + 2, 2, nPageEdge - 1, HEIGHT-2), &brushBtnFace);
  616.  
  617.     CRect rcClient;
  618.     GetClientRect(&rcClient);
  619.     ClientToRuler(rcClient);
  620.     rcClient.top = HEIGHT;
  621.     rcClient.bottom = HEIGHT + 2;
  622.     dc.FillRect(rcClient, &brushBtnFace);
  623.  
  624.     CRect rectFill(rcClient.left, HEIGHT+4, rcClient.right, HEIGHT+9);
  625.     dc.FillRect(rectFill, &brushWindow);
  626.  
  627.     if (m_bDraw3DExt)  // draws the 3D extension into the view
  628.     {
  629.         dc.SelectObject(&penBtnShadow);
  630.         dc.MoveTo(rcClient.left, HEIGHT+8);
  631.         dc.LineTo(rcClient.left, HEIGHT+2);
  632.         dc.LineTo(rcClient.right-1, HEIGHT+2);
  633.  
  634.         dc.SelectObject(&penWindowFrame);
  635.         dc.MoveTo(rcClient.left+1, HEIGHT+8);
  636.         dc.LineTo(rcClient.left+1, HEIGHT+3);
  637.         dc.LineTo(rcClient.right-2, HEIGHT+3);
  638.  
  639.         dc.SelectObject(&penBtnHighLight);
  640.         dc.MoveTo(rcClient.right-1, HEIGHT+2);
  641.         dc.LineTo(rcClient.right-1, HEIGHT+8);
  642.  
  643.         dc.SelectObject(&penBtnFace);
  644.         dc.MoveTo(rcClient.right-2, HEIGHT+3);
  645.         dc.LineTo(rcClient.right-2, HEIGHT+8);
  646.     }
  647.     else
  648.     {
  649.         dc.SelectObject(&penBtnShadow);
  650.         dc.MoveTo(rcClient.left, HEIGHT+2);
  651.         dc.LineTo(rcClient.right, HEIGHT+2);
  652.  
  653.         dc.SelectObject(&penWindowFrame);
  654.         dc.MoveTo(rcClient.left, HEIGHT+3);
  655.         dc.LineTo(rcClient.right, HEIGHT+3);
  656.     }
  657.  
  658.     dc.RestoreDC(-1);
  659. }
  660.  
  661. void CRulerBar::DrawTickMarks(CDC& dc)
  662. {
  663.     dc.SaveDC();
  664.  
  665.     dc.SelectObject(&penWindowText);
  666.     dc.SelectObject(&fnt);
  667.     dc.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
  668.     dc.SetBkMode(TRANSPARENT);
  669.  
  670.     DrawDiv(dc, m_unit.m_nSmallDiv, m_unit.m_nLargeDiv, 2);
  671.     DrawDiv(dc, m_unit.m_nMediumDiv, m_unit.m_nLargeDiv, 5);
  672.     DrawNumbers(dc, m_unit.m_nLargeDiv, m_unit.m_nTPU);
  673.  
  674.     dc.RestoreDC(-1);
  675. }
  676.  
  677. void CRulerBar::DrawNumbers(CDC& dc, int nInc, int nTPU)
  678. {
  679.     int nPageWidth = PrintWidth();
  680.     int nPageEdge = nPageWidth + m_rectMargin.right;
  681.     TCHAR buf[10];
  682.  
  683.     int nTwips, nPixel, nLen;
  684.  
  685.     for (nTwips = nInc; nTwips < nPageEdge; nTwips += nInc)
  686.     {
  687.         if (nTwips == nPageWidth)
  688.             continue;
  689.         nPixel = XTwipsToRuler(nTwips);
  690.         wsprintf(buf, _T("%d"), nTwips/nTPU);
  691.         nLen = lstrlen(buf);
  692.         CSize sz = dc.GetTextExtent(buf, nLen);
  693.         dc.ExtTextOut(nPixel - sz.cx/2, HEIGHT/2 - sz.cy/2, 0, NULL, buf, nLen, NULL);
  694.     }
  695. }
  696.  
  697. void CRulerBar::DrawDiv(CDC& dc, int nInc, int nLargeDiv, int nLength)
  698. {
  699.     int nPageWidth = PrintWidth();
  700.     int nPageEdge = nPageWidth + m_rectMargin.right;
  701.  
  702.     int nTwips, nPixel;
  703.  
  704.     for (nTwips = nInc; nTwips < nPageEdge; nTwips += nInc)
  705.     {
  706.         if (nTwips == nPageWidth || nTwips%nLargeDiv == 0)
  707.             continue;
  708.         nPixel = XTwipsToRuler(nTwips);
  709.         dc.MoveTo(nPixel, HEIGHT/2 - nLength/2);
  710.         dc.LineTo(nPixel, HEIGHT/2 - nLength/2 + nLength);
  711.     }
  712. }
  713.  
  714. void CRulerBar::OnLButtonDown(UINT nFlags, CPoint point)
  715. {
  716.     CPoint pt = point;
  717.     ClientToRuler(pt);
  718.  
  719.     m_pSelItem = NULL;
  720.     if (m_leftmargin.HitTestPix(pt))
  721.         m_pSelItem = &m_leftmargin;
  722.     else if (m_indent.HitTestPix(pt))
  723.         m_pSelItem = &m_indent;
  724.     else if (m_rightmargin.HitTestPix(pt))
  725.         m_pSelItem = &m_rightmargin;
  726.     else
  727.         m_pSelItem = GetHitTabPix(pt);
  728.     if (m_pSelItem == NULL)
  729.         m_pSelItem = GetFreeTab();
  730.     if (m_pSelItem == NULL)
  731.         return;
  732.     SetCapture();
  733.  
  734.     m_pSelItem->SetTrack(TRUE);
  735.     SetMarginBounds();
  736.     OnMouseMove(nFlags, point);
  737. }
  738.  
  739. void CRulerBar::SetMarginBounds()
  740. {
  741.     m_leftmargin.SetBounds(0, m_rightmargin.GetHorzPosTwips());
  742.     m_indent.SetBounds(0, m_rightmargin.GetHorzPosTwips());
  743.  
  744.     int nMin = (m_leftmargin.GetHorzPosTwips() > m_indent.GetHorzPosTwips()) ?
  745.         m_leftmargin.GetHorzPosTwips() : m_indent.GetHorzPosTwips();
  746.     int nMax = PrintWidth() + m_rectMargin.right;
  747.     m_rightmargin.SetBounds(nMin, nMax);
  748.  
  749.     // tabs can go from zero to the right page edge
  750.     for (int i=0;i<MAX_TAB_STOPS;i++)
  751.         m_pTabItems[i].SetBounds(0, nMax);
  752. }
  753.  
  754. CRulerItem* CRulerBar::GetFreeTab()
  755. {
  756.     int i;
  757.     for (i=0;i<MAX_TAB_STOPS;i++)
  758.     {
  759.         if (m_pTabItems[i].GetHorzPosTwips() == 0)
  760.             return &m_pTabItems[i];
  761.     }
  762.     return NULL;
  763. }
  764.  
  765. CTabRulerItem* CRulerBar::GetHitTabPix(CPoint point)
  766. {
  767.     int i;
  768.     for (i=0;i<MAX_TAB_STOPS;i++)
  769.     {
  770.         if (m_pTabItems[i].HitTestPix(point))
  771.             return &m_pTabItems[i];
  772.     }
  773.     return NULL;
  774. }
  775.  
  776. void CRulerBar::OnLButtonUp(UINT nFlags, CPoint point)
  777. {
  778.     if (::GetCapture() != m_hWnd)
  779.         return;
  780.     OnMouseMove(nFlags, point);
  781.     m_pSelItem->SetTrack(FALSE);
  782.     ReleaseCapture();
  783.     CWordPadView* pView = (CWordPadView*)GetView();
  784.     ASSERT(pView != NULL);
  785.     PARAFORMAT& pf = pView->GetParaFormatSelection();
  786.     FillInParaFormat(pf);
  787.     pView->SetParaFormat(pf);
  788.     m_pSelItem = NULL;
  789. }
  790.  
  791. void CRulerBar::OnMouseMove(UINT nFlags, CPoint point)
  792. {
  793.     CControlBar::OnMouseMove(nFlags, point);
  794. // use ::GetCapture to avoid creating temporaries
  795.     if (::GetCapture() != m_hWnd)
  796.         return;
  797.     ASSERT(m_pSelItem != NULL);
  798.     CRect rc(0,0, XTwipsToRuler(PrintWidth() + m_rectMargin.right), HEIGHT);
  799.     RulerToClient(rc);
  800.     BOOL bOnRuler = rc.PtInRect(point);
  801.  
  802. // snap to minimum movement
  803.     point.x = XClientToTwips(point.x);
  804.     point.x += m_unit.m_nMinMove/2;
  805.     point.x -= point.x%m_unit.m_nMinMove;
  806.  
  807.     m_pSelItem->TrackHorzPosTwips(point.x, bOnRuler);
  808.     UpdateWindow();
  809. }
  810.  
  811. void CRulerBar::OnSysColorChange()
  812. {
  813.     CControlBar::OnSysColorChange();
  814.     CreateGDIObjects();
  815.     Invalidate();
  816. }
  817.  
  818. void CRulerBar::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
  819. {
  820.     CControlBar::OnWindowPosChanging(lpwndpos);
  821.     CRect rect;
  822.     GetClientRect(rect);
  823.     int minx = min(rect.Width(), lpwndpos->cx);
  824.     int maxx = max(rect.Width(), lpwndpos->cx);
  825.     rect.SetRect(minx-2, rect.bottom - 6, minx, rect.bottom);
  826.     InvalidateRect(rect);
  827.     rect.SetRect(maxx-2, rect.bottom - 6, maxx, rect.bottom);
  828.     InvalidateRect(rect);
  829. }
  830.  
  831. void CRulerBar::OnShowWindow(BOOL bShow, UINT nStatus)
  832. {
  833.     CControlBar::OnShowWindow(bShow, nStatus);
  834.     m_bDeferInProgress = FALSE;
  835. }
  836.  
  837. void CRulerBar::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos)
  838. {
  839.     CControlBar::OnWindowPosChanged(lpwndpos);
  840.     m_bDeferInProgress = FALSE;
  841. }
  842.  
  843. LRESULT CRulerBar::OnSizeParent(WPARAM wParam, LPARAM lParam)
  844. {
  845.     BOOL bVis = GetStyle() & WS_VISIBLE;
  846.     if ((bVis && (m_nStateFlags & delayHide)) ||
  847.         (!bVis && (m_nStateFlags & delayShow)))
  848.     {
  849.         m_bDeferInProgress = TRUE;
  850.     }
  851.     return CControlBar::OnSizeParent(wParam, lParam);
  852. }
  853.