📄 ccrystaltextview.cpp
字号:
LPCTSTR pszChars = GetLineChars(nLine);
CString line;
ExpandChars(pszChars, 0, nLineLength, line);
y += pdc->DrawText(line, &rcPrintRect, DT_LEFT | DT_NOPREFIX | DT_TOP | DT_WORDBREAK);
}
}
/////////////////////////////////////////////////////////////////////////////
// CCrystalTextView message handlers
int CCrystalTextView::GetLineCount()
{
if (m_pTextBuffer == NULL)
return 1; // Single empty line
int nLineCount = m_pTextBuffer->GetLineCount();
ASSERT(nLineCount > 0);
return nLineCount;
}
int CCrystalTextView::GetLineLength(int nLineIndex)
{
if (m_pTextBuffer == NULL)
return 0;
return m_pTextBuffer->GetLineLength(nLineIndex);
}
LPCTSTR CCrystalTextView::GetLineChars(int nLineIndex)
{
if (m_pTextBuffer == NULL)
return NULL;
return m_pTextBuffer->GetLineChars(nLineIndex);
}
void CCrystalTextView::AttachToBuffer(CCrystalTextBuffer *pBuf /*= NULL*/)
{
if (m_pTextBuffer != NULL)
m_pTextBuffer->RemoveView(this);
if (pBuf == NULL)
{
pBuf = LocateTextBuffer();
// ...
}
m_pTextBuffer = pBuf;
if (m_pTextBuffer != NULL)
m_pTextBuffer->AddView(this);
ResetView();
// Init scrollbars
CScrollBar *pVertScrollBarCtrl = GetScrollBarCtrl(SB_VERT);
if (pVertScrollBarCtrl != NULL)
pVertScrollBarCtrl->EnableScrollBar(GetScreenLines() >= GetLineCount() ?
ESB_DISABLE_BOTH : ESB_ENABLE_BOTH);
CScrollBar *pHorzScrollBarCtrl = GetScrollBarCtrl(SB_HORZ);
if (pHorzScrollBarCtrl != NULL)
pHorzScrollBarCtrl->EnableScrollBar(GetScreenChars() >= GetMaxLineLength() ?
ESB_DISABLE_BOTH : ESB_ENABLE_BOTH);
// Update scrollbars
RecalcVertScrollBar();
RecalcHorzScrollBar();
}
void CCrystalTextView::DetachFromBuffer()
{
if (m_pTextBuffer != NULL)
{
m_pTextBuffer->RemoveView(this);
m_pTextBuffer = NULL;
ResetView();
}
}
int CCrystalTextView::GetScreenLines()
{
if (m_nScreenLines == -1)
{
CRect rect;
GetClientRect(&rect);
m_nScreenLines = rect.Height() / GetLineHeight();
}
return m_nScreenLines;
}
BOOL CCrystalTextView::GetItalic(int nColorIndex)
{
return FALSE;
}
BOOL CCrystalTextView::GetBold(int nColorIndex)
{
// if (nColorIndex == COLORINDEX_KEYWORD)
// return true;
return FALSE;
}
int CCrystalTextView::GetScreenChars()
{
if (m_nScreenChars == -1)
{
CRect rect;
GetClientRect(&rect);
m_nScreenChars = (rect.Width() - GetMarginWidth()) / GetCharWidth();
}
return m_nScreenChars;
}
void CCrystalTextView::OnDestroy()
{
DetachFromBuffer();
m_hAccel = NULL;
CView::OnDestroy();
for (int I = 0; I < 4; I ++)
{
if (m_apFonts[I] != NULL)
{
m_apFonts[I]->DeleteObject();
delete m_apFonts[I];
m_apFonts[I] = NULL;
}
}
if (m_pCacheBitmap != NULL)
{
delete m_pCacheBitmap;
m_pCacheBitmap = NULL;
}
}
BOOL CCrystalTextView::OnEraseBkgnd(CDC *pdc)
{
return TRUE;
}
void CCrystalTextView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
if (m_pCacheBitmap != NULL)
{
m_pCacheBitmap->DeleteObject();
delete m_pCacheBitmap;
m_pCacheBitmap = NULL;
}
m_nScreenLines = -1;
m_nScreenChars = -1;
RecalcVertScrollBar();
RecalcHorzScrollBar();
}
void CCrystalTextView::UpdateSiblingScrollPos(BOOL bHorz)
{
CSplitterWnd *pSplitterWnd = GetParentSplitter(this, FALSE);
if (pSplitterWnd != NULL)
{
// See CSplitterWnd::IdFromRowCol() implementation for details
int nCurrentRow = (GetDlgCtrlID() - AFX_IDW_PANE_FIRST) / 16;
int nCurrentCol = (GetDlgCtrlID() - AFX_IDW_PANE_FIRST) % 16;
ASSERT(nCurrentRow >= 0 && nCurrentRow < pSplitterWnd->GetRowCount());
ASSERT(nCurrentCol >= 0 && nCurrentCol < pSplitterWnd->GetColumnCount());
if (bHorz)
{
int nCols = pSplitterWnd->GetColumnCount();
for (int nCol = 0; nCol < nCols; nCol ++)
{
if (nCol != nCurrentCol) // We don't need to update ourselves
{
CCrystalTextView *pSiblingView = GetSiblingView(nCurrentRow, nCol);
if (pSiblingView != NULL)
pSiblingView->OnUpdateSibling(this, TRUE);
}
}
}
else
{
int nRows = pSplitterWnd->GetRowCount();
for (int nRow = 0; nRow < nRows; nRow ++)
{
if (nRow != nCurrentRow) // We don't need to update ourselves
{
CCrystalTextView *pSiblingView = GetSiblingView(nRow, nCurrentCol);
if (pSiblingView != NULL)
pSiblingView->OnUpdateSibling(this, FALSE);
}
}
}
}
}
void CCrystalTextView::OnUpdateSibling(CCrystalTextView *pUpdateSource, BOOL bHorz)
{
if (pUpdateSource != this)
{
ASSERT(pUpdateSource != NULL);
ASSERT_KINDOF(CCrystalTextView, pUpdateSource);
if (bHorz)
{
ASSERT(pUpdateSource->m_nTopLine >= 0);
ASSERT(pUpdateSource->m_nTopLine < GetLineCount());
if (pUpdateSource->m_nTopLine != m_nTopLine)
{
ScrollToLine(pUpdateSource->m_nTopLine, TRUE, FALSE);
UpdateCaret();
}
}
else
{
ASSERT(pUpdateSource->m_nOffsetChar >= 0);
ASSERT(pUpdateSource->m_nOffsetChar < GetMaxLineLength());
if (pUpdateSource->m_nOffsetChar != m_nOffsetChar)
{
ScrollToChar(pUpdateSource->m_nOffsetChar, TRUE, FALSE);
UpdateCaret();
}
}
}
}
void CCrystalTextView::RecalcVertScrollBar(BOOL bPositionOnly /*= FALSE*/)
{
SCROLLINFO si;
si.cbSize = sizeof(si);
if (bPositionOnly)
{
si.fMask = SIF_POS;
// si.nPos = m_nTopLine;
// MiK
si.nPos = CalcVisibleLines(0, m_nTopLine);
}
else
{
int nVisLines= CalcVisibleLines();
if (GetScreenLines() >= nVisLines /*MiK GetLineCount()*/ && m_nTopLine > 0)
{
m_nTopLine = 0;
Invalidate();
UpdateCaret();
}
si.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_POS | SIF_RANGE;
si.nMin = 0;
si.nMax = nVisLines - 1;
si.nPage = GetScreenLines();
si.nPos = CalcVisibleLines(0, m_nTopLine);
}
VERIFY(SetScrollInfo(SB_VERT, &si));
}
void CCrystalTextView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
CView::OnVScroll(nSBCode, nPos, pScrollBar);
// Note we cannot use nPos because of its 16-bit nature
SCROLLINFO si;
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
VERIFY(GetScrollInfo(SB_VERT, &si));
int nPageLines = GetScreenLines();
int nLineCount = GetLineCount();
int nNewTopLine= 0;
bool bSmoothScrolling= false;
switch (nSBCode)
{
case SB_TOP:
nNewTopLine = 0;
break;
case SB_BOTTOM:
nNewTopLine = FindVisibleLine(nLineCount - 1, -nPageLines + 1); //nLineCount - nPageLines + 1;
break;
case SB_LINEUP:
nNewTopLine = FindVisibleLine(m_nTopLine, -1);
break;
case SB_LINEDOWN:
nNewTopLine = FindVisibleLine(m_nTopLine, 1);
break;
case SB_PAGEUP:
nNewTopLine = FindVisibleLine(m_nTopLine, -si.nPage + 1);
break;
case SB_PAGEDOWN:
nNewTopLine = FindVisibleLine(m_nTopLine, si.nPage - 1);
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
nNewTopLine = FindVisibleLine(0, si.nTrackPos);
break;
case 98: // MiK: mouse wheel
nNewTopLine = FindVisibleLine(m_nTopLine, -3);
bSmoothScrolling = true;
break;
case 99:
nNewTopLine = FindVisibleLine(m_nTopLine, 3);
bSmoothScrolling = true;
break;
default:
return;
}
if (nNewTopLine < 0)
nNewTopLine = 0;
if (nNewTopLine >= nLineCount)
nNewTopLine = nLineCount - 1;
ScrollToLine(nNewTopLine, !bSmoothScrolling);
}
void CCrystalTextView::RecalcHorzScrollBar(BOOL bPositionOnly /*= FALSE*/)
{
// Again, we cannot use nPos because it's 16-bit
SCROLLINFO si;
si.cbSize = sizeof(si);
if (bPositionOnly)
{
si.fMask = SIF_POS;
si.nPos = m_nOffsetChar;
}
else
{
if (GetScreenChars() >= GetMaxLineLength() && m_nOffsetChar > 0)
{
m_nOffsetChar = 0;
Invalidate();
UpdateCaret();
}
si.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_POS | SIF_RANGE;
si.nMin = 0;
si.nMax = GetMaxLineLength() - 1;
si.nPage = GetScreenChars();
si.nPos = m_nOffsetChar;
}
VERIFY(SetScrollInfo(SB_HORZ, &si));
}
void CCrystalTextView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
CView::OnHScroll(nSBCode, nPos, pScrollBar);
SCROLLINFO si;
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
VERIFY(GetScrollInfo(SB_HORZ, &si));
int nPageChars = GetScreenChars();
int nMaxLineLength = GetMaxLineLength();
int nNewOffset;
switch (nSBCode)
{
case SB_LEFT:
nNewOffset = 0;
break;
case SB_BOTTOM:
nNewOffset = nMaxLineLength - nPageChars + 1;
break;
case SB_LINEUP:
nNewOffset = m_nOffsetChar - 1;
break;
case SB_LINEDOWN:
nNewOffset = m_nOffsetChar + 1;
break;
case SB_PAGEUP:
nNewOffset = m_nOffsetChar - si.nPage + 1;
break;
case SB_PAGEDOWN:
nNewOffset = m_nOffsetChar + si.nPage - 1;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
nNewOffset = si.nTrackPos;
break;
default:
return;
}
if (nNewOffset >= nMaxLineLength)
nNewOffset = nMaxLineLength - 1;
if (nNewOffset < 0)
nNewOffset = 0;
ScrollToChar(nNewOffset, TRUE);
UpdateCaret();
}
BOOL CCrystalTextView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (nHitTest == HTCLIENT)
{
CPoint pt;
::GetCursorPos(&pt);
ScreenToClient(&pt);
if (pt.x < GetMarginWidth())
{
::SetCursor(::LoadCursor(GetResourceHandle(), MAKEINTRESOURCE(IDR_MARGIN_CURSOR)));
}
else
{
CPoint ptText = ClientToText(pt);
PrepareSelBounds();
if (IsInsideSelBlock(ptText))
{
// [JRT]: Support For Disabling Drag and Drop...
if (!m_bDisableDragAndDrop) // If Drag And Drop Not Disabled
::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW))); // Set To Arrow Cursor
}
else
::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_IBEAM)));
}
return TRUE;
}
return CView::OnSetCursor(pWnd, nHitTest, message);
}
CPoint CCrystalTextView::ClientToText(const CPoint &point)
{
int nLineCount = GetLineCount();
CPoint pt;
pt.y = FindVisibleLine(m_nTopLine, point.y / GetLineHeight());
if (pt.y >= nLineCount)
pt.y = nLineCount - 1;
if (pt.y < 0)
pt.y = 0;
int nLength = 0;
LPCTSTR pszLine = NULL;
if (pt.y >= 0 && pt.y < nLineCount)
{
nLength = GetLineLength(pt.y);
pszLine = GetLineChars(pt.y);
}
int nPos = m_nOffsetChar + (point.x - GetMarginWidth()) / GetCharWidth();
if (nPos < 0)
nPos = 0;
int nIndex = 0, nCurPos = 0;
int nTabSize = GetTabSize();
while (nIndex < nLength)
{
if (pszLine[nIndex] == _T('\t'))
nCurPos += (nTabSize - nCurPos % nTabSize);
else
nCurPos ++;
if (nCurPos > nPos)
break;
nIndex ++;
}
ASSERT(nIndex >= 0 && nIndex <= nLength);
pt.x = nIndex;
return pt;
}
#ifdef _DEBUG
void CCrystalTextView::AssertValidTextPos(const CPoint &point)
{
if (GetLineCount() > 0)
{
ASSERT(m_nTopLine >= 0 && m_nOffsetChar >= 0);
ASSERT(point.y >= 0 && point.y < GetLineCount());
ASSERT(point.x >= 0 && point.x <= GetLineLength(point.y));
}
}
#endif
CPoint CCrystalTextView::TextToClient(const CPoint &point)
{
ASSERT_VALIDTEXTPOS(point);
int nLength = GetLineLength(point.y);
LPCTSTR pszLine = GetLineChars(point.y);
CPoint pt;
pt.y = CalcVisibleLines(m_nTopLine, point.y) * GetLineHeight();
pt.x = 0;
int nTabSize = GetTabSize();
for (int nIndex = 0; nIndex < point.x; nIndex ++)
{
if (pszLine[nIndex] == _T('\t'))
pt.x += (nTabSize - pt.x % nTabSize);
else
pt.x ++;
}
pt.x = (pt.x - m_nOffsetChar) * GetCharWidth() + GetMarginWidth();
return pt;
}
void CCrystalTextView::InvalidateLines(int nLine1, int nLine2, BOOL bInvalidateMargin /*= FALSE*/)
{
bInvalidateMargin = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -