⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rowview.cpp

📁 VC++技术内幕(第四版)的实例
💻 CPP
字号:
// rowview.cpp : implementation of the CRowView class (MM_TEXT)
//

#include "stdafx.h"
#include "resource.h"
#include "rowview.h"
#include <limits.h> // for INT_MAX

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

IMPLEMENT_DYNAMIC(CRowView, CScrollView)

/////////////////////////////////////////////////////////////////////////////
// CRowView

BEGIN_MESSAGE_MAP(CRowView, CScrollView)
	//{{AFX_MSG_MAP(CRowView)
	ON_WM_KEYDOWN()
	ON_WM_SIZE()
	ON_WM_LBUTTONDOWN()
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CRowView construction, initialization, and destruction

CRowView::CRowView()
{
	m_nPrevSelectedRow = 0;
}

CRowView::~CRowView()
{
}

/////////////////////////////////////////////////////////////////////////////
// CRowView updating and drawing

void CRowView::OnInitialUpdate()
{
	m_nPrevRowCount = GetRowCount();
	m_nPrevSelectedRow = GetActiveRow();
	OnUpdate(this, 0, NULL);
}

/////////////////////////////////////////////////////////////////////////////
void CRowView::UpdateRow(int nInvalidRow)
{
	TRACE("UpdateRow %d\n", nInvalidRow);
	int nRowCount = GetRowCount();
	// If the number of rows has changed, then adjust the scrolling range.
	if (nRowCount != m_nPrevRowCount) {
		UpdateScrollSizes();
		m_nPrevRowCount = nRowCount;
	}

	// When the currently selected row changes:
	// scroll the view so that the newly selected row is visible, and
	// ask the derived class to repaint the selected and previously
	// selected rows.

	CClientDC dc(this);
	OnPrepareDC(&dc);

	// Determine the range of the rows that are currently fully visible
	// in the window.  We want to do discrete scrolling by so that
	// the next or previous row is always fully visible.
	int nFirstRow, nLastRow;
	CRect rectClient;
	GetClientRect(&rectClient);
	dc.DPtoLP(&rectClient);
	RectLPtoRowRange(rectClient, nFirstRow, nLastRow, FALSE);

	// If necessary, scroll the window so the newly selected row is
	// visible.
	POINT pt = GetDeviceScrollPosition();
	BOOL bNeedToScroll = TRUE;
	if (nInvalidRow < nFirstRow) {
		// The newly selected row is above those currently visible
		// in the window.  Scroll so the newly selected row is at the
		// very top of the window.  The last row in the window might
		// be only partially visible.
		pt.y = RowToYPos(nInvalidRow);
	}
	else if (nInvalidRow > nLastRow){
		// The newly selected row is below those currently visible
		// in the window.  Scroll so the newly selected row is at the
		// very bottom of the window.  The first row in the window might
		// be only partially visible.
		pt.y = max(0, RowToYPos(nInvalidRow+1) - rectClient.Height());
	}
	else {
		bNeedToScroll = FALSE;
	}
	if (bNeedToScroll) {
		ScrollToDevicePosition(pt);
		// Scrolling will cause the newly selected row to be
		// redrawn in the invalidated area of the window.

		OnPrepareDC(&dc);  // Need to prepare the DC again because
			// ScrollToDevicePosition() will have changed the viewport
			// origin.  The DC is used some more below.
	}

	CRect rectInvalid = RowToWndRect(&dc, nInvalidRow);
	InvalidateRect(&rectInvalid);

	// Give the derived class an opportunity to repaint the
	// previously selected row, perhaps to un-highlight it.

	int nSelectedRow = GetActiveRow();
	if (m_nPrevSelectedRow != nSelectedRow)	{
		CRect rectOldSelection = RowToWndRect(&dc, m_nPrevSelectedRow);
		InvalidateRect(&rectOldSelection);
		m_nPrevSelectedRow = nSelectedRow;
	}
}

/////////////////////////////////////////////////////////////////////////////
void CRowView::UpdateScrollSizes()
{
	// UpdateScrollSizes() is called when it is necessary to adjust the
	// scrolling range or page/line sizes.  There are two occassions
	// where this is necessary:  (1) when a new row is added-- see
	// UpdateRow()-- and (2) when the window size changes-- see OnSize().

	CRect rectClient;
	GetClientRect(&rectClient);

	CClientDC dc(this);
	CalculateRowMetrics(&dc);

	// The vert scrolling range is the total display height of all
	// of the rows.
	CSize sizeTotal(m_nRowWidth, 
		m_nRowHeight * (min(GetRowCount(), LastViewableRow())));

	// The vertical per-page scrolling distance is equal to the
	// how many rows can be displayed in the current window, less
	// one row for paging overlap.
	CSize sizePage(m_nRowWidth / 5, max(m_nRowHeight,
				((rectClient.bottom / m_nRowHeight) - 1) * m_nRowHeight));

	// The vertical per-line scrolling distance is equal to the
		// height of the row.
	CSize sizeLine(m_nRowWidth / 20, m_nRowHeight);

	SetScrollSizes(MM_TEXT, sizeTotal, sizePage, sizeLine);
}


/////////////////////////////////////////////////////////////////////////////
void CRowView::OnDraw(CDC* pDC)
{
	if (GetRowCount() == 0) {
		return;
	}
	// The window has been invalidated and needs to be repainted;
	// or a page needs to be printed (or previewed).
	// First, determine the range of rows that need to be displayed or
	// printed.

	int nFirstRow, nLastRow;
	CRect rectClip;
	pDC->GetClipBox(&rectClip);	// Get the invalidated region.
	RectLPtoRowRange(rectClip, nFirstRow, nLastRow, TRUE);

	// Draw each row in the invalidated region of the window,
	// or on the printed (previewed) page.
	int nActiveRow = GetActiveRow();
	int nRow, y;
	int nLastViewableRow = LastViewableRow();
	for (nRow = nFirstRow,	y = m_nRowHeight * nFirstRow;
			nRow <= nLastRow; nRow++, y += m_nRowHeight) {
		if (nRow >= (nLastViewableRow - 1)) {
			CString strWarning;
			strWarning.LoadString(IDS_TOO_MANY_ROWS);
			pDC->TextOut(0, y, strWarning);
			break;
		}
		// Prepare for highlighting or un-highlighting the check, depending
		// on whether it is the currently selected check or not.  And
		// paint the background (behind the text) accordingly.
		CBrush brushBackground;
		COLORREF crOldText, crOldBackground;
   		if (!pDC->IsPrinting()) {
			if (nRow == nActiveRow)	{
				brushBackground.CreateSolidBrush(::GetSysColor(COLOR_HIGHLIGHT));
				crOldBackground = pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
				crOldText = pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
			}
			else {
				brushBackground.CreateSolidBrush(::GetSysColor(COLOR_WINDOW));
			}

			CRect rectSelection;
			pDC->GetClipBox(&rectSelection);
			rectSelection.top = y;
			rectSelection.bottom = y + m_nRowHeight;
			pDC->FillRect(&rectSelection, &brushBackground);
		}
		OnDrawRow(pDC, nRow, y, nRow == nActiveRow);
		// Restore the DC. (MOVED FROM DERIVED CLASS)
		if (!pDC->IsPrinting() && (nRow == nActiveRow))	{
			pDC->SetBkColor(crOldBackground);
			pDC->SetTextColor(crOldText);
		}
	}
}

/////////////////////////////////////////////////////////////////////////////
// Implementation

int CRowView::RowToYPos(int nRow)
{
	return (nRow * m_nRowHeight);
}

/////////////////////////////////////////////////////////////////////////////
CRect CRowView::RowToWndRect(CDC* pDC, int nRow)
{
	CRect clientRect;
	GetClientRect(clientRect);
	pDC->DPtoLP(clientRect);
	CRect rect(clientRect.left, nRow * m_nRowHeight,
			clientRect.right, (nRow + 1) * m_nRowHeight);
	pDC->LPtoDP(&rect);
	TRACE("	RowToWndRect - top = %d, bottom = %d, row = %d\n",
		rect.top, rect.bottom, nRow);
	return rect;
}

/////////////////////////////////////////////////////////////////////////////
int CRowView::LastViewableRow()
{
	return (INT_MAX / m_nRowHeight - 1);
}

/////////////////////////////////////////////////////////////////////////////
void CRowView::RectLPtoRowRange(const CRect& rect,
			int& nFirstRow,	int& nLastRow,
			BOOL bIncludePartiallyShownRows)
{
	int nRounding = bIncludePartiallyShownRows ? 0 : (m_nRowHeight - 1);
	nFirstRow = (rect.top + nRounding) / m_nRowHeight;
	nLastRow = min( (rect.bottom - nRounding) / m_nRowHeight,
		GetRowCount() - 1);
	TRACE("RectLPtoRowRange - top = %d, bottom = %d, first = %d, last = %d\n",
		rect.top, rect.bottom, nFirstRow, nLastRow);
}

/////////////////////////////////////////////////////////////////////////////
void CRowView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
	// The size of text that is displayed, printed or previewed changes
	// depending on the DC.  We explicitly call OnPrepareDC() to prepare
	// CClientDC objects used for calculating text positions and to
	// prepare the text metric member variables of the CRowView object.
	// The framework also calls OnPrepareDC() before passing the DC to
	// OnDraw().

	CScrollView::OnPrepareDC(pDC, pInfo);
	CalculateRowMetrics(pDC);
}

/////////////////////////////////////////////////////////////////////////////
// Overrides of CView for implementing printing.

BOOL CRowView::OnPreparePrinting(CPrintInfo* pInfo)
{
	return DoPreparePrinting(pInfo);
}

/////////////////////////////////////////////////////////////////////////////
void CRowView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
{
	// OnBeginPrinting() is called after the user has committed to
	// printing by OK'ing the Print dialog, and after the framework
	// has created a CDC object for the printer or the preview view.

	// This is the right opportunity to set up the page range.
	// Given the CDC object, we can determine how many rows will
	// fit on a page, so we can in turn determine how many printed
	// pages represent the entire document.

	int nPageHeight = pDC->GetDeviceCaps(VERTRES);
	CalculateRowMetrics(pDC);
	m_nRowsPerPrintedPage = nPageHeight / m_nRowHeight;
	int nPrintableRowCount = LastViewableRow() + 1;
	if (GetRowCount() < nPrintableRowCount) {
		nPrintableRowCount = GetRowCount();
	}
	pInfo->SetMaxPage((nPrintableRowCount + m_nRowsPerPrintedPage - 1)
		/ m_nRowsPerPrintedPage);
	pInfo->m_nCurPage = 1;	// start previewing at page# 1
}

/////////////////////////////////////////////////////////////////////////////
void CRowView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
	// Print the rows for the current page.

	int yTopOfPage = (pInfo->m_nCurPage -1) * m_nRowsPerPrintedPage
		* m_nRowHeight;

	// Orient the viewport so that the first row to be printed
	// has a viewport coordinate of (0,0).
	pDC->SetViewportOrg(0, -yTopOfPage);

	// Draw as many rows as will fit on the printed page.
	// Clip the printed page so that there is no partially shown
	// row at the bottom of the page (the same row which will be fully
	// shown at the top of the next page).

	int nPageWidth = pDC->GetDeviceCaps(HORZRES);
	CRect rectClip = CRect(0, yTopOfPage, nPageWidth, 
		 yTopOfPage + m_nRowsPerPrintedPage * m_nRowHeight);
	pDC->IntersectClipRect(&rectClip);
	OnDraw(pDC);
}

/////////////////////////////////////////////////////////////////////////////
// CRowView commands


void CRowView::OnSize(UINT nType, int cx, int cy)
{
	UpdateScrollSizes();
	CScrollView::OnSize(nType, cx, cy);
}

/////////////////////////////////////////////////////////////////////////////
void CRowView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
//	int nMin, nMax, nPos;
	CRect clientRect;

	GetClientRect(clientRect);
	CClientDC dc(this);
	dc.DPtoLP(clientRect);
	
	switch (nChar)
	{
		case VK_HOME:
			ChangeSelectionToRow(0);
			break;
		case VK_END:
			ChangeSelectionToRow(min(GetRowCount() - 1,
					LastViewableRow() - 2));
			break;
		case VK_UP:
			ChangeSelectionNextRow(FALSE);
			break;
		case VK_DOWN:
			ChangeSelectionNextRow(TRUE);
			break;
		case VK_LEFT:
			if(clientRect.Width() < GetTotalSize().cx) {
				OnScroll(SB_HORZ, SB_LINEUP, 0);
			}
			break;
		case VK_RIGHT:
			if(clientRect.Width() < GetTotalSize().cx) {
				OnScroll(SB_HORZ, SB_LINEDOWN, 0);
			}
			break;
		case VK_PRIOR:
			if(clientRect.Height() < GetTotalSize().cy) {
				OnScroll(SB_VERT, SB_PAGEUP, 0);
			}
			break;
		case VK_NEXT:
			if(clientRect.Height() < GetTotalSize().cy) {
				OnScroll(SB_VERT, SB_PAGEDOWN, 0);
			}
			break;
        default:
			CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);
	}
}

/////////////////////////////////////////////////////////////////////////////
void CRowView::OnLButtonDown(UINT, CPoint point)
{
	CClientDC dc(this);
	OnPrepareDC(&dc);
	dc.DPtoLP(&point);
	CRect rect(point, CSize(1,1));
	int nFirstRow, nLastRow;
	RectLPtoRowRange(rect, nFirstRow, nLastRow, TRUE);
	if (nFirstRow <= (GetRowCount() - 1)) {
		ChangeSelectionToRow(nFirstRow);
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -