// ruler.cpp : implementation file // // This is a part of the Microsoft Foundation Classes C++ library. // Copyright (C) 1992-1998 Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Microsoft Foundation Classes Reference and related // electronic documentation provided with the library. // See these sources for detailed information regarding the // Microsoft Foundation Classes product. #include "stdafx.h" #include "wordpad.h" #include "ruler.h" #include "wordpvw.h" #include "wordpdoc.h" #include "strings.h" #include #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif #define HEIGHT 17 #define RULERBARHEIGHT 17 CRulerItem::CRulerItem(UINT nBitmapID) { m_nAlignment = TA_CENTER; m_pDC = NULL; m_bTrack = FALSE; m_hbm = NULL; m_hbmMask = NULL; if (nBitmapID != 0) { m_hbmMask = ::LoadBitmap( AfxFindResourceHandle(MAKEINTRESOURCE(nBitmapID+1), RT_BITMAP), MAKEINTRESOURCE(nBitmapID+1)); ASSERT(m_hbmMask != NULL); VERIFY(LoadMaskedBitmap(MAKEINTRESOURCE(nBitmapID))); BITMAP bm; ::GetObject(m_hbm, sizeof(BITMAP), &bm); m_size = CSize(bm.bmWidth, bm.bmHeight); } } CRulerItem::~CRulerItem() { if (m_hbm != NULL) ::DeleteObject(m_hbm); if (m_hbmMask != NULL) ::DeleteObject(m_hbmMask); } BOOL CRulerItem::LoadMaskedBitmap(LPCTSTR lpszResourceName) { ASSERT(lpszResourceName != NULL); if (m_hbm != NULL) ::DeleteObject(m_hbm); HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_BITMAP); HRSRC hRsrc = ::FindResource(hInst, lpszResourceName, RT_BITMAP); if (hRsrc == NULL) return FALSE; m_hbm = AfxLoadSysColorBitmap(hInst, hRsrc); return (m_hbm != NULL); } void CRulerItem::SetHorzPosTwips(int nXPos) { if (GetHorzPosTwips() != nXPos) { if (m_bTrack) DrawFocusLine(); Invalidate(); m_nXPosTwips = nXPos; Invalidate(); if (m_bTrack) DrawFocusLine(); } } void CRulerItem::TrackHorzPosTwips(int nXPos, BOOL /*bOnRuler*/) { int nMin = GetMin(); int nMax = GetMax(); if (nXPos < nMin) nXPos = nMin; if (nXPos > nMax) nXPos = nMax; SetHorzPosTwips(nXPos); } void CRulerItem::DrawFocusLine() { if (GetHorzPosTwips() != 0) { m_rcTrack.left = m_rcTrack.right = GetHorzPosPix(); ASSERT(m_pDC != NULL); int nLeft = m_pRuler->XRulerToClient(m_rcTrack.left); m_pDC->MoveTo(nLeft, m_rcTrack.top); m_pDC->LineTo(nLeft, m_rcTrack.bottom); } } void CRulerItem::SetTrack(BOOL b) { m_bTrack = b; if (m_pDC != NULL) // just in case we lost focus Capture somewhere { DrawFocusLine(); m_pDC->RestoreDC(-1); delete m_pDC ; m_pDC = NULL; } if (m_bTrack) { CWordPadView* pView = (CWordPadView*)m_pRuler->GetView(); ASSERT(pView != NULL); pView->GetClientRect(&m_rcTrack); m_pDC = new CWindowDC(pView); m_pDC->SaveDC(); m_pDC->SelectObject(&m_pRuler->penFocusLine); m_pDC->SetROP2(R2_XORPEN); DrawFocusLine(); } } void CRulerItem::Invalidate() { CRect rc = GetHitRectPix(); m_pRuler->RulerToClient(rc.TopLeft()); m_pRuler->RulerToClient(rc.BottomRight()); m_pRuler->InvalidateRect(rc); } CRect CRulerItem::GetHitRectPix() { int nx = GetHorzPosPix(); return CRect( CPoint( (m_nAlignment == TA_CENTER) ? (nx - m_size.cx/2) : (m_nAlignment == TA_LEFT) ? nx : nx - m_size.cx , m_nYPosPix ), m_size); } void CRulerItem::Draw(CDC& dc) { CDC dcBitmap; dcBitmap.CreateCompatibleDC(&dc); CPoint pt(GetHorzPosPix(), GetVertPosPix()); HGDIOBJ hbm = ::SelectObject(dcBitmap.m_hDC, m_hbmMask); // do mask part if (m_nAlignment == TA_CENTER) dc.BitBlt(pt.x - m_size.cx/2, pt.y, m_size.cx, m_size.cy, &dcBitmap, 0, 0, SRCAND); else if (m_nAlignment == TA_LEFT) dc.BitBlt(pt.x, pt.y, m_size.cx, m_size.cy, &dcBitmap, 0, 0, SRCAND); else // TA_RIGHT dc.BitBlt(pt.x - m_size.cx, pt.y, m_size.cx, m_size.cy, &dcBitmap, 0, 0, SRCAND); // do image part ::SelectObject(dcBitmap.m_hDC, m_hbm); if (m_nAlignment == TA_CENTER) dc.BitBlt(pt.x - m_size.cx/2, pt.y, m_size.cx, m_size.cy, &dcBitmap, 0, 0, SRCINVERT); else if (m_nAlignment == TA_LEFT) dc.BitBlt(pt.x, pt.y, m_size.cx, m_size.cy, &dcBitmap, 0, 0, SRCINVERT); else // TA_RIGHT dc.BitBlt(pt.x - m_size.cx, pt.y, m_size.cx, m_size.cy, &dcBitmap, 0, 0, SRCINVERT); ::SelectObject(dcBitmap.m_hDC, hbm); } CComboRulerItem::CComboRulerItem(UINT nBitmapID1, UINT nBitmapID2, CRulerItem& item) : CRulerItem(nBitmapID1), m_secondary(nBitmapID2) , m_link(item) { m_bHitPrimary = TRUE; } BOOL CComboRulerItem::HitTestPix(CPoint pt) { m_bHitPrimary = FALSE; if (CRulerItem::GetHitRectPix().PtInRect(pt)) m_bHitPrimary = TRUE; else return m_secondary.HitTestPix(pt); return TRUE; } void CComboRulerItem::Draw(CDC& dc) { CRulerItem::Draw(dc); m_secondary.Draw(dc); } void CComboRulerItem::SetHorzPosTwips(int nXPos) { if (m_bHitPrimary) // only change linked items by delta m_link.SetHorzPosTwips(m_link.GetHorzPosTwips() + nXPos - GetHorzPosTwips()); CRulerItem::SetHorzPosTwips(nXPos); m_secondary.SetHorzPosTwips(nXPos); } void CComboRulerItem::TrackHorzPosTwips(int nXPos, BOOL /*bOnRuler*/) { int nMin = GetMin(); int nMax = GetMax(); if (nXPos < nMin) nXPos = nMin; if (nXPos > nMax) nXPos = nMax; SetHorzPosTwips(nXPos); } void CComboRulerItem::SetVertPos(int nYPos) { m_secondary.SetVertPos(nYPos); nYPos += m_secondary.GetHitRectPix().Height(); CRulerItem::SetVertPos(nYPos); } void CComboRulerItem::SetAlignment(int nAlign) { CRulerItem::SetAlignment(nAlign); m_secondary.SetAlignment(nAlign); } void CComboRulerItem::SetRuler(CRulerBar* pRuler) { m_pRuler = pRuler; m_secondary.SetRuler(pRuler); } void CComboRulerItem::SetBounds(int nMin, int nMax) { CRulerItem::SetBounds(nMin, nMax); m_secondary.SetBounds(nMin, nMax); } int CComboRulerItem::GetMin() { if (m_bHitPrimary) { int nPDist = GetHorzPosTwips() - CRulerItem::GetMin(); int nLDist = m_link.GetHorzPosTwips() - m_link.GetMin(); return GetHorzPosTwips() - min(nPDist, nLDist); } else return CRulerItem::GetMin(); } int CComboRulerItem::GetMax() { if (m_bHitPrimary) { int nPDist = CRulerItem::GetMax() - GetHorzPosTwips(); int nLDist = m_link.GetMax() - m_link.GetHorzPosTwips(); int nMinDist = (nPDist < nLDist) ? nPDist : nLDist; return GetHorzPosTwips() + nMinDist; } else return CRulerItem::GetMax(); } void CTabRulerItem::TrackHorzPosTwips(int nXPos, BOOL bOnRuler) { if (bOnRuler) CRulerItem::TrackHorzPosTwips(nXPos, bOnRuler); else CRulerItem::TrackHorzPosTwips(0, bOnRuler); } BEGIN_MESSAGE_MAP(CRulerBar, CControlBar) //{{AFX_MSG_MAP(CRulerBar) ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_MOUSEMOVE() ON_WM_SYSCOLORCHANGE() ON_WM_WINDOWPOSCHANGING() ON_WM_SHOWWINDOW() ON_WM_WINDOWPOSCHANGED() //}}AFX_MSG_MAP ON_MESSAGE(WM_SIZEPARENT, OnSizeParent) // Global help commands END_MESSAGE_MAP() CRulerBar::CRulerBar(BOOL b3DExt) : m_leftmargin(IDB_RULER_BLOCK, IDB_RULER_UP, m_indent), m_indent(IDB_RULER_DOWN), m_rightmargin(IDB_RULER_UP), m_tabItem(IDB_RULER_TAB) { m_bDeferInProgress = FALSE; m_leftmargin.SetRuler(this); m_indent.SetRuler(this); m_rightmargin.SetRuler(this); // all of the tab stops share handles for (int i=0;iGetPaperSize(), pView->GetMargins()); Update(pView->GetParaFormatSelection()); CRect rect; pView->GetRichEditCtrl().GetRect(&rect); CPoint pt = rect.TopLeft(); pView->ClientToScreen(&pt); ScreenToClient(&pt); if (m_cxLeftBorder != pt.x) { m_cxLeftBorder = pt.x; Invalidate(); } int nScroll = pView->GetScrollPos(SB_HORZ); if (nScroll != m_nScroll) { m_nScroll = nScroll; Invalidate(); } } } CSize CRulerBar::GetBaseUnits() { ASSERT(fnt.GetSafeHandle() != NULL); CFont* pFont = theApp.m_dcScreen.SelectObject(&fnt); TEXTMETRIC tm; VERIFY(theApp.m_dcScreen.GetTextMetrics(&tm) == TRUE); theApp.m_dcScreen.SelectObject(pFont); // return CSize(tm.tmAveCharWidth, tm.tmHeight+tm.tmDescent); return CSize(tm.tmAveCharWidth, tm.tmHeight); } BOOL CRulerBar::Create(CWnd* pParentWnd, DWORD dwStyle, UINT nID) { ASSERT_VALID(pParentWnd); // must have a parent dwStyle |= WS_CLIPSIBLINGS; // force WS_CLIPSIBLINGS (avoids SetWindowPos bugs) m_dwStyle = (dwStyle & CBRS_ALL); // create the HWND CRect rect; rect.SetRectEmpty(); LPCTSTR lpszClass = AfxRegisterWndClass(0, ::LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_BTNFACE+1), NULL); if (!CWnd::Create(lpszClass, NULL, dwStyle, rect, pParentWnd, nID)) return FALSE; // NOTE: Parent must resize itself for control bar to be resized int i; int nMax = 100; for (i=0;iSaveDC(); // offset coordinate system CPoint pointOffset(0,0); RulerToClient(pointOffset); pDC->SetViewportOrg(pointOffset); DrawFace(*pDC); DrawTickMarks(*pDC); DrawTabs(*pDC); m_leftmargin.Draw(*pDC); m_indent.Draw(*pDC); m_rightmargin.Draw(*pDC); pDC->RestoreDC(-1); } // Do not call CControlBar::OnPaint() for painting messages } void CRulerBar::DrawTabs(CDC& dc) { int i; int nPos = 0; for (i=0;i nPos) nPos = (m_pTabItems[i].GetHorzPosTwips()); m_pTabItems[i].Draw(dc); } int nPageWidth = PrintWidth(); nPos = nPos - nPos%720 + 720; dc.SelectObject(&penBtnShadow); for ( ; nPos < nPageWidth; nPos += 720) { int nx = XTwipsToRuler(nPos); dc.MoveTo(nx, HEIGHT - 1); dc.LineTo(nx, HEIGHT + 1); } } void CRulerBar::DrawFace(CDC& dc) { int nPageWidth = XTwipsToRuler(PrintWidth()); int nPageEdge = XTwipsToRuler(PrintWidth() + m_rectMargin.right); dc.SaveDC(); dc.SelectObject(&penBtnShadow); dc.MoveTo(0,0); dc.LineTo(nPageEdge - 1, 0); dc.LineTo(nPageEdge - 1, HEIGHT - 2); dc.LineTo(nPageWidth - 1, HEIGHT - 2); dc.LineTo(nPageWidth - 1, 1); dc.LineTo(nPageWidth, 1); dc.LineTo(nPageWidth, HEIGHT -2); dc.SelectObject(&penBtnHighLight); dc.MoveTo(nPageWidth, HEIGHT - 1); dc.LineTo(nPageEdge, HEIGHT -1); dc.MoveTo(nPageWidth + 1, HEIGHT - 3); dc.LineTo(nPageWidth + 1, 1); dc.LineTo(nPageEdge - 1, 1); dc.SelectObject(&penWindow); dc.MoveTo(0, HEIGHT - 1); dc.LineTo(nPageWidth, HEIGHT -1); dc.SelectObject(&penBtnFace); dc.MoveTo(1, HEIGHT - 2); dc.LineTo(nPageWidth - 1, HEIGHT - 2); dc.SelectObject(&penWindowFrame); dc.MoveTo(0, HEIGHT - 2); dc.LineTo(0, 1); dc.LineTo(nPageWidth - 1, 1); dc.FillRect(CRect(1, 2, nPageWidth - 1, HEIGHT-2), &brushWindow); dc.FillRect(CRect(nPageWidth + 2, 2, nPageEdge - 1, HEIGHT-2), &brushBtnFace); CRect rcClient; GetClientRect(&rcClient); ClientToRuler(rcClient); rcClient.top = HEIGHT; rcClient.bottom = HEIGHT + 2; dc.FillRect(rcClient, &brushBtnFace); CRect rectFill(rcClient.left, HEIGHT+4, rcClient.right, HEIGHT+9); dc.FillRect(rectFill, &brushWindow); if (m_bDraw3DExt) // draws the 3D extension into the view { dc.SelectObject(&penBtnShadow); dc.MoveTo(rcClient.left, HEIGHT+8); dc.LineTo(rcClient.left, HEIGHT+2); dc.LineTo(rcClient.right-1, HEIGHT+2); dc.SelectObject(&penWindowFrame); dc.MoveTo(rcClient.left+1, HEIGHT+8); dc.LineTo(rcClient.left+1, HEIGHT+3); dc.LineTo(rcClient.right-2, HEIGHT+3); dc.SelectObject(&penBtnHighLight); dc.MoveTo(rcClient.right-1, HEIGHT+2); dc.LineTo(rcClient.right-1, HEIGHT+8); dc.SelectObject(&penBtnFace); dc.MoveTo(rcClient.right-2, HEIGHT+3); dc.LineTo(rcClient.right-2, HEIGHT+8); } else { dc.SelectObject(&penBtnShadow); dc.MoveTo(rcClient.left, HEIGHT+2); dc.LineTo(rcClient.right, HEIGHT+2); dc.SelectObject(&penWindowFrame); dc.MoveTo(rcClient.left, HEIGHT+3); dc.LineTo(rcClient.right, HEIGHT+3); } dc.RestoreDC(-1); } void CRulerBar::DrawTickMarks(CDC& dc) { dc.SaveDC(); dc.SelectObject(&penWindowText); dc.SelectObject(&fnt); dc.SetTextColor(GetSysColor(COLOR_WINDOWTEXT)); dc.SetBkMode(TRANSPARENT); DrawDiv(dc, m_unit.m_nSmallDiv, m_unit.m_nLargeDiv, 2); DrawDiv(dc, m_unit.m_nMediumDiv, m_unit.m_nLargeDiv, 5); DrawNumbers(dc, m_unit.m_nLargeDiv, m_unit.m_nTPU); dc.RestoreDC(-1); } void CRulerBar::DrawNumbers(CDC& dc, int nInc, int nTPU) { int nPageWidth = PrintWidth(); int nPageEdge = nPageWidth + m_rectMargin.right; TCHAR buf[10]; int nTwips, nPixel, nLen; for (nTwips = nInc; nTwips < nPageEdge; nTwips += nInc) { if (nTwips == nPageWidth) continue; nPixel = XTwipsToRuler(nTwips); wsprintf(buf, _T("%d"), nTwips/nTPU); nLen = lstrlen(buf); CSize sz = dc.GetTextExtent(buf, nLen); dc.ExtTextOut(nPixel - sz.cx/2, HEIGHT/2 - sz.cy/2, 0, NULL, buf, nLen, NULL); } } void CRulerBar::DrawDiv(CDC& dc, int nInc, int nLargeDiv, int nLength) { int nPageWidth = PrintWidth(); int nPageEdge = nPageWidth + m_rectMargin.right; int nTwips, nPixel; for (nTwips = nInc; nTwips < nPageEdge; nTwips += nInc) { if (nTwips == nPageWidth || nTwips%nLargeDiv == 0) continue; nPixel = XTwipsToRuler(nTwips); dc.MoveTo(nPixel, HEIGHT/2 - nLength/2); dc.LineTo(nPixel, HEIGHT/2 - nLength/2 + nLength); } } void CRulerBar::OnLButtonDown(UINT nFlags, CPoint point) { CPoint pt = point; ClientToRuler(pt); m_pSelItem = NULL; if (m_leftmargin.HitTestPix(pt)) m_pSelItem = &m_leftmargin; else if (m_indent.HitTestPix(pt)) m_pSelItem = &m_indent; else if (m_rightmargin.HitTestPix(pt)) m_pSelItem = &m_rightmargin; else m_pSelItem = GetHitTabPix(pt); if (m_pSelItem == NULL) m_pSelItem = GetFreeTab(); if (m_pSelItem == NULL) return; SetCapture(); m_pSelItem->SetTrack(TRUE); SetMarginBounds(); OnMouseMove(nFlags, point); } void CRulerBar::SetMarginBounds() { m_leftmargin.SetBounds(0, m_rightmargin.GetHorzPosTwips()); m_indent.SetBounds(0, m_rightmargin.GetHorzPosTwips()); int nMin = (m_leftmargin.GetHorzPosTwips() > m_indent.GetHorzPosTwips()) ? m_leftmargin.GetHorzPosTwips() : m_indent.GetHorzPosTwips(); int nMax = PrintWidth() + m_rectMargin.right; m_rightmargin.SetBounds(nMin, nMax); // tabs can go from zero to the right page edge for (int i=0;iSetTrack(FALSE); ReleaseCapture(); CWordPadView* pView = (CWordPadView*)GetView(); ASSERT(pView != NULL); PARAFORMAT& pf = pView->GetParaFormatSelection(); FillInParaFormat(pf); pView->SetParaFormat(pf); m_pSelItem = NULL; } void CRulerBar::OnMouseMove(UINT nFlags, CPoint point) { CControlBar::OnMouseMove(nFlags, point); // use ::GetCapture to avoid creating temporaries if (::GetCapture() != m_hWnd) return; ASSERT(m_pSelItem != NULL); CRect rc(0,0, XTwipsToRuler(PrintWidth() + m_rectMargin.right), HEIGHT); RulerToClient(rc); BOOL bOnRuler = rc.PtInRect(point); // snap to minimum movement point.x = XClientToTwips(point.x); point.x += m_unit.m_nMinMove/2; point.x -= point.x%m_unit.m_nMinMove; m_pSelItem->TrackHorzPosTwips(point.x, bOnRuler); UpdateWindow(); } void CRulerBar::OnSysColorChange() { CControlBar::OnSysColorChange(); CreateGDIObjects(); Invalidate(); } void CRulerBar::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos) { CControlBar::OnWindowPosChanging(lpwndpos); CRect rect; GetClientRect(rect); int minx = min(rect.Width(), lpwndpos->cx); int maxx = max(rect.Width(), lpwndpos->cx); rect.SetRect(minx-2, rect.bottom - 6, minx, rect.bottom); InvalidateRect(rect); rect.SetRect(maxx-2, rect.bottom - 6, maxx, rect.bottom); InvalidateRect(rect); } void CRulerBar::OnShowWindow(BOOL bShow, UINT nStatus) { CControlBar::OnShowWindow(bShow, nStatus); m_bDeferInProgress = FALSE; } void CRulerBar::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos) { CControlBar::OnWindowPosChanged(lpwndpos); m_bDeferInProgress = FALSE; } LRESULT CRulerBar::OnSizeParent(WPARAM wParam, LPARAM lParam) { BOOL bVis = GetStyle() & WS_VISIBLE; if ((bVis && (m_nStateFlags & delayHide)) || (!bVis && (m_nStateFlags & delayShow))) { m_bDeferInProgress = TRUE; } return CControlBar::OnSizeParent(wParam, lParam); }