📄 viewedit.cpp
字号:
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#include <ctype.h>
#ifdef AFX_CORE4_SEG
#pragma code_seg(AFX_CORE4_SEG)
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CEditView
#define new DEBUG_NEW
AFX_STATIC const UINT _afxMsgFindReplace = ::RegisterWindowMessage(FINDMSGSTRING);
#ifdef _UNICODE
AFX_STATIC_DATA HFONT _afxUnicodeFont = 0;
void AFX_CDECL AfxEditviewTerm()
{
AfxDeleteObject((HGDIOBJ*)&_afxUnicodeFont);
}
char _afxEditviewTerm = (char)atexit(&AfxEditviewTerm);
#endif //_UNICODE
BEGIN_MESSAGE_MAP(CEditView, CCtrlView)
//{{AFX_MSG_MAP(CEditView)
ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateNeedSel)
ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateNeedClip)
ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_ALL, OnUpdateNeedText)
ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
ON_UPDATE_COMMAND_UI(ID_EDIT_FIND, OnUpdateNeedText)
ON_UPDATE_COMMAND_UI(ID_EDIT_REPLACE, OnUpdateNeedText)
ON_UPDATE_COMMAND_UI(ID_EDIT_REPEAT, OnUpdateNeedFind)
ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateNeedSel)
ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR, OnUpdateNeedSel)
ON_CONTROL_REFLECT_EX(EN_CHANGE, OnEditChange)
ON_WM_CREATE()
ON_MESSAGE(WM_SETFONT, OnSetFont)
ON_COMMAND(ID_EDIT_CUT, OnEditCut)
ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)
ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll)
ON_COMMAND(ID_EDIT_FIND, OnEditFind)
ON_COMMAND(ID_EDIT_REPLACE, OnEditReplace)
ON_COMMAND(ID_EDIT_REPEAT, OnEditRepeat)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
// Special registered message for Find and Replace
ON_REGISTERED_MESSAGE(_afxMsgFindReplace, OnFindReplaceCmd)
// Standard Print commands (print only - not preview)
ON_COMMAND(ID_FILE_PRINT, CCtrlView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CCtrlView::OnFilePrint)
END_MESSAGE_MAP()
const AFX_DATADEF DWORD CEditView::dwStyleDefault =
AFX_WS_DEFAULT_VIEW |
WS_HSCROLL | WS_VSCROLL |
ES_AUTOHSCROLL | ES_AUTOVSCROLL |
ES_MULTILINE | ES_NOHIDESEL;
// Operating system specific maximum buffer limit
const AFX_DATADEF UINT CEditView::nMaxSize = 1024U*1024U-1;
/////////////////////////////////////////////////////////////////////////////
// _AFX_EDIT_STATE
_AFX_EDIT_STATE::_AFX_EDIT_STATE()
{
// Note: it is only necessary to initialize non-zero data.
bNext = TRUE;
}
_AFX_EDIT_STATE::~_AFX_EDIT_STATE()
{
}
EXTERN_PROCESS_LOCAL(_AFX_EDIT_STATE, _afxEditState)
/////////////////////////////////////////////////////////////////////////////
// CEditView construction/destruction
// pass a NULL style because dwStyleDefault stays for backward compatibility
CEditView::CEditView() : CCtrlView(_T("EDIT"), NULL)
{
m_nTabStops = 8*4; // default 8 character positions
m_hPrinterFont = NULL;
m_hMirrorFont = NULL;
m_pShadowBuffer = NULL;
m_nShadowSize = 0;
}
CEditView::~CEditView()
{
ASSERT(m_hWnd == NULL);
ASSERT(m_pShadowBuffer == NULL || afxData.bWin95);
delete[] m_pShadowBuffer;
}
BOOL CEditView::PreCreateWindow(CREATESTRUCT& cs)
{
m_dwDefaultStyle = dwStyleDefault;
return CCtrlView::PreCreateWindow(cs);
}
int CEditView::OnCreate(LPCREATESTRUCT lpcs)
{
if (CCtrlView::OnCreate(lpcs) != 0)
return -1;
#ifdef _UNICODE
AfxLockGlobals(CRIT_EDITVIEW);
if (_afxUnicodeFont == NULL)
{
// get unicode font same size as system font
HFONT hSystemFont = (HFONT)GetStockObject(SYSTEM_FONT);
LOGFONT systemFont;
VERIFY(::GetObject(hSystemFont, sizeof(LOGFONT), (void*)&systemFont));
// default size and facename, but allow customization
LOGFONT logFont; memset(&logFont, 0, sizeof(LOGFONT));
logFont.lfHeight = systemFont.lfHeight;
logFont.lfWeight = systemFont.lfWeight;
logFont.lfCharSet = DEFAULT_CHARSET;
lstrcpy(logFont.lfFaceName, _T("Lucida Sans Unicode"));
AfxCustomLogFont(AFX_IDS_UNICODE_FONT, &logFont);
// attempt to create the font
_afxUnicodeFont = ::CreateFontIndirect(&logFont);
if (_afxUnicodeFont == NULL)
TRACE1("Unable to create unicode font '%s'.\n", logFont.lfFaceName);
}
AfxUnlockGlobals(CRIT_EDITVIEW);
// set unicode font instead of using system font
if (_afxUnicodeFont != NULL)
SendMessage(WM_SETFONT, (WPARAM)_afxUnicodeFont);
#endif
GetEditCtrl().LimitText(nMaxSize);
GetEditCtrl().SetTabStops(m_nTabStops);
return 0;
}
void CEditView::OnDestroy()
{
_AFX_EDIT_STATE* pEditState = _afxEditState;
pEditState->pFindReplaceDlg = NULL;
CView::OnDestroy();
}
// EDIT controls always turn off WS_BORDER and draw it themselves
void CEditView::CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType)
{
if (nAdjustType != 0)
{
// default behavior for in-place editing handles scrollbars
DWORD dwStyle = GetStyle();
if (dwStyle & WS_VSCROLL)
lpClientRect->right += afxData.cxVScroll - CX_BORDER;
if (dwStyle & WS_HSCROLL)
lpClientRect->bottom += afxData.cyHScroll - CY_BORDER;
return;
}
::AdjustWindowRectEx(lpClientRect, GetStyle() | WS_BORDER, FALSE,
GetExStyle() & ~(WS_EX_CLIENTEDGE));
}
/////////////////////////////////////////////////////////////////////////////
// CEditView document like functions
void CEditView::DeleteContents()
{
ASSERT_VALID(this);
ASSERT(m_hWnd != NULL);
SetWindowText(NULL);
ASSERT_VALID(this);
}
void CEditView::Serialize(CArchive& ar)
// Read and write CEditView object to archive, with length prefix.
{
ASSERT_VALID(this);
ASSERT(m_hWnd != NULL);
if (ar.IsStoring())
{
UINT nLen = GetBufferLength();
ar << (DWORD)nLen;
WriteToArchive(ar);
}
else
{
DWORD dwLen;
ar >> dwLen;
if (dwLen > nMaxSize)
AfxThrowArchiveException(CArchiveException::badIndex);
UINT nLen = (UINT)dwLen;
ReadFromArchive(ar, nLen);
}
ASSERT_VALID(this);
}
void CEditView::ReadFromArchive(CArchive& ar, UINT nLen)
// Read certain amount of text from the file, assume at least nLen
// characters (not bytes) are in the file.
{
ASSERT_VALID(this);
LPVOID hText = LocalAlloc(LMEM_MOVEABLE, (nLen+1)*sizeof(TCHAR));
if (hText == NULL)
AfxThrowMemoryException();
LPTSTR lpszText = (LPTSTR)LocalLock(hText);
ASSERT(lpszText != NULL);
if (ar.Read(lpszText, nLen*sizeof(TCHAR)) != nLen*sizeof(TCHAR))
{
LocalUnlock(hText);
LocalFree(hText);
AfxThrowArchiveException(CArchiveException::endOfFile);
}
// Replace the editing edit buffer with the newly loaded data
lpszText[nLen] = '\0';
#ifndef _UNICODE
if (afxData.bWin95)
{
// set the text with SetWindowText, then free
BOOL bResult = ::SetWindowText(m_hWnd, lpszText);
LocalUnlock(hText);
LocalFree(hText);
// make sure that SetWindowText was successful
if (!bResult || ::GetWindowTextLength(m_hWnd) < (int)nLen)
AfxThrowMemoryException();
// remove old shadow buffer
delete[] m_pShadowBuffer;
m_pShadowBuffer = NULL;
m_nShadowSize = 0;
ASSERT_VALID(this);
return;
}
#endif
LocalUnlock(hText);
HLOCAL hOldText = GetEditCtrl().GetHandle();
ASSERT(hOldText != NULL);
LocalFree(hOldText);
GetEditCtrl().SetHandle((HLOCAL)(UINT)(DWORD)hText);
Invalidate();
ASSERT_VALID(this);
}
void CEditView::WriteToArchive(CArchive& ar)
// Write just the text to an archive, no length prefix.
{
ASSERT_VALID(this);
LPCTSTR lpszText = LockBuffer();
ASSERT(lpszText != NULL);
UINT nLen = GetBufferLength();
TRY
{
ar.Write(lpszText, nLen*sizeof(TCHAR));
}
CATCH_ALL(e)
{
UnlockBuffer();
THROW_LAST();
}
END_CATCH_ALL
UnlockBuffer();
ASSERT_VALID(this);
}
void CEditView::SerializeRaw(CArchive& ar)
// Read/Write object as stand-alone file.
{
ASSERT_VALID(this);
if (ar.IsStoring())
{
WriteToArchive(ar);
}
else
{
CFile* pFile = ar.GetFile();
ASSERT(pFile->GetPosition() == 0);
DWORD nFileSize = pFile->GetLength();
if (nFileSize/sizeof(TCHAR) > nMaxSize)
{
AfxMessageBox(AFX_IDP_FILE_TOO_LARGE);
AfxThrowUserException();
}
// ReadFromArchive takes the number of characters as argument
ReadFromArchive(ar, (UINT)nFileSize/sizeof(TCHAR));
}
ASSERT_VALID(this);
}
/////////////////////////////////////////////////////////////////////////////
// CEditView Printing Helpers
AFX_STATIC UINT AFXAPI _AfxEndOfLine(LPCTSTR lpszText, UINT nLen, UINT nIndex)
{
ASSERT(AfxIsValidAddress(lpszText, nLen, FALSE));
LPCTSTR lpsz = lpszText + nIndex;
LPCTSTR lpszStop = lpszText + nLen;
while (lpsz < lpszStop && *lpsz != '\r')
++lpsz;
return lpsz - lpszText;
}
AFX_STATIC UINT AFXAPI _AfxNextLine(LPCTSTR lpszText, UINT nLen, UINT nIndex)
{
ASSERT(AfxIsValidAddress(lpszText, nLen, FALSE));
LPCTSTR lpsz = lpszText + nIndex;
LPCTSTR lpszStop = lpszText + nLen;
while (lpsz < lpszStop && *lpsz == '\r')
++lpsz;
if (lpsz < lpszStop && *lpsz == '\n')
++lpsz;
return lpsz - lpszText;
}
AFX_STATIC UINT AFXAPI
_AfxClipLine(CDC* pDC, int aCharWidths[256], int cxLine, int nTabStop,
LPCTSTR lpszText, UINT nIndex, UINT nIndexEnd)
{
ASSERT_VALID(pDC);
ASSERT(nIndex < nIndexEnd);
ASSERT(AfxIsValidAddress(lpszText, nIndexEnd, FALSE));
TEXTMETRIC tm;
::GetTextMetrics(pDC->m_hDC, &tm);
// make an initial guess on the number of characters that will fit
int cx = 0;
LPCTSTR lpszStart = lpszText + nIndex;
LPCTSTR lpszStop = lpszText + nIndexEnd;
LPCTSTR lpsz = lpszStart;
while (lpsz < lpszStop)
{
if (*lpsz == '\t')
cx += nTabStop - (cx % nTabStop);
else
{
#ifdef _UNICODE
if (*lpsz <= 0xFF)
cx += aCharWidths[(BYTE)*lpsz];
else
cx += tm.tmAveCharWidth;
#else //_UNICODE
if (_afxDBCS && _istlead(*lpsz))
{
++lpsz;
cx += tm.tmAveCharWidth;
}
else
cx += aCharWidths[(BYTE)*lpsz];
#endif //!_UNICODE
}
++lpsz;
if (cx > cxLine)
break;
}
// adjust for errors in the guess
cx = pDC->GetTabbedTextExtent(lpszStart, lpsz-lpszStart, 1, &nTabStop).cx;
if (cx > cxLine)
{
// remove characters until it fits
do
{
ASSERT(lpsz != lpszStart);
if (_afxDBCS)
lpsz = _tcsdec(lpszStart, lpsz);
else
--lpsz;
cx = pDC->GetTabbedTextExtent(lpszStart, lpsz-lpszStart, 1, &nTabStop).cx;
} while (cx > cxLine);
}
else if (cx < cxLine)
{
// add characters until it doesn't fit
while (lpsz < lpszStop)
{
lpsz = _tcsinc(lpsz);
ASSERT(lpsz <= lpszStop);
cx = pDC->GetTabbedTextExtent(lpszStart, lpsz-lpszStart, 1, &nTabStop).cx;
if (cx > cxLine)
{
if (_afxDBCS)
lpsz = _tcsdec(lpszStart, lpsz);
else
--lpsz;
break;
}
}
}
// return index of character just past the last that would fit
return lpsz - lpszText;
}
/////////////////////////////////////////////////////////////////////////////
// CEditView Printing support
BOOL CEditView::OnPreparePrinting(CPrintInfo* pInfo)
{
return DoPreparePrinting(pInfo);
}
void CEditView::OnBeginPrinting(CDC* pDC, CPrintInfo*)
{
ASSERT_VALID(this);
ASSERT_VALID(pDC);
// initialize page start vector
ASSERT(m_aPageStart.GetSize() == 0);
m_aPageStart.Add(0);
ASSERT(m_aPageStart.GetSize() > 0);
if (m_hPrinterFont == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -