📄 viewedit.cpp
字号:
}
void CEditView::OnEditReplace()
{
ASSERT_VALID(this);
OnEditFindReplace(FALSE);
ASSERT_VALID(this);
}
void CEditView::OnEditRepeat()
{
ASSERT_VALID(this);
_AFX_EDIT_STATE* pEditState = _afxEditState;
if (!FindText(pEditState->strFind,
pEditState->bNext,
pEditState->bCase))
{
OnTextNotFound(pEditState->strFind);
}
ASSERT_VALID(this);
}
void CEditView::OnEditFindReplace(BOOL bFindOnly)
{
ASSERT_VALID(this);
_AFX_EDIT_STATE* pEditState = _afxEditState;
if (pEditState->pFindReplaceDlg != NULL)
{
if (pEditState->bFindOnly == bFindOnly)
{
pEditState->pFindReplaceDlg->SetActiveWindow();
pEditState->pFindReplaceDlg->ShowWindow(SW_SHOW);
return;
}
ASSERT(pEditState->bFindOnly != bFindOnly);
pEditState->pFindReplaceDlg->SendMessage(WM_CLOSE);
ASSERT(pEditState->pFindReplaceDlg == NULL);
ASSERT_VALID(this);
}
CString strFind;
GetSelectedText(strFind);
if (strFind.IsEmpty())
strFind = pEditState->strFind;
CString strReplace = pEditState->strReplace;
pEditState->pFindReplaceDlg = new CFindReplaceDialog;
ASSERT(pEditState->pFindReplaceDlg != NULL);
DWORD dwFlags = FR_HIDEWHOLEWORD;
if (pEditState->bNext)
dwFlags |= FR_DOWN;
if (pEditState->bCase)
dwFlags |= FR_MATCHCASE;
if (!pEditState->pFindReplaceDlg->Create(bFindOnly, strFind,
strReplace, dwFlags, this))
{
pEditState->pFindReplaceDlg = NULL;
ASSERT_VALID(this);
return;
}
pEditState->pFindReplaceDlg->SetActiveWindow();
pEditState->pFindReplaceDlg->ShowWindow(SW_SHOW);
ASSERT(pEditState->pFindReplaceDlg != NULL);
pEditState->bFindOnly = bFindOnly;
ASSERT_VALID(this);
}
void CEditView::OnFindNext(LPCTSTR lpszFind, BOOL bNext, BOOL bCase)
{
ASSERT_VALID(this);
_AFX_EDIT_STATE* pEditState = _afxEditState;
pEditState->strFind = lpszFind;
pEditState->bCase = bCase;
pEditState->bNext = bNext;
if (!FindText(pEditState->strFind, bNext, bCase))
OnTextNotFound(pEditState->strFind);
ASSERT_VALID(this);
}
void CEditView::OnReplaceSel(LPCTSTR lpszFind, BOOL bNext, BOOL bCase,
LPCTSTR lpszReplace)
{
ASSERT_VALID(this);
_AFX_EDIT_STATE* pEditState = _afxEditState;
pEditState->strFind = lpszFind;
pEditState->strReplace = lpszReplace;
pEditState->bCase = bCase;
pEditState->bNext = bNext;
if (!InitializeReplace())
return;
GetEditCtrl().ReplaceSel(pEditState->strReplace);
FindText(pEditState->strFind, bNext, bCase);
ASSERT_VALID(this);
}
void CEditView::OnReplaceAll(LPCTSTR lpszFind, LPCTSTR lpszReplace, BOOL bCase)
{
ASSERT_VALID(this);
_AFX_EDIT_STATE* pEditState = _afxEditState;
pEditState->strFind = lpszFind;
pEditState->strReplace = lpszReplace;
pEditState->bCase = bCase;
pEditState->bNext = TRUE;
if (!InitializeReplace() &&
!SameAsSelected(pEditState->strFind, pEditState->bCase))
{
// initial find was not successful
return;
}
do
{
GetEditCtrl().ReplaceSel(pEditState->strReplace);
} while (FindText(pEditState->strFind, 1, bCase));
ASSERT_VALID(this);
}
BOOL CEditView::InitializeReplace()
// helper to do find first if no selection
{
ASSERT_VALID(this);
_AFX_EDIT_STATE* pEditState = _afxEditState;
// do find next if no selection
int nStartChar, nEndChar;
GetEditCtrl().GetSel(nStartChar, nEndChar);
if (nStartChar == nEndChar)
{
if (!FindText(pEditState->strFind, pEditState->bNext,
pEditState->bCase))
{
// text not found
OnTextNotFound(pEditState->strFind);
}
return FALSE;
}
if (!SameAsSelected(pEditState->strFind, pEditState->bCase))
{
if (!FindText(pEditState->strFind, pEditState->bNext,
pEditState->bCase))
{
// text not found
OnTextNotFound(pEditState->strFind);
}
return FALSE;
}
ASSERT_VALID(this);
return TRUE;
}
LRESULT CEditView::OnFindReplaceCmd(WPARAM, LPARAM lParam)
{
ASSERT_VALID(this);
_AFX_EDIT_STATE* pEditState = _afxEditState;
CFindReplaceDialog* pDialog = CFindReplaceDialog::GetNotifier(lParam);
ASSERT(pDialog != NULL);
ASSERT(pDialog == pEditState->pFindReplaceDlg);
if (pDialog->IsTerminating())
{
pEditState->pFindReplaceDlg = NULL;
}
else if (pDialog->FindNext())
{
OnFindNext(pDialog->GetFindString(),
pDialog->SearchDown(), pDialog->MatchCase());
}
else if (pDialog->ReplaceCurrent())
{
ASSERT(!pEditState->bFindOnly);
OnReplaceSel(pDialog->GetFindString(),
pDialog->SearchDown(), pDialog->MatchCase(),
pDialog->GetReplaceString());
}
else if (pDialog->ReplaceAll())
{
ASSERT(!pEditState->bFindOnly);
OnReplaceAll(pDialog->GetFindString(), pDialog->GetReplaceString(),
pDialog->MatchCase());
}
ASSERT_VALID(this);
return 0;
}
typedef int (WINAPI* AFX_COMPARE_PROC)(LPCTSTR str1, LPCTSTR str2);
BOOL CEditView::SameAsSelected(LPCTSTR lpszCompare, BOOL bCase)
{
// check length first
size_t nLen = lstrlen(lpszCompare);
int nStartChar, nEndChar;
GetEditCtrl().GetSel(nStartChar, nEndChar);
if (nLen != (size_t)(nEndChar - nStartChar))
return FALSE;
// length is the same, check contents
CString strSelect;
GetSelectedText(strSelect);
return (bCase && lstrcmp(lpszCompare, strSelect) == 0) ||
(!bCase && lstrcmpi(lpszCompare, strSelect) == 0);
}
BOOL CEditView::FindText(LPCTSTR lpszFind, BOOL bNext, BOOL bCase)
{
ASSERT_VALID(this);
ASSERT(lpszFind != NULL);
ASSERT(*lpszFind != '\0');
UINT nLen = GetBufferLength();
int nStartChar, nEndChar;
GetEditCtrl().GetSel(nStartChar, nEndChar);
UINT nStart = nStartChar;
int iDir = bNext ? +1 : -1;
// can't find a match before the first character
if (nStart == 0 && iDir < 0)
return FALSE;
CWaitCursor wait;
LPCTSTR lpszText = LockBuffer();
if (iDir < 0)
{
// always go back one for search backwards
nStart -= (lpszText+nStart) -
_tcsdec(lpszText, lpszText+nStart);
}
else if (nStartChar != nEndChar && SameAsSelected(lpszFind, bCase))
{
// easy to go backward/forward with SBCS
if (_istlead(lpszText[nStart]))
nStart++;
nStart += iDir;
}
// handle search with nStart past end of buffer
size_t nLenFind = lstrlen(lpszFind);
if (nStart+nLenFind-1 >= nLen)
{
if (iDir < 0 && nLen >= nLenFind)
{
if (_afxDBCS)
{
// walk back to previous character n times
nStart = nLen;
int n = nLenFind;
while (n--)
{
nStart -= (lpszText+nStart) -
_tcsdec(lpszText, lpszText+nStart);
}
}
else
{
// single-byte character set is easy and fast
nStart = nLen - nLenFind;
}
ASSERT(nStart+nLenFind-1 <= nLen);
}
else
{
UnlockBuffer();
return FALSE;
}
}
// start the search at nStart
LPCTSTR lpsz = lpszText + nStart;
AFX_COMPARE_PROC pfnCompare = bCase ? lstrcmp : lstrcmpi;
if (_afxDBCS)
{
// double-byte string search
LPCTSTR lpszStop;
if (iDir > 0)
{
// start at current and find _first_ occurrance
lpszStop = lpszText + nLen - nLenFind + 1;
}
else
{
// start at top and find _last_ occurrance
lpszStop = lpsz;
lpsz = lpszText;
}
LPCTSTR lpszFound = NULL;
while (lpsz <= lpszStop)
{
if (!bCase || (*lpsz == *lpszFind &&
(!_istlead(*lpsz) || lpsz[1] == lpszFind[1])))
{
LPTSTR lpch = (LPTSTR)(lpsz + nLenFind);
TCHAR chSave = *lpch;
*lpch = '\0';
int nResult = (*pfnCompare)(lpsz, lpszFind);
*lpch = chSave;
if (nResult == 0)
{
lpszFound = lpsz;
if (iDir > 0)
break;
}
}
lpsz = _tcsinc(lpsz);
}
UnlockBuffer();
if (lpszFound != NULL)
{
int n = (int)(lpszFound - lpszText);
GetEditCtrl().SetSel(n, n+nLenFind);
return TRUE;
}
}
else
{
// single-byte string search
UINT nCompare;
if (iDir < 0)
nCompare = (UINT)(lpsz - lpszText) + 1;
else
nCompare = nLen - (UINT)(lpsz - lpszText) - nLenFind + 1;
while (nCompare > 0)
{
ASSERT(lpsz >= lpszText);
ASSERT(lpsz+nLenFind-1 <= lpszText+nLen-1);
LPSTR lpch = (LPSTR)(lpsz + nLenFind);
char chSave = *lpch;
*lpch = '\0';
int nResult = (*pfnCompare)(lpsz, lpszFind);
*lpch = chSave;
if (nResult == 0)
{
UnlockBuffer();
int n = (int)(lpsz - lpszText);
GetEditCtrl().SetSel(n, n+nLenFind);
ASSERT_VALID(this);
return TRUE;
}
// restore character at end of search
*lpch = chSave;
// move on to next substring
nCompare--;
lpsz += iDir;
}
UnlockBuffer();
}
ASSERT_VALID(this);
return FALSE;
}
void CEditView::OnTextNotFound(LPCTSTR)
{
ASSERT_VALID(this);
MessageBeep(0);
}
/////////////////////////////////////////////////////////////////////////////
// CEditView Tab Stops
void CEditView::SetTabStops(int nTabStops)
{
ASSERT_VALID(this);
m_nTabStops = nTabStops;
GetEditCtrl().SetTabStops(m_nTabStops);
Invalidate();
ASSERT_VALID(this);
}
/////////////////////////////////////////////////////////////////////////////
// CEditView diagnostics
#ifdef _DEBUG
void CEditView::AssertValid() const
{
CCtrlView::AssertValid();
ASSERT_VALID(&m_aPageStart);
if (m_hPrinterFont != NULL)
ASSERT_VALID(CFont::FromHandle(m_hPrinterFont));
if (m_hMirrorFont != NULL)
ASSERT_VALID(CFont::FromHandle(m_hMirrorFont));
_AFX_EDIT_STATE* pEditState = _afxEditState;
if (pEditState->pFindReplaceDlg != NULL)
ASSERT_VALID(pEditState->pFindReplaceDlg);
}
void CEditView::Dump(CDumpContext& dc) const
{
CCtrlView::Dump(dc);
dc << "m_nTabStops = " << m_nTabStops;
if (m_hPrinterFont != NULL)
dc << "\nm_hPrinterFont " << (UINT)m_hPrinterFont;
if (m_hMirrorFont != NULL)
dc << "\nm_hMirrorFont " << (UINT)m_hMirrorFont;
dc << "\nm_aPageStart: " << &m_aPageStart;
dc << "\nstatic member data:";
_AFX_EDIT_STATE* pEditState = _afxEditState;
if (pEditState->pFindReplaceDlg != NULL)
{
dc << "\npFindReplaceDlg = "
<< (void*)pEditState->pFindReplaceDlg;
dc << "\nbFindOnly = " << pEditState->bFindOnly;
}
dc << "\nstrFind = " << pEditState->strFind;
dc << "\nstrReplace = " << pEditState->strReplace;
dc << "\nbCase = " << pEditState->bCase;
dc << "\nbNext = " << pEditState->bNext;
dc << "\n";
}
#endif //_DEBUG
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif
IMPLEMENT_DYNCREATE(CEditView, CCtrlView)
#pragma warning(disable: 4074)
#pragma init_seg(lib)
PROCESS_LOCAL(_AFX_EDIT_STATE, _afxEditState)
/////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -