📄 advrichedit.cpp
字号:
#include "stdafx.h"
#include "AdvRichEdit.h"
#include "resource.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CAdvRichEdit::CAdvRichEdit()
{
SetKeywordColor(RGB(0,0,255), FALSE);
SetNumberColor(RGB(255,0,255), FALSE);
SetCommentColor(RGB(0,128,0),FALSE);
m_bInForcedChange = FALSE;
m_changeType = ctUndo;
m_crOldSel.cpMin = m_crOldSel.cpMax = 0;
}
CAdvRichEdit::~CAdvRichEdit()
{
}
void CAdvRichEdit::Initialize()
{
m_defaultFont.CreateFont(0,0,0,0,
FW_NORMAL,
FALSE,FALSE,FALSE,
GB2312_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH|FF_ROMAN,
"Fixedsys");
this->SetFont(&m_defaultFont);
PARAFORMAT pf;
pf.cbSize = sizeof(PARAFORMAT);
pf.dwMask = PFM_TABSTOPS ;
pf.cTabCount = MAX_TAB_STOPS;
for( int itab = 0 ; itab < pf.cTabCount ; itab++ )
pf.rgxTabs[itab] = (itab + 1) * 1440/5 ;
SetParaFormat( pf );
SetEventMask(ENM_CHANGE | ENM_SELCHANGE | ENM_PROTECTED);
/* 弹出式菜单 */
m_editMenu.LoadMenu(IDR_EDITOR_MENU);
}
#include <fstream.h>
bool CAdvRichEdit::LoadKeyword(LPCTSTR filePath)
{
if(strlen(filePath) == 0)
return false;
ifstream fopen;
fopen.open(filePath);
if(fopen.fail())
return false;
char buffer[32];
while(!fopen.eof())
{
fopen>>buffer;
CString key;
key.Format(" %s ",buffer);
AddKeywords(key);
}
return true;
}
/* 设置注释开端 */
void CAdvRichEdit::AddKeywords(LPCTSTR lpszKwd)
{
m_strKeywords = m_strKeywords + lpszKwd;
m_strKeywordsLower = m_strKeywords;
m_strKeywordsLower.MakeLower();
}
void CAdvRichEdit::ClearKeywords()
{
m_strKeywords.Empty();
m_strKeywordsLower.Empty();
}
void CAdvRichEdit::SetKeywordColor(COLORREF clr, BOOL bBold)
{
m_icKeyword.clrColor = clr;
m_icKeyword.bBold = bBold;
}
void CAdvRichEdit::SetNumberColor(COLORREF clr, BOOL bBold)
{
m_icNumber.clrColor = clr;
m_icNumber.bBold = bBold;
}
void CAdvRichEdit::SetCommentColor(COLORREF clr, BOOL bBold)
{
m_icComment.clrColor = clr;
m_icComment.bBold = bBold;
}
BEGIN_MESSAGE_MAP(CAdvRichEdit, CRichEditCtrl)
//{{AFX_MSG_MAP(CAdvRichEdit)
ON_CONTROL_REFLECT(EN_CHANGE, OnChange)
ON_WM_GETDLGCODE()
ON_WM_CHAR()
ON_WM_CONTEXTMENU()
ON_COMMAND(IDM_EDITOR_UNDO, OnEditorUndo)
ON_COMMAND(IDM_EDITOR_PASTE,OnEditorPaste)
ON_COMMAND(IDM_EDITOR_CUT, OnEditorCut)
ON_COMMAND(IDM_EDITOR_COPY, OnEditorCopy)
ON_WM_HSCROLL()
ON_WM_VSCROLL()
ON_WM_MOUSEWHEEL()
//}}AFX_MSG_MAP
ON_NOTIFY_REFLECT(EN_PROTECTED, OnProtected)
ON_NOTIFY_REFLECT(EN_SELCHANGE, OnSelChange)
ON_MESSAGE(WM_SETTEXT, OnSetText)
END_MESSAGE_MAP()
UINT CAdvRichEdit::OnGetDlgCode()
{
UINT uCode = CRichEditCtrl::OnGetDlgCode();
uCode = DLGC_WANTALLKEYS |
DLGC_WANTARROWS |
DLGC_WANTCHARS |
DLGC_WANTMESSAGE |
DLGC_WANTTAB;
return uCode;
}
void CAdvRichEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (nChar == '\t' && GetKeyState(VK_CONTROL) >= 0)
{
ReplaceSel("\t");
return;
}
CRichEditCtrl::OnChar(nChar, nRepCnt, nFlags);
}
/* 判断关键字函数 */
int CAdvRichEdit::IsKeyword(LPCTSTR lpszSymbol)
{
CString strSymbol;
strSymbol.Format(" %s ", lpszSymbol);
/* 把关键字先转化为最小再比较 */
strSymbol.MakeLower();
return m_strKeywordsLower.Find(strSymbol);
}
/* 修改某个段的字符格式但是不是词法分析哦 */
void CAdvRichEdit::SetFormatRange(int nStart, int nEnd, BOOL bBold, COLORREF clr)
{
if (nStart >= nEnd)
return;
/* richedit有个问题,就是必须对选中的文字设计格式所以要先选中 */
SetSel(nStart, nEnd);
DWORD dwEffects = bBold?CFE_BOLD:0;
CHARFORMAT cfm;
cfm.cbSize = sizeof(cfm);
GetSelectionCharFormat(cfm);
if ((cfm.dwMask & CFM_COLOR) &&
(cfm.crTextColor == clr) &&
(cfm.dwMask & CFM_BOLD ) &&
(cfm.dwEffects & CFE_BOLD) == dwEffects)
return;
cfm.dwEffects = dwEffects;
cfm.crTextColor = clr;
cfm.dwMask = CFM_BOLD | CFM_COLOR;
SetSelectionCharFormat(cfm);
}
/* 格式化需要更新的字符块 */
void CAdvRichEdit::FormatTextRange(int nStart, int nEnd)
{
if (nStart >= nEnd)
return;
m_bInForcedChange = TRUE;
CHARRANGE crOldSel;
GetSel(crOldSel);
LockWindowUpdate();
HideSelection(TRUE, FALSE);
TCHAR *pBuffer = NULL;
try {
SetSel(nStart, nEnd);
pBuffer = new TCHAR[nEnd - nStart + 1];
/* pPtr,pBuffer 是重新format的串块 */
long nLen = GetSelText(pBuffer);
ASSERT(nLen <= nEnd - nStart);
pBuffer[nLen] = 0;
TCHAR *pStart, *pPtr;
pStart = pPtr = pBuffer;
TCHAR* pSymbolStart = NULL;
/* 全局字体颜色 */
SymbolColor ic;
/* 词法分析阶段 */
while (*pPtr != 0)
{
/* ch存储第一个字符 */
TCHAR ch = *pPtr;
/* C语言式的注释 */
if(ch == '/' && (pPtr[1] == '*'))
{
pSymbolStart = pPtr;
TCHAR ch1 = ch;
TCHAR before;
/* 预先接收*号 */
ch = *(++pPtr);
do {
before = *pPtr;
ch = *(++pPtr);
} while (ch != 0 && !(before == '*' && ch == '/'));
/* 使用before而不使用next的原因是我们需要接收'/'号,使用next那'/'就不是注释色 */
if (ch == ch1)
pPtr++;
ic = m_icComment;
}
/* C++方式的注释 */
else if(ch == '/' && (pPtr[1] == '/'))
{
pSymbolStart = pPtr;
TCHAR ch1 = ch;
ch = *(++pPtr);
do {
ch = *(++pPtr);
} while (ch != 0 && ch != '\r');
if (ch == ch1)
pPtr++;
ic = m_icComment;
}else if (_istdigit(ch) && (int)ch>0)
{ /* 如果是数字,ch大于0是处理中文因为中文是由两个char组成但是每个char都是负数 */
pSymbolStart = pPtr;
_tcstod(pSymbolStart, &pPtr);
ic = m_icNumber;
}else if (_istalpha(ch) || ch == '_')
{ /* 处理关键字,首先必须是字母或者是下划线 */
pSymbolStart = pPtr;
do {
ch = *(++pPtr);
} while (_istalnum(ch) || ch == '_');
/* 如果是数字和下划线会被接收 */
/* 接受的字符串结尾被设置为0。也就是停止接受 */
*pPtr = 0;
int nPos = IsKeyword(pSymbolStart);
if (nPos >= 0)
{
ic = m_icKeyword;
}else
{
pSymbolStart = NULL;
}
*pPtr = ch;
}else
{
pPtr++;
}
if (pSymbolStart != NULL)
{
if(pSymbolStart < pPtr)
{
SetFormatRange(nStart + pStart - pBuffer, nStart + pSymbolStart - pBuffer, FALSE, RGB(0,0,0));
SetFormatRange(nStart + pSymbolStart - pBuffer, nStart + pPtr - pBuffer, ic.bBold, ic.clrColor);
}else
{
*pPtr = 0;
}
pStart = pPtr;
pSymbolStart = 0;
} else if (*pPtr == 0)
{
SetFormatRange(nStart + pStart - pBuffer, nStart + pPtr - pBuffer, FALSE, RGB(0,0,0));
}
}
}
catch(...){}
delete [] pBuffer;
SetSel(crOldSel);
HideSelection(FALSE, FALSE);
UnlockWindowUpdate();
m_bInForcedChange = FALSE;
}
/* 更新全部字符块 */
void CAdvRichEdit::FormatAll()
{
FormatTextRange(0,GetTextLength());
}
/* 当设置文字的时候全部更新 */
LRESULT CAdvRichEdit::OnSetText(WPARAM wParam, LPARAM lParam)
{
LRESULT res = Default();
FormatAll();
return res;
}
/* 字符发生变化 */
void CAdvRichEdit::OnChange()
{
if (m_bInForcedChange)
return;
CHARRANGE crCurSel;
GetSel(crCurSel);
if (m_changeType == ctMove && crCurSel.cpMin == crCurSel.cpMax)
{
m_changeType = ctPaste;
}
switch(m_changeType)
{
case ctReplSel:
FormatAll();
break;
case ctPaste:
FormatTextLines(m_crOldSel.cpMin, crCurSel.cpMax);
break;
case ctDelete:
FormatAll();
break;
case ctBack:
case ctCut:
FormatTextLines(crCurSel.cpMin, crCurSel.cpMax);
break;
case ctUndo:
FormatAll();
break;
case ctMove:
FormatTextLines(crCurSel.cpMin, crCurSel.cpMax);
if (crCurSel.cpMin > m_crOldSel.cpMin)
FormatTextLines(m_crOldSel.cpMin, m_crOldSel.cpMin);
else
FormatTextLines(m_crOldSel.cpMax, m_crOldSel.cpMax);
break;
default:
FormatAll();
break;
}
m_changeType = ctUndo;
}
/* 如果遇到保护属性 */
void CAdvRichEdit::OnProtected(NMHDR* pNMHDR, LRESULT* pResult)
{
ENPROTECTED* pEP = (ENPROTECTED*)pNMHDR;
switch (pEP->msg)
{
case WM_KEYDOWN:
switch (pEP->wParam)
{
case VK_DELETE:
m_changeType = ctDelete;
break;
case VK_BACK:
m_changeType = ctBack;
break;
default:
m_changeType = ctUnknown;
break;
}
break;
case EM_REPLACESEL:
case WM_CHAR:
m_changeType = ctReplSel;
break;
case WM_PASTE:
m_changeType = (m_changeType == ctCut)?ctMove:ctPaste;
break;
case WM_CUT:
m_changeType = ctCut;
break;
default:
m_changeType = ctUnknown;
break;
};
if (pEP->msg != EM_SETCHARFORMAT && m_changeType != ctMove)
m_crOldSel = pEP->chrg;
*pResult = FALSE;
}
void CAdvRichEdit::OnSelChange(NMHDR* pNMHDR, LRESULT* pResult)
{
SELCHANGE* pSC = (SELCHANGE*)pNMHDR;
*pResult = 0;
}
void CAdvRichEdit::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
CRichEditCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
CWnd *parent = GetParent();
ASSERT_VALID(parent);
parent->SendMessage(WM_EDITCTRLHSCROLL,0,0);
}
void CAdvRichEdit::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
CRichEditCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
CWnd *parent = GetParent();
ASSERT_VALID(parent);
parent->SendMessage(WM_EDITCTRLHSCROLL,0,0);
}
BOOL CAdvRichEdit::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
BOOL temp = CRichEditCtrl::OnMouseWheel(nFlags, zDelta, pt);
CWnd *parent = GetParent();
ASSERT_VALID(parent);
parent->SendMessage(WM_EDITCTRLHSCROLL,0,0);
return temp;
}
/* 剪切,粘贴,拷贝,撤销,从剪切板粘贴 */
void CAdvRichEdit::DoCut()
{
this->Cut();
}
void CAdvRichEdit::DoPaste()
{
if(this->CanPaste())
{
this->Paste();
}
}
void CAdvRichEdit::DoCopy()
{
this->Copy();
}
int CAdvRichEdit::DoUndo()
{
if(this->CanUndo())
{
return this->Undo();
}
return 0;
}
void CAdvRichEdit::DoPasteSerial()
{
this->PasteSpecial(CF_TEXT);
}
void CAdvRichEdit::FormatTextLines(int nLineStart, int nLineEnd)
{
long nStart = LineIndex(LineFromChar(nLineStart));
long nEnd = LineIndex(LineFromChar(nLineEnd));
nEnd += LineLength(nLineEnd);
FormatTextRange(nStart, nEnd);
}
DWORD CALLBACK read(DWORD dwCookie,LPBYTE lpBuf,LONG nCount,LONG* nRead)
{
CFile* fp = (CFile *)dwCookie;
*nRead = fp->Read(lpBuf,nCount);
return 0;
}
bool CAdvRichEdit::LoadFile(LPCTSTR filePath)
{
CFile file;
if(!file.Open(filePath,CFile::modeReadWrite|CFile::typeBinary))
{
MessageBox("UnHandled file!\n","Error",MB_OK);
return FALSE;
}
EDITSTREAM m_es;
m_es.dwCookie = (DWORD)&file;
m_es.pfnCallback = read;
StreamIn(SF_TEXT,m_es);
file.Close();
return TRUE;
}
DWORD CALLBACK write(DWORD dwCookie,LPBYTE pbBuff,LONG cb,LONG *pcb)
{
CFile* pFile = (CFile*)dwCookie;
pFile->Write(pbBuff, cb);
*pcb = cb;
return 0;
}
bool CAdvRichEdit::SaveFile(LPCTSTR filePath)
{
CFile file;
if(!file.Open(filePath,CFile::modeCreate | CFile::modeWrite))
{
MessageBox("Cann't create the file!\n","Error",MB_OK);
return FALSE;
}
EDITSTREAM es;
es.dwCookie = (DWORD)&file;
es.pfnCallback = write;
StreamOut(SF_TEXT, es);
file.Close();
return TRUE;
}
void CAdvRichEdit::OnContextMenu(CWnd* pWnd, CPoint point)
{
CMenu *p=NULL;
p = m_editMenu.GetSubMenu(0);
ASSERT_VALID(p);
p->TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this);
}
void CAdvRichEdit::OnEditorUndo()
{
DoUndo();
}
void CAdvRichEdit::OnEditorPaste()
{
DoPasteSerial();
}
void CAdvRichEdit::OnEditorCut()
{
DoCut();
}
void CAdvRichEdit::OnEditorCopy()
{
DoCopy();
}
int CAdvRichEdit::GetCurrentLine()
{
CHARRANGE cr;
GetSel(cr);
if(cr.cpMin == cr.cpMax)
{
return LineFromChar(cr.cpMin);
}else
{
return -1;
}
}
void CAdvRichEdit::Search(LPCTSTR keyword)
{
FINDTEXTEX ft;
ft.chrg.cpMin = 0;
ft.chrg.cpMax = -1;
ft.lpstrText = (LPSTR)keyword;
long n = FindText(FR_DOWN, &ft);
if (n != -1)
{
SetSel(ft.chrgText);
}else
{
MessageBox(_T("Cann't find the string!"),_T("Tips"));
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -