📄 viewrich.cpp
字号:
CRichEditCntrItem* pItem = NULL;
CReObject reo;
HRESULT hr = m_lpRichEditOle->GetObject(REO_IOB_SELECTION, &reo,
REO_GETOBJ_ALL_INTERFACES);
//reo's interfaces are all in UNICODE
if (GetScode(hr) == S_OK)
{
pItem = pDoc->LookupItem(reo.poleobj);
if (pItem == NULL)
pItem = pDoc->CreateClientItem(&reo);
ASSERT(pItem != NULL);
}
return pItem;
}
CRichEditCntrItem* CRichEditView::GetInPlaceActiveItem() const
{
ASSERT(m_lpRichEditOle != NULL);
CRichEditDoc* pDoc = GetDocument();
CRichEditCntrItem* pItem = NULL;
CReObject reo;
HRESULT hr = m_lpRichEditOle->GetObject(REO_IOB_SELECTION, &reo,
REO_GETOBJ_ALL_INTERFACES);
//reo's interfaces are all in UNICODE
if (GetScode(hr) == S_OK && (reo.dwFlags & REO_INPLACEACTIVE))
{
pItem = pDoc->LookupItem(reo.poleobj);
if (pItem == NULL)
pItem = pDoc->CreateClientItem(&reo);
ASSERT(pItem != NULL);
}
return pItem;
}
/////////////////////////////////////////////////////////////////////////////
// CRichEditView operations
HRESULT CRichEditView::InsertItem(CRichEditCntrItem* pItem)
{
ASSERT(m_lpRichEditOle != NULL);
CReObject reo(pItem);
reo.cp = REO_CP_SELECTION;
HRESULT hr = m_lpRichEditOle->InsertObject(&reo);
CHARRANGE cr;
GetRichEditCtrl().GetSel(cr);
cr.cpMin = cr.cpMax -1;
GetRichEditCtrl().SetSel(cr);
return hr;
}
void CRichEditView::InsertFileAsObject(LPCTSTR lpszFileName)
{
CString str = lpszFileName;
CWaitCursor wait;
CRichEditCntrItem* pItem = NULL;
TRY
{
// create item from dialog results
pItem = GetDocument()->CreateClientItem();
pItem->m_bLock = TRUE;
if (!pItem->CreateFromFile(str))
AfxThrowMemoryException(); // any exception will do
pItem->UpdateLink();
InsertItem(pItem);
pItem->m_bLock = FALSE;
}
CATCH(CException, e)
{
if (pItem != NULL)
{
pItem->m_bLock = FALSE;
ASSERT_VALID(pItem);
pItem->Delete();
}
}
END_CATCH
}
void CRichEditView::DoPaste(COleDataObject& dataobj, CLIPFORMAT cf, HMETAFILEPICT hMetaPict)
{
CWaitCursor wait;
CRichEditCntrItem* pItem = NULL;
TRY
{
// create item from dialog results
pItem = GetDocument()->CreateClientItem();
pItem->m_bLock = TRUE;
if (m_nPasteType == COlePasteSpecialDialog::pasteLink) // paste link
{
if (!pItem->CreateLinkFromData(&dataobj))
AfxThrowMemoryException(); // any exception will do
}
else if (m_nPasteType == COlePasteSpecialDialog::pasteNormal)
{
if (!pItem->CreateFromData(&dataobj))
AfxThrowMemoryException(); // any exception will do
}
else if (m_nPasteType == COlePasteSpecialDialog::pasteStatic)
{
if (!pItem->CreateStaticFromData(&dataobj))
AfxThrowMemoryException(); // any exception will do
}
else
{
// paste embedded
if (!pItem->CreateFromData(&dataobj) &&
!pItem->CreateStaticFromData(&dataobj))
{
AfxThrowMemoryException(); // any exception will do
}
}
if (cf == 0)
{
// copy the current iconic representation
FORMATETC fmtetc;
fmtetc.cfFormat = CF_METAFILEPICT;
fmtetc.dwAspect = DVASPECT_ICON;
fmtetc.ptd = NULL;
fmtetc.tymed = TYMED_MFPICT;
fmtetc.lindex = 1;
HGLOBAL hObj = dataobj.GetGlobalData(CF_METAFILEPICT, &fmtetc);
if (hObj != NULL)
{
pItem->SetIconicMetafile(hObj);
// the following code is an easy way to free a metafile pict
STGMEDIUM stgMed;
memset(&stgMed, 0, sizeof(stgMed));
stgMed.tymed = TYMED_MFPICT;
stgMed.hGlobal = hObj;
ReleaseStgMedium(&stgMed);
}
// set the current drawing aspect
hObj = dataobj.GetGlobalData((CLIPFORMAT)_oleData.cfObjectDescriptor);
if (hObj != NULL)
{
ASSERT(hObj != NULL);
// got CF_OBJECTDESCRIPTOR ok. Lock it down and extract size.
LPOBJECTDESCRIPTOR pObjDesc = (LPOBJECTDESCRIPTOR)GlobalLock(hObj);
ASSERT(pObjDesc != NULL);
((COleClientItem*)pItem)->SetDrawAspect((DVASPECT)pObjDesc->dwDrawAspect);
GlobalUnlock(hObj);
GlobalFree(hObj);
}
}
else
{
if (hMetaPict != NULL)
{
pItem->SetIconicMetafile(hMetaPict);
((COleClientItem*)pItem)->SetDrawAspect(DVASPECT_ICON);
}
else
((COleClientItem*)pItem)->SetDrawAspect(DVASPECT_CONTENT);
}
HRESULT hr = InsertItem(pItem);
pItem->UpdateItemType();
pItem->m_bLock = FALSE;
if (hr != NOERROR)
AfxThrowOleException(hr);
}
CATCH(CException, e)
{
if (pItem != NULL)
{
pItem->m_bLock = FALSE;
ASSERT_VALID(pItem);
pItem->Delete();
}
}
END_CATCH
}
/////////////////////////////////////////////////////////////////////////////
// CRichEditView virtuals
void CRichEditView::OnPrinterChanged(const CDC& dcPrinter)
{
// this is typically called by the view when it gets a WM_DEVMODECHANGE
// also called during page setup
CSize size;
if (dcPrinter.m_hDC != NULL)
{
// this will fill in the page size
size.cx = MulDiv(dcPrinter.GetDeviceCaps(PHYSICALWIDTH), 1440,
dcPrinter.GetDeviceCaps(LOGPIXELSX));
size.cy = MulDiv(dcPrinter.GetDeviceCaps(PHYSICALHEIGHT), 1440,
dcPrinter.GetDeviceCaps(LOGPIXELSY));
}
else
size = CSize(8*1440+720, 11*1440); // 8.5" by 11"
if (GetPaperSize() != size)
{
SetPaperSize(size);
if (m_nWordWrap == WrapToTargetDevice) //wrap to ruler
WrapChanged();
}
}
BOOL CRichEditView::OnPasteNativeObject(LPSTORAGE)
{
// use this function to pull out native data from an embedded object
// one would typically do this by create a COleStreamFile and attaching it
// to an archive
return FALSE;
}
HMENU CRichEditView::GetContextMenu(WORD, LPOLEOBJECT, CHARRANGE* )
{
return NULL;
}
HRESULT CRichEditView::GetClipboardData(CHARRANGE* /*lpchrg*/, DWORD /*reco*/,
LPDATAOBJECT /*lpRichDataObj*/, LPDATAOBJECT* /*lplpdataobj*/)
{
return E_NOTIMPL;
}
HRESULT CRichEditView::QueryAcceptData(LPDATAOBJECT lpdataobj,
CLIPFORMAT* lpcfFormat, DWORD /*dwReco*/, BOOL bReally, HGLOBAL hMetaPict)
{
ASSERT(lpcfFormat != NULL);
if (!bReally) // not actually pasting
return S_OK;
// if direct pasting a particular native format allow it
if (IsRichEditFormat(*lpcfFormat))
return S_OK;
COleDataObject dataobj;
dataobj.Attach(lpdataobj, FALSE);
// if format is 0, then force particular formats if available
if (*lpcfFormat == 0 && (m_nPasteType == 0))
{
if (dataobj.IsDataAvailable((CLIPFORMAT)_oleData.cfRichTextAndObjects)) // native avail, let richedit do as it wants
return S_OK;
else if (dataobj.IsDataAvailable((CLIPFORMAT)_oleData.cfRichTextFormat))
{
*lpcfFormat = (CLIPFORMAT)_oleData.cfRichTextFormat;
return S_OK;
}
else if (dataobj.IsDataAvailable(CF_TEXT))
{
*lpcfFormat = CF_TEXT;
return S_OK;
}
}
// paste OLE formats
DoPaste(dataobj, *lpcfFormat, hMetaPict);
return S_FALSE;
}
HRESULT CRichEditView::GetWindowContext(LPOLEINPLACEFRAME* lplpFrame,
LPOLEINPLACEUIWINDOW* lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo)
{
CRichEditCntrItem* pItem = GetSelectedItem();
if (pItem == NULL)
return E_FAIL;
pItem->m_pView = this;
HRESULT hr = pItem->GetWindowContext(lplpFrame, lplpDoc, lpFrameInfo);
pItem->m_pView = NULL;
return hr;
}
HRESULT CRichEditView::ShowContainerUI(BOOL b)
{
CRichEditCntrItem* pItem = GetSelectedItem();
if (pItem == NULL)
return E_FAIL;
if (b)
pItem->m_pView = this;
HRESULT hr = pItem->ShowContainerUI(b);
if (FAILED(hr) || !b)
pItem->m_pView = NULL;
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// CRichEditView Find & Replace
void CRichEditView::AdjustDialogPosition(CDialog* pDlg)
{
ASSERT(pDlg != NULL);
long lStart, lEnd;
GetRichEditCtrl().GetSel(lStart, lEnd);
CPoint point = GetRichEditCtrl().GetCharPos(lStart);
ClientToScreen(&point);
CRect rectDlg;
pDlg->GetWindowRect(&rectDlg);
if (rectDlg.PtInRect(point))
{
if (point.y > rectDlg.Height())
rectDlg.OffsetRect(0, point.y - rectDlg.bottom - 20);
else
{
int nVertExt = GetSystemMetrics(SM_CYSCREEN);
if (point.y + rectDlg.Height() < nVertExt)
rectDlg.OffsetRect(0, 40 + point.y - rectDlg.top);
}
pDlg->MoveWindow(&rectDlg);
}
}
void CRichEditView::OnEditFindReplace(BOOL bFindOnly)
{
ASSERT_VALID(this);
m_bFirstSearch = TRUE;
_AFX_RICHEDIT_STATE* pEditState = _afxRichEditState;
if (pEditState->pFindReplaceDlg != NULL)
{
if (pEditState->bFindOnly == bFindOnly)
{
pEditState->pFindReplaceDlg->SetActiveWindow();
pEditState->pFindReplaceDlg->ShowWindow(SW_SHOW);
return;
}
else
{
ASSERT(pEditState->bFindOnly != bFindOnly);
pEditState->pFindReplaceDlg->SendMessage(WM_CLOSE);
ASSERT(pEditState->pFindReplaceDlg == NULL);
ASSERT_VALID(this);
}
}
CString strFind = GetRichEditCtrl().GetSelText();
// if selection is empty or spans multiple lines use old find text
if (strFind.IsEmpty() || (strFind.FindOneOf(_T("\n\r")) != -1))
strFind = pEditState->strFind;
CString strReplace = pEditState->strReplace;
pEditState->pFindReplaceDlg = new CFindReplaceDialog;
ASSERT(pEditState->pFindReplaceDlg != NULL);
DWORD dwFlags = NULL;
if (pEditState->bNext)
dwFlags |= FR_DOWN;
if (pEditState->bCase)
dwFlags |= FR_MATCHCASE;
if (pEditState->bWord)
dwFlags |= FR_WHOLEWORD;
// hide stuff that RichEdit doesn't support
dwFlags |= FR_HIDEUPDOWN;
if (!pEditState->pFindReplaceDlg->Create(bFindOnly, strFind,
strReplace, dwFlags, this))
{
pEditState->pFindReplaceDlg = NULL;
ASSERT_VALID(this);
return;
}
ASSERT(pEditState->pFindReplaceDlg != NULL);
pEditState->bFindOnly = bFindOnly;
pEditState->pFindReplaceDlg->SetActiveWindow();
pEditState->pFindReplaceDlg->ShowWindow(SW_SHOW);
ASSERT_VALID(this);
}
void CRichEditView::OnFindNext(LPCTSTR lpszFind, BOOL bNext, BOOL bCase, BOOL bWord)
{
ASSERT_VALID(this);
_AFX_RICHEDIT_STATE* pEditState = _afxRichEditState;
pEditState->strFind = lpszFind;
pEditState->bCase = bCase;
pEditState->bWord = bWord;
pEditState->bNext = bNext;
if (!FindText(pEditState))
TextNotFound(pEditState->strFind);
else
AdjustDialogPosition(pEditState->pFindReplaceDlg);
ASSERT_VALID(this);
}
void CRichEditView::OnReplaceSel(LPCTSTR lpszFind, BOOL bNext, BOOL bCase,
BOOL bWord, LPCTSTR lpszReplace)
{
ASSERT_VALID(this);
_AFX_RICHEDIT_STATE* pEditState = _afxRichEditState;
pEditState->strFind = lpszFind;
pEditState->strReplace = lpszReplace;
pEditState->bCase = bCase;
pEditState->bWord = bWord;
pEditState->bNext = bNext;
if (!SameAsSelected(pEditState->strFind, pEditState->bCase, pEditState->bWord))
{
if (!FindText(pEditState))
TextNotFound(pEditState->strFind);
else
AdjustDialogPosition(pEditState->pFindReplaceDlg);
return;
}
GetRichEditCtrl().ReplaceSel(pEditState->strReplace);
if (!FindText(pEditState))
TextNotFound(pEditState->strFind);
else
AdjustDialogPosition(pEditState->pFindReplaceDlg);
ASSERT_VALID(this);
}
void CRichEditView::OnReplaceAll(LPCTSTR lpszFind, LPCTSTR lpszReplace, BOOL bCase, BOOL bWord)
{
ASSERT_VALID(this);
_AFX_RICHEDIT_STATE* pEditState = _afxRichEditState;
pEditState->strFind = lpszFind;
pEditState->strReplace = lpszReplace;
pEditState->bCase = bCase;
pEditState->bWord = bWord;
pEditState->bNext = TRUE;
CWaitCursor wait;
// no selection or different than what looking for
if (!SameAsSelected(pEditState->strFind, pEditState->bCase, pEditState->bWord))
{
if (!FindText(pEditState))
{
TextNotFound(pEditState->strFind);
return;
}
}
GetRichEditCtrl().HideSelection(TRUE, FALSE);
do
{
GetRichEditCtrl().ReplaceSel(pEditState->strReplace);
} while (FindTextSimple(pEditState));
TextNotFound(pEditState->strFind);
GetRichEditCtrl().HideSelection(FALSE, FALSE);
ASSERT_VALID(this);
}
LRESULT CRichEditView::OnFindReplaceCmd(WPARAM, LPARAM lParam)
{
ASSERT_VALID(this);
CFindReplaceDialog* pDialog = CFindReplaceDialog::GetNotifier(lParam);
ASSERT(pDialog != NULL);
_AFX_RICHEDIT_STATE* pEditState = _afxRichEditState;
ASSERT(pDialog == pEditState->pFindReplaceDlg);
if (pDialog->IsTerminating())
pEditState->pFindReplaceDlg = NULL;
else if (pDialog->FindNext())
{
OnFindNext(pDialog->GetFindString(), pDialog->SearchDown(),
pDialog->MatchCase(), pDialog->MatchWholeWord());
}
else if (pDialog->ReplaceCurrent())
{
ASSERT(!pEditState->bFindOnly);
OnReplaceSel(pDialog->GetFindString(),
pDialog->SearchDown(), pDialog->MatchCase(), pDialog->MatchWholeWord(),
pDialog->GetReplaceString());
}
else if (pDialog->ReplaceAll())
{
ASSERT(!pEditState->bFindOnly);
OnReplaceAll(pDialog->GetFindString(), pDialog->GetReplaceString(),
pDialog->MatchCase(), pDialog->MatchWholeWord());
}
ASSERT_VALID(this);
return 0;
}
BOOL CRichEditView::SameAsSelected(LPCTSTR lpszCompare, BOOL bCase, BOOL /*bWord*/)
{
// check length first
size_t nLen = lstrlen(lpszCompare);
long lStartChar, lEndChar;
GetRichEditCtrl().GetSel(lStartChar, lEndChar);
if (nLen != (size_t)(lEndChar - lStartChar))
return FALSE;
// length is the same, check contents
CString strSelect = GetRichEditCtrl().GetSelText();
return (bCase && lstrcmp(lpszCompare, strSelect) == 0) ||
(!bCase && lstrcmpi(lpszCompare, strSelect) == 0);
}
BOOL CRichEditView::FindText(_AFX_RICHEDIT_STATE* pEditState)
{
ASSERT(pEditState != NULL);
return FindText(pEditState->strFind, pEditState->bCase, pEditState->bWord);
}
BOOL CRichEditView::FindText(LPCTSTR lpszFind, BOOL bCase, BOOL bWord)
{
ASSERT_VALID(this);
CWaitCursor wait;
return FindTextSimple(lpszFind, bCase, bWord);
}
BOOL CRichEditView::FindTextSimple(_AFX_RICHEDIT_STATE* pEditState)
{
ASSERT(pEditState != NULL);
return FindTextSimple(pEditState->strFind, pEditState->bCase, pEditState->bWord);
}
BOOL CRichEditView::FindTextSimple(LPCTSTR lpszFind, BOOL bCase, BOOL bWord)
{
USES_CONVERSION;
ASSERT(lpszFind != NULL);
FINDTEXTEX ft;
GetRichEditCtrl().GetSel(ft.chrg);
if (m_bFirstSearch)
{
m_lInitialSearchPos = ft.chrg.cpMin;
m_bFirstSearch = FALSE;
}
ft.lpstrText = T2A((LPTSTR)lpszFind);
if (ft.chrg.cpMin != ft.chrg.cpMax) // i.e. there is a selection
{
#ifndef _UNICODE
// If byte at beginning of selection is a DBCS lead byte,
// increment by one extra byte.
TEXTRANGE textRange;
TCHAR ch[2];
textRange.chrg.cpMin = ft.chrg.cpMin;
textRange.chrg.cpMax = ft.chrg.cpMin + 1;
textRange.lpstrText = ch;
GetRichEditCtrl().SendMessage(EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
if (_istlead(ch[0]))
{
ASSERT(ft.chrg.cpMax - ft.chrg.cpMin >= 2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -