📄 rowview.cpp
字号:
// From MSVC4.2 Sample CHKBOOK
// Modify by JHCC, 1997
// rowview.cpp : implementation of the CRowView class
#include "stdafx.h"
#include "JHHB.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();
}
void CRowView::UpdateRow(int 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.
CRect rectClient;
GetClientRect(&rectClient);
dc.DPtoLP(&rectClient);
int nFirstRow;
int nLastRow;
RectLPtoRowRange(rectClient, nFirstRow, nLastRow, FALSE);
// If necessary, scroll the window so the newly selected row is visible.
POINT pt;
pt.x = 0;
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);
GetRowWidthHeight(&dc, m_nRowWidth, m_nRowHeight);
// 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.
CRect rectClip;
pDC->GetClipBox(&rectClip); // Get the invalidated region.
int nFirstRow;
int nLastRow;
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)
{
CString strWarning = _T("...");
// strWarning.LoadString(IDS_TOO_MANY_ROWS);
pDC->TextOut(0, y, strWarning);
break;
}
OnDrawRow(pDC, nRow, y, nRow == nActiveRow);
}
}
/////////////////////////////////////////////////////////////////////////////
// Implementation
int CRowView::RowToYPos(int nRow)
{
return nRow * m_nRowHeight;
}
CRect CRowView::RowToWndRect(CDC* pDC, int nRow)
{
int nHorzRes = pDC->GetDeviceCaps(HORZRES);;
CRect rect(0, nRow * m_nRowHeight,
nHorzRes, (nRow + 1) * m_nRowHeight);
pDC->LPtoDP(&rect);
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);
}
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);
GetRowWidthHeight(pDC, m_nRowWidth, m_nRowHeight);
}
/////////////////////////////////////////////////////////////////////////////
// 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);
GetRowWidthHeight(pDC, m_nRowWidth, m_nRowHeight);
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)
{
switch (nChar)
{
case VK_HOME:
ChangeSelectionToRow(0);
break;
case VK_END:
ChangeSelectionToRow(GetRowCount() - 1);
break;
case VK_UP:
ChangeSelectionNextRow(FALSE);
break;
case VK_DOWN:
ChangeSelectionNextRow(TRUE);
break;
case VK_PRIOR:
OnVScroll(SB_PAGEUP,
0, // nPos not used for PAGEUP
GetScrollBarCtrl(SB_VERT));
break;
case VK_NEXT:
OnVScroll(SB_PAGEDOWN,
0, // nPos not used for PAGEDOWN
GetScrollBarCtrl(SB_VERT));
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;
int nLastRow;
RectLPtoRowRange(rect, nFirstRow, nLastRow, TRUE);
if (nFirstRow <= (GetRowCount() - 1))
ChangeSelectionToRow(nFirstRow);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -