📄 syneditview.cpp
字号:
CPoint p1, p2;
CRichEditCtrl &SynCtrl = GetRichEditCtrl();
SynCtrl.SetWindowText(_T("8"));
p1 = SynCtrl.GetCharPos(0);
p2 = SynCtrl.GetCharPos(1);
m_nCharNumberWidth = p2.x - p1.x; //数字宽度
SynCtrl.SetWindowText(_T(" "));
p1 = SynCtrl.GetCharPos(0);
p2 = SynCtrl.GetCharPos(1);
m_nCharSpaceWidth = p2.x - p1.x; //空格宽度
SynCtrl.SetWindowText(_T("\t"));
p1 = SynCtrl.GetCharPos(0);
p2 = SynCtrl.GetCharPos(1);
m_nCharTabWidth = p2.x - p1.x; //TAB宽度
SynCtrl.SetWindowText(_T("\n "));
CPoint ps, pe;
p1 = SynCtrl.GetCharPos(0);
p2 = SynCtrl.GetCharPos(3);
//m_nLineHeight = p2.y - p1.y; //行高
m_nLineHeight = 16;
ShowWindow(TRUE);
}
LRESULT CSynEditView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
{
CPaintDC dc(this); // device context for painting
DrawSynEditView();
return FALSE;
}
case WM_PASTE:
{
//处理粘贴的情况,当用户粘入rtf格式时,只取出其中的文本,否则直接粘可能会引起文本错位
char * buffer;
if(!OpenClipboard())
return FALSE;
buffer = (char*)::GetClipboardData(CF_TEXT);
CloseClipboard();
CString str = buffer;
CRichEditCtrl &edit = GetRichEditCtrl();
CHARRANGE cr;
edit.GetSel(cr);
SetParseCookieZeroFromGivenLine(edit.LineFromChar(cr.cpMin)); //粘贴时需重置解析缓冲区
edit.ReplaceSel(str, TRUE);
return FALSE;
}
case WM_SIZE:
{
CRichEditView::WindowProc(message, wParam, lParam);
GetParent()->GetClientRect(&m_rcClient);
MoveWindow(&m_rcClient);
if (m_pCacheBitmap != NULL)
{
delete m_pCacheBitmap;
m_pCacheBitmap = NULL;
}
return FALSE;
}
default:
return CRichEditView::WindowProc(message, wParam, lParam);
}
}
void CSynEditView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
InvalidateRect(m_rcClient, FALSE);
m_bAllowDraw = FALSE;
CRichEditView::OnHScroll(nSBCode, nPos, pScrollBar);
m_bAllowDraw = TRUE;
ValidateRect(m_rcClient);
//判断用户是否正在拖动水平滚动条
SCROLLINFO si;
si.cbSize = sizeof(si);
GetScrollInfo(SB_HORZ, &si);
if(nSBCode==SB_THUMBPOSITION || nSBCode==SB_THUMBTRACK)
m_bTracking = TRUE;
else
m_bTracking = FALSE;
SendMessage(WM_PAINT, 0, 0);
}
void CSynEditView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
InvalidateRect(m_rcClient, FALSE);
m_bAllowDraw = FALSE;
CRichEditView::OnVScroll(nSBCode, nPos, pScrollBar);
m_bAllowDraw = TRUE;
ValidateRect(m_rcClient);
SendMessage(WM_PAINT, 0, 0);
}
/* dwCookie - 传入前一行的解析结果,如果前一行是多行注释的开始
或者前一行是一软回车时有用
strLine - 被解析的一行字符串
ColorInfo - 解析后的颜色值,指定是关键字、字符串、注释还是正常的字符颜色
nActualItems - strLine被解析后的块数
函数返回解析结果,指示解析后当前行是处于字符串中、注释中、多行注释中还是正常状态
nActualItems - 返回当前行分解的字符串块数
*/
DWORD CSynEditView::ParseLine( DWORD dwCookie,
CString &strLine,
COLORINFO *ColorInfo,
int &nActualItems)
{
int nLength = strLine.GetLength();
if(nLength == 0)
return dwCookie;
int nIdentBegin = -1;
BOOL bRedefineBlock = TRUE;
BOOL bDecIndex = FALSE;
BOOL bIsInTheControlChar = FALSE;
//上一行之变量指示是否在\的控制中, 初始化时必须为FALSE
//控制字符\的含义:参考下列语句:
//CString strTemp = _T("\"");
//第二个引号并不表示字符串变量的结束,而是表明这是在定义"这个字符串,
//这是因为它的前面有控制字符\,第三个引号才表示定义字符串变量的结束。
for (int I = 0; ; I++)
{
if (bRedefineBlock) //如果开始定义颜色块则向下做
{
int nPos = I;
if (bDecIndex)
nPos--;
if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
{
DEFINE_BLOCK(nPos, COLORINDEX_COMMENT);
}
else {
if (dwCookie & COOKIE_STRING)
{
DEFINE_BLOCK(nPos, COLORINDEX_STRING);
}
else
{
DEFINE_BLOCK(nPos, COLORINDEX_NORMAL);
}
}
bRedefineBlock = FALSE;
bDecIndex = FALSE;
}
if (I == nLength)
goto Out;
if (dwCookie & COOKIE_COMMENT)
{
DEFINE_BLOCK(I, COLORINDEX_COMMENT);
dwCookie |= COOKIE_COMMENT;
goto Out;
}
if (dwCookie & COOKIE_STRING)
//如果当前正处于字符串变量中,则应检查是否有结束字符串变量的字符串
{
if(I > 0)
{
if(strLine[I-1] != '\\')
{
if(strLine[I] != '\\')
bIsInTheControlChar = FALSE;
else
bIsInTheControlChar = TRUE;
}
else
{
if(strLine[I] == '\\')
{
if(!bIsInTheControlChar)
bIsInTheControlChar = TRUE;
else
bIsInTheControlChar = FALSE;
}
}
}
if(strLine[I]==_T('\"') && !bIsInTheControlChar)
{
dwCookie &= ~COOKIE_STRING;
bRedefineBlock = TRUE;
}
goto CmpNextChar;
}
if (dwCookie & COOKIE_CHAR)
//如果当前正处于字符变量中,则应检查是否有结束字符变量的字符串
{
if(I > 0) {
if(strLine[I-1] != '\\')
{
if(strLine[I] != '\\')
bIsInTheControlChar = FALSE;
else
bIsInTheControlChar = TRUE;
}
else
{
if(strLine[I] == '\\')
{
if(!bIsInTheControlChar)
bIsInTheControlChar = TRUE;
else
bIsInTheControlChar = FALSE;
}
}
}
if(strLine[I]==_T('\'') && !bIsInTheControlChar)
{
dwCookie &= ~COOKIE_CHAR;
bRedefineBlock = TRUE;
}
goto CmpNextChar;
}
if (dwCookie & COOKIE_EXT_COMMENT)
//如果当前正处于多行注释中,则应检查是否有结束多行注释的字符串
{
if(I >= 1 && strLine[I-1]==_T('*') && strLine[I]==_T('/'))
{
dwCookie &= ~COOKIE_EXT_COMMENT;
bRedefineBlock = TRUE;
}
goto CmpNextChar;
}
if(I >= 1 && strLine[I-1]==_T('/') && strLine[I]==_T('/'))
//处理单行注释
{
DEFINE_BLOCK(I - 1, COLORINDEX_COMMENT);
dwCookie |= COOKIE_COMMENT;
goto Out; //只要发现有单行注释的字符串则退出
}
if( strLine[I]==_T('\"') )
//处理字符串变量
{
DEFINE_BLOCK(I, COLORINDEX_STRING);
dwCookie |= COOKIE_STRING;
goto CmpNextChar;
}
if( strLine[I]==_T('\'') )
//处理字符变量
{
DEFINE_BLOCK(I, COLORINDEX_CHAR);
dwCookie |= COOKIE_CHAR;
goto CmpNextChar;
}
if( I>=1 && strLine[I-1]==_T('/') && strLine[I]==_T('*'))
//处理多行注释
{
DEFINE_BLOCK(I - 1, COLORINDEX_COMMENT);
dwCookie |= COOKIE_EXT_COMMENT;
if ( ++I >= nLength) // 考虑"/*/"的情况
goto Out;
goto CmpNextChar;
}
//C++中,字符串由字母和下划线_组成,我们扩展来包含#以处理类似#if的关键字
if (isalnum(strLine[I]) || strLine[I] == '_' || strLine[I] == '#')
{
if (nIdentBegin == -1)
nIdentBegin = I;
}
else
{
//分解出一个字符串,此时判断是关键字还是数字
if (nIdentBegin >= 0)
{
CString strtmp= strLine.Mid(nIdentBegin, I - nIdentBegin);
if (IsSynWord(strtmp))
{
DEFINE_BLOCK(nIdentBegin, COLORINDEX_SYNTAX);
}
else if (IsNumber(strtmp))
{
DEFINE_BLOCK(nIdentBegin, COLORINDEX_NUMBER);
}
bRedefineBlock = TRUE;
bDecIndex = TRUE;
nIdentBegin = -1;
}
}
CmpNextChar:;
}
Out: //当遇到单行注释时会直接跳到这儿
//处理剩下的字符串
if (nIdentBegin >= 0)
{
CString strtmp = strLine.Mid(nIdentBegin, I - nIdentBegin);
if (IsSynWord(strtmp))
{
DEFINE_BLOCK(nIdentBegin, COLORINDEX_SYNTAX);
}
else if (IsNumber(strtmp))
{
DEFINE_BLOCK(nIdentBegin, COLORINDEX_NUMBER);
}
}
return dwCookie;
}
//判断给定的串是否是数字变量
BOOL CSynEditView::IsNumber(CString &strReadyToTest)
{
int nLength = strReadyToTest.GetLength();
{
if (nLength > 2 && strReadyToTest[0] == _T('0') &&
strReadyToTest[1] == _T('x'))
{
for (int I = 2; I < nLength; I++)
{
if (_istdigit(strReadyToTest[I]) ||(strReadyToTest[I] >= _T('A') &&
strReadyToTest[I] <= _T('F')) ||(strReadyToTest[I] >= _T('a') &&
strReadyToTest[I] <= _T('f')))
continue;
return FALSE;
}
return TRUE;
}
}
if (!_istdigit(strReadyToTest[0]))
return FALSE;
for (int I = 1; I < nLength; I++)
{
if (!_istdigit(strReadyToTest[I]) && strReadyToTest[I] != _T('+') &&
strReadyToTest[I] != _T('-') && strReadyToTest[I] != _T('.') &&
strReadyToTest[I] != _T('e') && strReadyToTest[I] != _T('E'))
return FALSE;
}
return TRUE;
}
void CSynEditView::SetSynEditViewMargin(int nLeftMargin, int nTopMargin)
{
m_nLeftMargin = nLeftMargin;
m_nTopMargin = nTopMargin;
GetClientRect(&m_rcClient);
CRect rect(m_rcClient);
rect.left = m_nLeftMargin;
rect.top = m_nTopMargin;
GetRichEditCtrl().SetRect(&rect);
}
DWORD CALLBACK CSynEditView::EditStreamCallbackReadFromFile(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
CFile* pFile = (CFile*) dwCookie;
ASSERT_KINDOF(CFile, pFile);
*pcb = pFile->Read(pbBuff, cb);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -