📄 textviewpaint.cpp
字号:
void TextView::PaintText(HDC hdc, ULONG nLineNo, int xpos, int ypos, RECT *bounds)
{
USPDATA * uspData;
ULONG lineOffset;
// grab the USPDATA for this line
uspData = GetUspData(hdc, nLineNo, &lineOffset);
// set highlight-colours depending on window-focus
if(GetFocus() == m_hWnd)
UspSetSelColor(uspData, GetColour(TXC_HIGHLIGHTTEXT), GetColour(TXC_HIGHLIGHT));
else
UspSetSelColor(uspData, GetColour(TXC_HIGHLIGHTTEXT2), GetColour(TXC_HIGHLIGHT2));
// update selection-attribute information for the line
UspApplySelection(uspData, m_nSelectionStart - lineOffset, m_nSelectionEnd - lineOffset);
ApplySelection(uspData, nLineNo, lineOffset, uspData->stringLen);
// draw the text!
UspTextOut(uspData, hdc, xpos, ypos, m_nLineHeight, m_nHeightAbove, bounds);
}
int TextView::ApplySelection(USPDATA *uspData, ULONG nLine, ULONG nOffset, ULONG nTextLen)
{
int selstart = 0;
int selend = 0;
if(m_nSelectionType != SEL_BLOCK)
return 0;
if(nLine >= m_cpBlockStart.line && nLine <= m_cpBlockEnd.line)
{
int trailing;
UspXToOffset(uspData, m_cpBlockStart.xpos, &selstart, &trailing, 0);
selstart += trailing;
UspXToOffset(uspData, m_cpBlockEnd.xpos, &selend, &trailing, 0);
selend += trailing;
if(selstart > selend)
selstart ^= selend ^= selstart^= selend;
}
UspApplySelection(uspData, selend, selstart);
return 0;
}
//
// Apply visual-styles to the text by returning colour and font
// information into the supplied TEXT_ATTR structure
//
// nLineNo - line number
// nOffset - actual offset of line within file
//
// Returns new length of buffer if text has been modified
//
int TextView::ApplyTextAttributes(ULONG nLineNo, ULONG nOffset, ULONG &nColumn, TCHAR *szText, int nTextLen, ATTR *attr)
{
int i;
ULONG selstart = min(m_nSelectionStart, m_nSelectionEnd);
ULONG selend = max(m_nSelectionStart, m_nSelectionEnd);
//
// STEP 1. Apply the "base coat"
//
for(i = 0; i < nTextLen; i++)
{
attr[i].len = 1;
attr[i].font = 0;
attr[i].eol = 0;
attr[i].reserved = 0;
// change the background if the line is too long
if(nColumn >= (ULONG)m_nLongLineLimit && CheckStyle(TXS_LONGLINES))
{
attr[i].fg = GetColour(TXC_FOREGROUND);
attr[i].bg = LongColour(nLineNo);
}
else
{
attr[i].fg = GetColour(TXC_FOREGROUND);
attr[i].bg = LineColour(nLineNo);//GetColour(TXC_BACKGROUND);
}
// keep track of how many columns we have processed
if(szText[i] == '\t')
nColumn += m_nTabWidthChars - (nColumn % m_nTabWidthChars);
else
nColumn += 1;
}
//
// TODO: 1. Apply syntax colouring first of all
//
//
// TODO: 2. Apply bookmarks, line highlighting etc (override syntax colouring)
//
//
// STEP 3: Now apply text-selection (overrides everything else)
//
if(m_nSelectionType == SEL_NORMAL)
{
for(i = 0; i < nTextLen; i++)
{
// highlight uses a separate attribute-flag
if(nOffset + i >= selstart && nOffset + i < selend)
attr[i].sel = 1;
else
attr[i].sel = 0;
}
}
else if(m_nSelectionType == SEL_BLOCK)
{
}
//SyntaxColour(szText, nTextLen, attr);
//
// Turn any CR/LF at the end of a line into a single 'space' character
//
nTextLen = StripCRLF(szText, attr, nTextLen, false);
//
// Finally identify control-characters (after CR/LF has been changed to 'space')
//
for(i = 0; i < nTextLen; i++)
{
ULONG ch = szText[i];
attr[i].ctrl = ch < 0x20 ? 1 : 0;
if(ch == '\r' || ch == '\n')
attr[i].eol=TRUE;
}
return nTextLen;
}
void PaintRect(HDC hdc, int x, int y, int width, int height, COLORREF fill)
{
RECT rect = { x, y, x+width, y+height };
fill = SetBkColor(hdc, fill);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, 0, 0, 0);
SetBkColor(hdc, fill);
}
void PaintRect(HDC hdc, RECT *rect, COLORREF fill)
{
fill = SetBkColor(hdc, fill);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, rect, 0, 0, 0);
SetBkColor(hdc, fill);
}
int TextView::CRLF_size(TCHAR *szText, int nLength)
{
if(nLength >= 2)
{
if(szText[nLength-2] == '\r' && szText[nLength-1] == '\n')
return 2;
}
if(nLength >= 1)
{
if(szText[nLength-1] == '\r' || szText[nLength-1] == '\n' ||
szText[nLength-1] == '\x0b' || szText[nLength-1] == '\x0c' ||
szText[nLength-1] == '\x85' || szText[nLength-1] == 0x2028 ||
szText[nLength-1] == 0x2029)
return 1;
}
return 0;
}
void TextView::MarkCRLF(USPDATA *uspData, TCHAR *szText, int nLength, ATTR *attr)
{
SCRIPT_LOGATTR *logAttr = UspGetLogAttr(uspData);
if(nLength >= 2)
{
if(szText[nLength-2] == '\r' && szText[nLength-1] == '\n')
{
logAttr[nLength-1].fCharStop = 0;
logAttr[nLength-2].fCharStop = 0;
}
}
if(nLength >= 1)
{
if( szText[nLength-1] == '\n' ||
szText[nLength-1] == '\r' ||
szText[nLength-1] == '\x0b' ||
szText[nLength-1] == '\x0c' ||
szText[nLength-1] == 0x0085 ||
szText[nLength-1] == 0x2029 ||
szText[nLength-1] == 0x2028)
{
logAttr[nLength-1].fCharStop = 0;
}
}
}
//
// Strip CR/LF combinations from the end of a line and
// replace with a single space character (for drawing purposes)
//
int TextView::StripCRLF(TCHAR *szText, ATTR *attr, int nLength, bool fAllow)
{
if(nLength >= 2)
{
if(szText[nLength-2] == '\r' && szText[nLength-1] == '\n')
{
attr[nLength-2].eol = TRUE;
if(m_nCRLFMode & TXL_CRLF)
{
// convert CRLF to a single space
szText[nLength-2] = ' ';
return nLength - 1 - (int)fAllow;
}
else
{
return nLength;
}
}
}
if(nLength >= 1)
{
if( szText[nLength-1] == '\x0b' ||
szText[nLength-1] == '\x0c' ||
szText[nLength-1] == 0x0085 ||
szText[nLength-1] == 0x2029 ||
szText[nLength-1] == 0x2028)
{
attr[nLength-1].eol = TRUE;
//szText[nLength-1] = ' ';
return nLength - 0;//(int)fAllow;
}
if(szText[nLength-1] == '\r')
{
attr[nLength-1].eol = TRUE;
if(m_nCRLFMode & TXL_CR)
{
szText[nLength-1] = ' ';
return nLength - (int)fAllow;
}
}
if(szText[nLength-1] == '\n')
{
attr[nLength-1].eol = TRUE;
if(m_nCRLFMode & TXL_LF)
{
szText[nLength-1] = ' ';
return nLength - (int)fAllow;
}
}
}
return nLength;
}
//
//
//
COLORREF TextView::LineColour(ULONG nLineNo)
{
if(m_nCurrentLine == nLineNo && CheckStyle(TXS_HIGHLIGHTCURLINE))
return GetColour(TXC_CURRENTLINE);
else
return GetColour(TXC_BACKGROUND);
}
COLORREF TextView::LongColour(ULONG nLineNo)
{
if(m_nCurrentLine == nLineNo && CheckStyle(TXS_HIGHLIGHTCURLINE))
return GetColour(TXC_CURRENTLINE);
else
return GetColour(TXC_LONGLINE);
}
COLORREF MixRGB(COLORREF rgbCol1, COLORREF rgbCol2)
{
return RGB(
(GetRValue(rgbCol1) + GetRValue(rgbCol2)) / 2,
(GetGValue(rgbCol1) + GetGValue(rgbCol2)) / 2,
(GetBValue(rgbCol1) + GetBValue(rgbCol2)) / 2
);
}
COLORREF RealizeColour(COLORREF col)
{
COLORREF result = col;
if(col & 0x80000000)
result = GetSysColor(col & 0xff);
if(col & 0x40000000)
result = MixRGB(GetSysColor((col & 0xff00) >> 8), result);
if(col & 0x20000000)
result = MixRGB(GetSysColor((col & 0xff00) >> 8), result);
return result;
}
//
// Return an RGB value corresponding to the specified HVC_xxx index
//
// If the RGB value has the top bit set (0x80000000) then it is
// not a real RGB value - instead the low 29bits specify one
// of the GetSysColor COLOR_xxx indices. This allows us to use
// system colours without worrying about colour-scheme changes etc.
//
COLORREF TextView::GetColour(UINT idx)
{
if(idx >= TXC_MAX_COLOURS)
return 0;
return REALIZE_SYSCOL(m_rgbColourList[idx]);
}
COLORREF TextView::SetColour(UINT idx, COLORREF rgbColour)
{
COLORREF rgbOld;
if(idx >= TXC_MAX_COLOURS)
return 0;
rgbOld = m_rgbColourList[idx];
m_rgbColourList[idx] = rgbColour;
ResetLineCache();
return rgbOld;
}
//
// Paint a checkered rectangle, with each alternate
// pixel being assigned a different colour
//
void DrawCheckedRect(HDC hdc, RECT *rect, COLORREF fg, COLORREF bg)
{
static WORD wCheckPat[8] =
{
0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555
};
HBITMAP hbmp;
HBRUSH hbr, hbrold;
COLORREF fgold, bgold;
hbmp = CreateBitmap(8, 8, 1, 1, wCheckPat);
hbr = CreatePatternBrush(hbmp);
SetBrushOrgEx(hdc, rect->left, 0, 0);
hbrold = (HBRUSH)SelectObject(hdc, hbr);
fgold = SetTextColor(hdc, fg);
bgold = SetBkColor(hdc, bg);
PatBlt(hdc, rect->left, rect->top,
rect->right - rect->left,
rect->bottom - rect->top,
PATCOPY);
SetBkColor(hdc, bgold);
SetTextColor(hdc, fgold);
SelectObject(hdc, hbrold);
DeleteObject(hbr);
DeleteObject(hbmp);
}
#include <uxtheme.h>
#include <tmschema.h>
//
// Need to custom-draw the non-client area when using XP/Vista themes,
// otherwise the border looks old-style
//
LONG TextView::OnNcPaint(HRGN hrgnUpdate)
{
HRGN hrgnClip = hrgnUpdate;
if(m_hTheme != 0)
{
HDC hdc = GetWindowDC(m_hWnd);//GetDCEx(m_hWnd, GetWindowDC(m_hWnd);
RECT rc;
RECT rcWindow;
DWORD state = ETS_NORMAL;
if(!IsWindowEnabled(m_hWnd))
state = ETS_DISABLED;
else if(GetFocus() == m_hWnd)
state = ETS_HOT;
else
state = ETS_NORMAL;
GetWindowRect(m_hWnd, &rcWindow);
GetClientRect(m_hWnd, &rc);
ClientToScreen(m_hWnd, (POINT *)&rc.left);
ClientToScreen(m_hWnd, (POINT *)&rc.right);
rc.right = rcWindow.right - (rc.left - rcWindow.left);
rc.bottom = rcWindow.bottom - (rc.top - rcWindow.top);
hrgnClip = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
if(hrgnUpdate != (HRGN)1)
CombineRgn(hrgnClip, hrgnClip, hrgnUpdate, RGN_AND);
OffsetRect(&rc, -rcWindow.left, -rcWindow.top);
ExcludeClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top);
//if (IsThemeBackgroundPartiallyTransparent (hTheme, EP_EDITTEXT, state))
// DrawThemeParentBackground(m_hWnd, hdc, &rcWindow);
DrawThemeBackground(m_hTheme, hdc,
6,
state,
//EP_EDITTEXT,
//state,
//3,0,
&rcWindow, NULL);
ReleaseDC(m_hWnd, hdc);
}
return DefWindowProc(m_hWnd, WM_NCPAINT, (WPARAM)hrgnClip, 0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -