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

📄 richeditctrlex.cpp

📁 Visual C++编写的工程解析器源代码
💻 CPP
字号:
// RichEditCtrlEx.cpp : implementation file
//

#include "stdafx.h"
#include "MainFrm.h"
#include "RichEditCtrlEx.h"
#include "FileEx.h"

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

/////////////////////////////////////////////////////////////////////////////
static WM_FINDREPLACE = ::RegisterWindowMessage(FINDMSGSTRING);
// CRichEditCtrlEx

CRichEditCtrlEx::CRichEditCtrlEx()
{
	CRichEditCtrl::CRichEditCtrl();	

	VERIFY(m_wndPopMenu.CreatePopupMenu());
	
	m_wndPopMenu.AppendMenu(MF_STRING, ID_RICHEDITEX_READONLY, (LPCTSTR)"只读设置(&A)");
	m_wndPopMenu.AppendMenu(MF_STRING, ID_RICHEDITEX_FONTSET, (LPCTSTR)"字体设置(&O)");
	m_wndPopMenu.AppendMenu(MF_STRING, ID_RICHEDITEX_FINDSTRING, (LPCTSTR)"查找文本(&F)");
	m_wndPopMenu.AppendMenu(MF_STRING, ID_RICHEDITEX_REPLSTRING, (LPCTSTR)"替换文本(&R)");
	m_wndPopMenu.AppendMenu(MF_STRING, ID_RICHEDITEX_SAVEFILE, (LPCTSTR)"保存文件(&S)");

	m_nSearchCharPos = 0;
}

CRichEditCtrlEx::~CRichEditCtrlEx()
{
	CRichEditCtrl::~CRichEditCtrl();
}

BEGIN_MESSAGE_MAP(CRichEditCtrlEx, CRichEditCtrl)
	//{{AFX_MSG_MAP(CRichEditCtrlEx)
	ON_WM_CONTEXTMENU()
	//}}AFX_MSG_MAP
	ON_COMMAND_RANGE(ID_RICHEDITEX_READONLY, ID_RICHEDITEX_SAVEFILE, OnMenuCommProc)
	ON_REGISTERED_MESSAGE(WM_FINDREPLACE, OnFindReplace)
END_MESSAGE_MAP()

/*********************自定义消息部分**********************/

//得到当前光标所在行(发消息)!!!!基准行为:1
int CRichEditCtrlEx::GetCursorRow()
{
	int nStartSel = 0;
	SendMessage(EM_GETSEL, (WPARAM)&nStartSel, 0);

	return SendMessage(EM_LINEFROMCHAR, (WPARAM)nStartSel, 0);	//得到当前行的索引号	
}

//得到当前光标所在列(发消息)!!!!基准列为:1
int CRichEditCtrlEx::GetCursorCol()
{
	int nLine = GetCursorRow();
	int nSelStart = 0;
	SendMessage(EM_GETSEL, (WPARAM)&nSelStart, 0);
	return nSelStart - SendMessage(EM_LINEINDEX, (WPARAM)nLine, 0);
}

//清空所有RichEditCtrl的内容,并释放所占空间
void CRichEditCtrlEx::Clear()
{
	this->SetSel(0, -1);
	this->ReplaceSel("");

	this->EmptyUndoBuffer();
}

/******************从文件加载RichEditCtrl内容****************/
void CRichEditCtrlEx::LoadFromFile(CString lpszFilename)
{
	strFilename = lpszFilename;
	CFileFind* ffFinder = new CFileFind;
	if(ffFinder->FindFile((LPCTSTR)strFilename) == 0)
	{				
		MessageBox((LPCTSTR)"打开文件出错,文件不存在或已被删除...",
			"错误信息", MB_OK | MB_ICONERROR);

		delete ffFinder;
		return;
	}
	delete ffFinder;

	m_wndPopMenu.CheckMenuItem(ID_RICHEDITEX_READONLY, MF_BYCOMMAND | MF_UNCHECKED);
	CFile pFile;
	pFile.GetStatus((LPCTSTR)strFilename, status);
	this->SetReadOnly((status.m_attribute & 0x01));	

	pFile.Open(strFilename, CFile::modeRead);

	EDITSTREAM es;
	
	es.pfnCallback = MyStreamInCallback; 
	es.dwCookie = (DWORD) &pFile;
	
	SendMessage(EM_STREAMIN, (WPARAM)SF_TEXT, (LPARAM)&es);
	
	//设置滚动条范围
	//int nMax = this->GetLineCount();
	//this->SetScrollRange(SB_VERT, 0, nMax - 1);
}

DWORD CALLBACK CRichEditCtrlEx::MyStreamInCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
   CFile* pFile = (CFile*) dwCookie;

   *pcb = pFile->Read(pbBuff, cb);

   return 0;
}

/******************保存RichEditCtrl内容到文件****************/
void CRichEditCtrlEx::SaveToFile(CString lpszFilename)
{
	CFileFind* ffFinder = new CFileFind;
	if(ffFinder->FindFile((LPCTSTR)lpszFilename) !=0)
	{
		CString str = "";
		str.Format("文件:%s\n已经存在,您想覆盖已有文件吗(Y/N)?", lpszFilename);
		if(MessageBox((LPCTSTR)str, "文件覆盖提示...", MB_YESNO | MB_ICONINFORMATION) == IDYES)
		{			
			CFile pFile;
			pFile.Open(lpszFilename, CFile::modeWrite | CFile::modeCreate);
			
			EDITSTREAM es;
			
			es.pfnCallback = MyStreamOutCallback; 
			es.dwCookie = (DWORD) &pFile;
			
			SendMessage(EM_STREAMOUT, (WPARAM)SF_TEXT, (LPARAM)&es);	
		}
	}
	else
	{
		CFile pFile;
		pFile.Open(lpszFilename, CFile::modeWrite | CFile::modeCreate);
		
		EDITSTREAM es;
		
		es.pfnCallback = MyStreamOutCallback; 
		es.dwCookie = (DWORD) &pFile;
		
		SendMessage(EM_STREAMOUT, (WPARAM)SF_TEXT, (LPARAM)&es);	
	}
	delete ffFinder;
}

DWORD CALLBACK CRichEditCtrlEx::MyStreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
   CFile* pFile = (CFile*) dwCookie;

   pFile->Write(pbBuff, cb);
   *pcb = cb;

   return 0;
}

//向RichEditCtrl中追加一行内容
void CRichEditCtrlEx::AddText(LPCTSTR szTextIn)
{
	int iTotalTextLength = GetWindowTextLength();
	this->SetSel(iTotalTextLength, iTotalTextLength);
	this->ReplaceSel(szTextIn);
	SNDUPDATEMSG();

	this->LineScroll(1);
}

//弹出右键菜单
void CRichEditCtrlEx::OnContextMenu(CWnd* pWnd, CPoint point) 
{
	if(status.m_attribute & 0x01)
		m_wndPopMenu.EnableMenuItem(ID_RICHEDITEX_READONLY, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
	else
		m_wndPopMenu.EnableMenuItem(ID_RICHEDITEX_READONLY, MF_BYCOMMAND | MF_ENABLED);

	m_wndPopMenu.TrackPopupMenu(TPM_LEFTALIGN | TPM_TOPALIGN, point.x, point.y, this);	
}

/****************************处理菜单命令*****************************/
//选择文件夹路径
CString CRichEditCtrlEx::SelectDirectory(/*LPTSTR lpszCaption*/)
{		
	CString strRet = "";
	/*
	char dispname[MAX_PATH], path[MAX_PATH];
	memset(path, 0x0, sizeof(path));
	
	//默认为程序自身路径
	::GetModuleFileName(::AfxGetInstanceHandle(), path, sizeof(path));
	strRet = CString(path);
	strRet = strRet.Left(strRet.ReverseFind('\\'));
	
	BROWSEINFO bi;
	ITEMIDLIST* pidl;
	//
	bi.hwndOwner = m_hWnd;
	bi.pidlRoot = 0;
	bi.pszDisplayName = dispname;
	bi.lpszTitle = lpszCaption;
	bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_EDITBOX|BIF_DONTGOBELOWDOMAIN ;
	bi.lpfn = 0;
	bi.lParam = 0;
	bi.iImage = 0;
	if(pidl = SHBrowseForFolder(&bi))
	{
		::memset(path, 0x0, sizeof(path));
		SHGetPathFromIDList(pidl, path);
		strRet = CString(path);
	}			
	return strRet;
	*/
	CFileDialog fdFileDilg(FALSE);
	if(fdFileDilg.DoModal() == IDOK)
		strRet = fdFileDilg.GetPathName();
	
	return strRet;
};

void CRichEditCtrlEx::OnMenuCommProc(UINT nID)
{	
	switch(nID)
	{
	case ID_RICHEDITEX_READONLY:	//只读属性
		{
			BOOL bCheckFlag = FALSE;
			if(this->GetStyle() & ES_READONLY)
				bCheckFlag = FALSE;
			else
				bCheckFlag = TRUE;
			
			this->SetReadOnly(bCheckFlag);
			m_wndPopMenu.CheckMenuItem( ID_RICHEDITEX_READONLY, MF_BYCOMMAND | (bCheckFlag ? MF_CHECKED:MF_UNCHECKED) );
			m_wndPopMenu.EnableMenuItem( ID_RICHEDITEX_REPLSTRING, MF_BYCOMMAND | 
				(bCheckFlag ? MF_DISABLED | MF_GRAYED : MF_ENABLED) );
		}
		break;

	case ID_RICHEDITEX_FONTSET:		//没有记忆当前的字体设置[在打开Font对话框之前]
		
		{
			LOGFONT lf;
			memset(&lf, 0, sizeof(LOGFONT));
			
			strcpy(lf.lfFaceName, "Arial");
			
			CFontDialog fontdlg(&lf);
			if(fontdlg.DoModal() == IDOK)
			{
				fontdlg.GetCurrentFont(&lf);
				CFont font;
				ASSERT( font.CreateFontIndirect(&lf) );
				
				this->SetFont(&font);
			}
		}
		break;

	case ID_RICHEDITEX_SAVEFILE:	//保存当前文件
		{
			CString strFilePath = SelectDirectory(/*"请选择保存目录"*/);
			strFilePath += strFilename.Right(strFilename.GetLength() - strFilename.ReverseFind('\\'));
			//
			this->SaveToFile(strFilePath);
		}
		break;

	case ID_RICHEDITEX_FINDSTRING:	//查找文本
		{			
			this->HideSelection(FALSE, TRUE);			

			CFindReplaceDialog* findDlg = new CFindReplaceDialog;
			
			CString strFind = "";
			strFind = this->GetSelText();
			findDlg->Create(TRUE, (LPCSTR)strFind, NULL, FR_DOWN, this);
		}
		break;

	case ID_RICHEDITEX_REPLSTRING:	//查找替换文本
		{
			this->HideSelection(FALSE, TRUE);
			
			CFindReplaceDialog* replaceDlg = new CFindReplaceDialog;
			
			CString strFind = "";
			strFind = this->GetSelText();
			
			replaceDlg->Create(FALSE, (LPCSTR)strFind, (LPCSTR)strFind, FR_DOWN, this);
		}
	}
}

BOOL CRichEditCtrlEx::PreTranslateMessage(MSG* pMsg) 
{
	switch(pMsg->message)
	{
	case WM_KEYDOWN:
		{
			if(HIBYTE(::GetKeyState(VK_CONTROL)) == 255)
			{
				switch(pMsg->wParam)
				{
				case 'F':	OnMenuCommProc(ID_RICHEDITEX_FINDSTRING);	return TRUE;
				case 'R':	
					{
						BOOL bCheckFlag = FALSE;
						if(this->GetStyle() & ES_READONLY)
							bCheckFlag = FALSE;
						else
							bCheckFlag = TRUE;

						if(bCheckFlag)
							OnMenuCommProc(ID_RICHEDITEX_REPLSTRING);	return TRUE;
					}
				case 'S':	OnMenuCommProc(ID_RICHEDITEX_SAVEFILE);		return TRUE;
				}
			}							
		}
	case WM_KEYUP:
	case WM_LBUTTONDOWN:
	case WM_LBUTTONUP:
		{
			SNDUPDATEMSG();
			//!!!设置m_nSearchCharPos值!!!
			m_nSearchCharPos = SendMessage(EM_LINEINDEX, (WPARAM)GetCursorRow(), 0);
			m_nSearchCharPos += this->GetCursorCol();
		}		
		break;
	}
	
	return CRichEditCtrl::PreTranslateMessage(pMsg);
}

/*********************查找/替换文本回调函数******************/
LRESULT CRichEditCtrlEx::OnFindReplace(WPARAM wParam, LPARAM lParam)
{
	CFindReplaceDialog *pDlg = CFindReplaceDialog::GetNotifier(lParam);
	if( NULL != pDlg )
	{
		FINDREPLACE* froptions = (FINDREPLACE*)lParam;
		
		FINDTEXTEX ft;
		ft.lpstrText = (LPSTR)froptions->lpstrFindWhat;
		
		DWORD dwFlags = 0x0;
		if(froptions->Flags & FR_MATCHCASE)
			dwFlags |= FR_MATCHCASE;
		
		if(froptions->Flags & FR_WHOLEWORD)
			dwFlags |= FR_WHOLEWORD;		
		
		//如果用户点击了"Find Next"/"Replace"/"Replace All"按钮
		if(froptions && (froptions->Flags & FR_FINDNEXT || froptions->Flags & FR_REPLACE))
		{			
			if(froptions->Flags & FR_DOWN)	//向下搜索
			{
				ft.chrg.cpMin = m_nSearchCharPos;
				ft.chrg.cpMax = -1;

				long n = this->FindText(dwFlags, &ft), m = n;
				if(n != -1)
				{
					m = n + strlen(ft.lpstrText);
					this->SetSel(n, m);
					if(froptions->Flags & FR_REPLACE)	//如果是向下搜索替换文本
					{
						this->ReplaceSel(froptions->lpstrReplaceWith, TRUE);
						m = n + strlen(froptions->lpstrReplaceWith);
						this->SetSel(n, m);
					}								
					SNDUPDATEMSG();
					m_nSearchCharPos = m;
				}
				else
				{
					this->ReplaceSel(froptions->lpstrReplaceWith, TRUE);
					MessageBox("文档搜索完毕!", "Microsoft文本搜索器", MB_OK | MB_ICONWARNING);
				}
			}
			//向上搜索
			else
			{					
				long nLoopMin = 0, nStorePos = -1;
				ft.chrg.cpMin = nLoopMin;
				ft.chrg.cpMax = m_nSearchCharPos;				
				
				while((nLoopMin = this->FindText(dwFlags, &ft)) != -1)
				{
					ft.chrg.cpMin = nLoopMin + strlen(ft.lpstrText);
					nStorePos = nLoopMin;
				}
				
				if(nStorePos != -1 && m_nSearchCharPos != 0)
				{
					m_nSearchCharPos = nStorePos;
					this->SetSel(m_nSearchCharPos, m_nSearchCharPos + strlen(ft.lpstrText));
					SNDUPDATEMSG();
				}
				else
					MessageBox("文档搜索完毕!", "Microsoft文本搜索器", MB_OK | MB_ICONWARNING);
			}					
		}
		else if(froptions->Flags & FR_REPLACEALL)	//替换全部内容
		{
			ft.chrg.cpMin = m_nSearchCharPos;
			ft.chrg.cpMax = -1;

			long n = this->FindText(dwFlags, &ft), m = n + strlen(froptions->lpstrFindWhat);
						
			while(n != -1)
			{				
				this->SetSel(n, m);
				this->ReplaceSel(froptions->lpstrReplaceWith, TRUE);

				m = n + strlen(froptions->lpstrReplaceWith);
				this->SetSel(n, m);
											
				SNDUPDATEMSG();
				m_nSearchCharPos = m;

				ft.chrg.cpMin = m_nSearchCharPos;
				n = this->FindText(dwFlags, &ft);		
				m = n + strlen(froptions->lpstrFindWhat);
			}
		}
	}
	return 0;
}

⌨️ 快捷键说明

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