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

📄 syneditview.cpp

📁 编译原理语法分析器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
////////////////////////////////////////////////////////////
//	文件:		SynEditView.cpp
//	版本:		1.0.0.0
//	创建	:	2002年1月15日
//
//	作者:		郑旭
//	E-mail:		happymood@163.net
//
//	CSynEditView语法编辑视实现代码
//
//	你可以自由使用或是改变CSynEditView的代码以适应你的需要,
//	但是请保留这段文字。
////////////////////////////////////////////////////////////

//本人欲在北京求一软件开发职位,期望月薪3000元以上,
//若您是招聘单位并对本人有意,请与本人联系。

/*//////////////////////////////////////////////////////////
设计思路:
假设SynCtrl即是隐藏在CRichEditView后面可以用GetRichEditCtrl函数取得的控制。
SynEditView可看作覆盖在SynCtrl表面的一层不透明的画布,在程序中我们自己作画,
再将画出来的内容覆盖在SynCtrl表面,即可作成语法关键字编辑效果。
虽然在程序中重载OnPaint函数但不作任何操作带来的后果是SynCtrl不再重画,但是
隐藏在SynCtrl后面的内容仍然存在,我们可以通过GetLine取得其文本信息,也可以
通过GetFont取得其字体信息!我们可以取出这些信息进行加工,再将加工后的东西显
示出来。通过仔细的调整各个参数,使得画出来的东西与不重载SynCtrl的OnPaint函
数前SynCtrl画出来的东西完全重合,但只是把其中是关键字的部分进行着色,即可达
到完美的语法编程器的效果。
/*//////////////////////////////////////////////////////////

#include "stdafx.h"
#include <winver.h>
#include <malloc.h>

#include "SynEditView.h"

const COOKIE_COMMENT		=		0x0002;
const COOKIE_EXT_COMMENT	=		0x0004;
const COOKIE_STRING			=		0x0008;
const COOKIE_CHAR			=		0x0010;

//定义颜色块宏
#define DEFINE_BLOCK(pos, color)	\
	ASSERT((pos) >= 0 && (pos) <= nLength);\
	if (ColorInfo != NULL)\
{\
	if (nActualItems == 0 || ColorInfo[nActualItems - 1].Pos <= (pos)) {\
		ColorInfo[nActualItems].Pos = (pos);\
		ColorInfo[nActualItems].Color = (color);\
		nActualItems ++;\
	}\
}


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
 
/////////////////////////////////////////////////////////////////////////////
// CSynEditView

IMPLEMENT_DYNCREATE(CSynEditView, CSynEditView)

BEGIN_MESSAGE_MAP(CSynEditView, CSynEditView)
//{{AFX_MSG_MAP(CSynEditView)
ON_WM_CREATE()
	ON_WM_HSCROLL()
	ON_WM_VSCROLL()
	//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CSynEditView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CSynEditView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CSynEditView::OnFilePrintPreview)
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CSynEditView construction/destruction

CSynEditView::CSynEditView()
{
	m_nLanguage = _CPP;

	m_clrBkColor = RGB(255, 255, 255);  
	m_clrCommentColor = RGB(0, 128, 0);  
	m_clrSyntaxColor = RGB(0, 0, 255);  
	m_clrNormalColor = RGB(0, 0, 0);  
	m_clrStringColor = RGB(200, 0, 0);  
	m_clrCharColor = RGB(200, 0, 0);  
	m_clrNumberColor = RGB(255, 0, 0);  
	m_clrBKSelText = RGB(0, 0, 128);  	

	m_nTabSize = 4;
	m_nParseArraySize = 0;
	m_nLeftMargin = 1;
	m_nTopMargin = 1;
	m_bAllowDraw = TRUE;
	m_bRealReturn = TRUE;

	m_bTracking = FALSE;
	m_pdwParseCookies = NULL;
	m_rcClient = NULL;
	m_pCacheBitmap = NULL;
}

CSynEditView::~CSynEditView()
{
	if (m_pCacheBitmap != NULL)
		delete m_pCacheBitmap;
	
	if (m_pdwParseCookies != NULL)
		delete m_pdwParseCookies;
}

BOOL CSynEditView::PreCreateWindow(CREATESTRUCT& cs)
{
	//装入rich edit version 2.0
	if (LoadLibraryA("RICHED20.DLL") == NULL)
	{
		AfxMessageBox(_T("Fail to load \"riched20.dll\"."),
			MB_OK | MB_ICONERROR);
		PostMessage(WM_QUIT,0,0);
		return FALSE;
	}
	m_strClass = RICHEDIT_CLASSA;	//for 2.0 class 

	return CSynEditView::PreCreateWindow(cs);
}

void CSynEditView::OnInitialUpdate()
{
	CSynEditView::OnInitialUpdate();

	SetMargins(CRect(720, 720, 720, 720));
	
	SelectLanguage( _CPP );

	::GetObject(GetStockObject(SYSTEM_FONT), sizeof(LOGFONT), &m_lf);  
	m_lf.lfWeight = FW_NORMAL;
	m_lf.lfHeight = 0xfffffff2;
	m_lf.lfCharSet = GB2312_CHARSET;
	strcpy(m_lf.lfFaceName, _T("Fixedsys"));

	SetSynEditViewFont(m_lf); 

	SendMessage(EM_SETUNDOLIMIT, 1000, 0);
	GetDocument()->m_bRTF = FALSE; //只处理文本
	SetWrapMode(WrapNone);

	SendMessage(EM_SETTEXTMODE, TM_PLAINTEXT|TM_MULTILEVELUNDO|TM_SINGLECODEPAGE, 0);
}

/////////////////////////////////////////////////////////////////////////////
// CSynEditView printing

BOOL CSynEditView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}


/////////////////////////////////////////////////////////////////////////////
// CSynEditView diagnostics

#ifdef _DEBUG
void CSynEditView::AssertValid() const
{
	CSynEditView::AssertValid();
}

void CSynEditView::Dump(CDumpContext& dc) const
{
	CSynEditView::Dump(dc);
}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CSynEditView message handlers

void CSynEditView::LoadFile(CString strFile)
{
	ASSERT(this);

	CFile* pInputFile = NULL;
	try
	{
		pInputFile = new CFile(strFile, CFile::modeRead | CFile::shareDenyNone);
		
		EDITSTREAM strm;
		strm.dwCookie = (DWORD) pInputFile;
		strm.pfnCallback = EditStreamCallbackReadFromFile;
		
		long lResult = GetRichEditCtrl().StreamIn(SF_TEXT, strm);
		
		pInputFile->Close();
		delete pInputFile;
	}
	catch (CFileException* pEx)
	{
		pEx->Delete();
	}

	GetRichEditCtrl().SetModify( FALSE ); 
}

 
//设定编辑器字体
void CSynEditView::SetSynEditViewFont(LOGFONT lf)
{
	m_lf = lf;
	SetSynCtrlFont();
	SetSynEditViewTabSize(m_nTabSize);
}

void CSynEditView::SetSynCtrlFont()
{
	CString str;
	GetWindowText(str);
	BOOL bModify = GetRichEditCtrl().GetModify(); 

	m_font.DeleteObject();
	m_font.CreateFontIndirect(&m_lf); 
	SetFont(&m_font);

	CalcEditorInfo();
	SetSynEditViewMargin(m_nCharNumberWidth, 0);
	
	SetWindowText(str);
	GetRichEditCtrl().SetModify(bModify);
}

//设定编辑器的Tab宽度,以空格为标准进行计算
void CSynEditView::SetSynEditViewTabSize(int nSize)
{
	ResetParseCookie();

	CString str;
	GetWindowText(str);

	CRichEditCtrl &SynCtrl = GetRichEditCtrl();

	BOOL bModify = SynCtrl.GetModify(); 
	SetSynCtrlTabSize(nSize);

	SetWindowText(str);
	SynCtrl.SetModify(bModify);
}

//改变RichEditCtrl的默认Tab宽度
void CSynEditView::SetSynCtrlTabSize(int nSize)
{
	CRichEditCtrl &SynCtrl = GetRichEditCtrl();	 

	//设置TAB间隔
	CDC *pdc = GetDC();
	PARAFORMAT pf ;
	pf.cbSize = sizeof(PARAFORMAT);
	pf.dwMask = PFM_TABSTOPS ;
	pf.cTabCount = MAX_TAB_STOPS;
	SynCtrl.GetParaFormat( pf );
	int nSynCtrlTabSize = pf.rgxTabs[0];
	if(nSynCtrlTabSize == 0)
		nSynCtrlTabSize = 720;

	int nNewTab;
	nNewTab = int(nSynCtrlTabSize * 1.0 * nSize * m_nCharSpaceWidth / m_nCharTabWidth);

	pf.cTabCount = MAX_TAB_STOPS;
	pf.dwMask = PFM_TABSTOPS;
	for( int itab = 0; itab < pf.cTabCount; itab++ )
		pf.rgxTabs[itab] = (itab+1) * nNewTab ;
	SetParaFormat( pf );

	m_nTabSize = nSize;	
}


void CSynEditView::LoadText(CString &strText)
{
	ASSERT(this);

	ResetParseCookie();	
	SetWindowText(strText);
	GetRichEditCtrl().SetModify( FALSE ); 
}

//根据指定行在指定的矩形区域画出语法加亮的文本
void CSynEditView::DrawSingleLineColorText( CDC *cacheDC, int nLine, CRect rcLine)
{
	CRect rectforspace(rcLine);
	CRect rect(rcLine);
	
	CFont cf;
	cf.CreateFontIndirect(&m_lf);
	CFont *pOldFont = cacheDC->SelectObject(&cf);
	
	CString strnewline=_T(""), strtmp=_T(""), strLine;
	BOOL bRealReturn = GetLineString(nLine, strLine); //取指定行文本,并返回是否为硬回车标志

	int nTabNumber = 0;
	int npos = strLine.Find(_T("\t"));

	//将所有的Tab转化为相应数量的空格
	while(npos!=-1) {
		strtmp = strLine.Left(npos); 
		int nlen = strtmp.GetLength();
		nlen %= m_nTabSize;
		nlen = m_nTabSize - nlen;
		CString strNewTab(0x20, nlen);
		strtmp+=strNewTab;
		strnewline+=strtmp;
		strLine=strLine.Right(strLine.GetLength()-npos-1); 
		npos = strLine.Find(_T("\t"));
	}
	strnewline+=strLine;
	strLine=strnewline;

	int nLength = strLine.GetLength(); 
	CSize size;
	
	int nActualItems = 0;
	COLORINFO *ColorInfo = (COLORINFO *)_alloca( sizeof(COLORINFO) * (nLength + 1) );	
	DWORD dwCookie = GetParseCookie(nLine-1);
	CString str;
	if( m_bRealReturn )
		dwCookie &= COOKIE_EXT_COMMENT; 
	m_bRealReturn = bRealReturn;
	dwCookie = ParseLine(dwCookie, strLine, ColorInfo, nActualItems);
	m_pdwParseCookies[nLine] = dwCookie;
	
	COLORREF clr;
	int nlen;
	if (nActualItems > 0)
	{
		ASSERT(ColorInfo[0].Pos >= 0 && ColorInfo[0].Pos <= nLength);
		for (int I = 0; I < nActualItems; I ++)
		{
			nlen = ColorInfo[I + 1].Pos - ColorInfo[I].Pos;
			if( I == nActualItems - 1 )
				str = strLine.Mid(ColorInfo[I].Pos, strLine.GetLength() - ColorInfo[I].Pos);
			else
				str = strLine.Mid(ColorInfo[I].Pos, nlen);

			if(str.IsEmpty())
				continue;

			clr = GetColor(ColorInfo[I].Color);
			JudgeInSeletioAndDrawText( cacheDC, rcLine, str, m_clrBkColor, clr );
		}
	}

	cacheDC->SelectObject(pOldFont); 
}

void CSynEditView::SetWrapMode(int nWrapMode)
{
	ASSERT(this);

	m_nWordWrap = nWrapMode;
	CSynEditView::WrapChanged(); 
	ResetParseCookie();

	if(m_nWordWrap == WrapNone)
	{
		GetRichEditCtrl().ShowScrollBar(SB_BOTH, TRUE); 
	}
	else
	{
		GetRichEditCtrl().ShowScrollBar(SB_HORZ, FALSE); 
	}
}


int CSynEditView::GetLinesTop(int nline)
{
	CRichEditCtrl &SynCtrl = GetRichEditCtrl();
	if( nline > SynCtrl.GetLineCount()-1 ) {
		int nOffset = SynCtrl.LineIndex( nline-1 );
		CPoint p = SynCtrl.GetCharPos( nOffset );	
		return p.y+m_nLineHeight;
	}
	int nOffset = SynCtrl.LineIndex( nline );
	CPoint p = SynCtrl.GetCharPos( nOffset );	
	return p.y;
}


int CSynEditView::GetCurrentLine()
{
	CRichEditCtrl &SynCtrl=GetRichEditCtrl();	
	CHARRANGE cr;
	SynCtrl.GetSel(cr); 
	if( cr.cpMin == cr.cpMax )
		return SynCtrl.LineFromChar( cr.cpMax );
	else
		return m_nCurrentLine;
}


DWORD CSynEditView::GetParseCookie(int nLineIndex)
{
	CRichEditCtrl &SynCtrl=GetRichEditCtrl();
	if (m_pdwParseCookies == NULL)
	{
		m_nParseArraySize = m_nLineCount;
		m_pdwParseCookies = new DWORD[m_nLineCount];
		memset(m_pdwParseCookies, 0xff, m_nLineCount * sizeof(DWORD));
	}
	
	if (nLineIndex < 0)
		return 0;
	if (m_pdwParseCookies[nLineIndex] != (DWORD) -1)
		return m_pdwParseCookies[nLineIndex];
	
	register int L = nLineIndex;
	while (L >= 0 && m_pdwParseCookies[L] == (DWORD) -1)
		L --;
	L ++;
	
	int nBlocks = 0;
	CString strLine;
	BOOL bRealReturn = m_bRealReturn;
	while (L <= nLineIndex)
	{
		DWORD dwCookie = 0;
		if (L > 0) {
			dwCookie = m_pdwParseCookies[L - 1];
			if(bRealReturn )
				dwCookie &= COOKIE_EXT_COMMENT;
		}
		ASSERT(dwCookie != (DWORD) -1);
		bRealReturn = GetLineString(L, strLine);
		m_pdwParseCookies[L] = ParseLine(dwCookie, strLine, NULL, nBlocks);
		ASSERT(m_pdwParseCookies[L] != (DWORD) -1);
		L ++;
	}
	
	return m_pdwParseCookies[nLineIndex];
}

//取指定行文本,返回指定该行在WrapToWindow模式下是否为硬回车
//[注]在WrapToWindow模式下如果一行过长则会被分割成多行,此时只有最后一行才是硬回车
BOOL CSynEditView::GetLineString(int nLine, CString &strLine)
{
	strLine = _T("");
	CRichEditCtrl &SynCtrl=GetRichEditCtrl();
	if(nLine > m_nLineCount - 1 || nLine < 0) 
		return TRUE;
		
	int nTemp = SynCtrl.LineIndex(nLine);
	nTemp = SynCtrl.LineLength(nTemp) * sizeof(WCHAR);
	if(nTemp<=1) {
		strLine=_T(" ");
		return TRUE;
	}
	nTemp += 4 * sizeof(WCHAR); //尽量多留点空
	int nLen = SynCtrl.GetLine(nLine, strLine.GetBuffer(nTemp), nTemp);  		
	strLine.ReleaseBuffer(); 
	BOOL bRealReturn;
	
	if(nLen > strLine.GetLength())
		nLen = strLine.GetLength();
	if(nLen>=1 && strLine[nLen-1]==0xd ) {
		strLine = strLine.Left(--nLen);  
		bRealReturn=TRUE;
	}
	else  {
		strLine = strLine.Left(nLen);  
		bRealReturn=FALSE;
	}
	strLine += _T(" ");

	return bRealReturn;
}

//重置语法解析缓冲区
void CSynEditView::ResetParseCookie()

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -