📄 richeditctrlex.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 + -