Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

833 lines
23 KiB

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