⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 advrichedit.cpp

📁 一个PLX教学编译器IDE
💻 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 + -