📄 dispsl.cpp
字号:
RECT rcView;
if(pHit)
*pHit = HT_Nothing;
GetViewRect(rcView, prcClient);
// Create measurer at cp(0)
CMeasurer me(this);
// Get character in the line
cch = CLine::CchFromXpos(me, pt.x + _xScroll - rcView.left, &dx, pHit);
if(pt.x > rcView.right && pHit)
*pHit = HT_Nothing;
// Don't allow click at EOL to select EOL marker and take into account
// single line edits as well
if(!fAllowEOL && cch == (LONG)CLine::_cch && CLine::_cchEOP)
me._rpTX.BackupCpCRLF();
if(ptp)
ptp->SetCp(me.GetCp());
if(prp)
prp->RpSet(0, cch);
return me.GetCp();
}
/*
* CDisplaySL::PointFromTp(tp, fAtEnd, pt, prp)
*
* @mfunc
* Determine coordinates at given tp
*
* @devnote
* --- Use when in-place active only ---
*
* @rdesc
* line index at cp, -1 if error
*/
LONG CDisplaySL::PointFromTp(
const CRchTxtPtr &tp, //@parm Text ptr to get coordinates at
const RECT *prcClient, //@parm Client rectangle (can be NULL if active).
BOOL fAtEnd, //@parm Return end of previous line for ambiguous cp
POINT &pt, //@parm Returns point at cp in client coords
CLinePtr * const prp, //@parm Returns line pointer at tp (may be null)
UINT taMode) //@parm Text Align mode: top, baseline, bottom
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::PointFromTp");
CLinePtr rp(this);
RECT rcView;
LONG yHeight;
LONG yDescent;
const CCharFormat *pcf;
HDC hdc;
CCcs *pccs;
if(!rp.RpSetCp(tp.GetCp(), fAtEnd))
return -1;
AssertSz(_ped->_fInPlaceActive || (prcClient != NULL),
"CDisplaySL::PointFromTp() called with invalid client rect");
GetViewRect(rcView, prcClient);
pt.y = 0;
pt.x = rp.IsValid() ? rp->_xLeft : 0;
if (rp.RpGetIch())
{
CMeasurer me(this, tp);
// Backup to start of line
me.Advance(-rp.RpGetIch());
// And measure from there to where we are
me.NewLine(*rp);
pt.x += me.MeasureText(rp.RpGetIch());
}
pt.x += rcView.left - _xScroll;
pt.y += rcView.top;
if (prp)
*prp = rp;
if(taMode != TA_TOP)
{
if (taMode & TA_BOTTOM)
{
// Assume line has something useful
yHeight = CLine::_yHeight;
yDescent = CLine::_yDescent;
if (yHeight == -1)
{
// Control has no height use the default char format
// to return something useful.
// Control s/b empty at this point because we will
// always request that the view be updated for a control
// with data which will in turn cause the control to be
// measured.
AssertSz(!_ped->_fRich,
"CDisplaySL::PointFromTp height -1 on rich edit control");
// Get defaut character format
if( (pcf = _ped->GetCharFormat(-1)) != NULL)
{
// Get the DC
hdc = GetDC();
if(hdc != NULL)
{
// Get the default char format
pccs = fc().GetCcs(hdc, pcf, GetZoomNumerator(),
GetZoomDenominator(),
GetDeviceCaps(hdc, LOGPIXELSY));
if(pccs != NULL)
{
// Use data in default char format
yDescent = pccs->_yDescent;
yHeight = pccs->_yHeight;
pccs->Release();
}
ReleaseDC(hdc);
}
}
}
// Height of -1 at this point means an error occurred
if (yHeight != -1)
{
pt.y += yHeight;
if((taMode & TA_BASELINE) == TA_BASELINE)
{
pt.y -= yDescent;
}
}
}
// Do any specical horizontal calculation
if (taMode & TA_CENTER)
{
pt.x += ModeOffsetIntoChar(taMode, tp);
}
}
return rp;
}
/*
* CDisplaySL::UpdateView(&tpFirst, cchOld, cchNew)
*
* @mfunc
* Update visible part of display (the "view" on the screen).
*
* @devnote
* --- Use when in-place active only ---
*
* @rdesc
* TRUE if success
*/
BOOL CDisplaySL::UpdateView(
const CRchTxtPtr &tpFirst, //@parm Text ptr where change happened
LONG cchOld, //@parm Count of chars deleted
LONG cchNew) //@parm Count of chars inserted
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::UpdateView");
BOOL fUpdateScrollBarHorz = FALSE;
BOOL fReturn = TRUE;
RECT rcView;
CTxtSelection *psel = _ped->GetSelNC();
LONG xWidthOld = _xWidth + _xLineOverhang;
BOOL fScrollChanged = FALSE;
BOOL fRestoreCaret = FALSE;
RECT rcClient;
RECT rc;
LONG yHeightOld = _yHeight;
if (_fNoUpdateView)
return fReturn;
AssertSz(_ped->_fInPlaceActive, "CDisplaySL::UpdateView(...) called when inactive");
_ped->TxGetClientRect(&rcClient);
GetViewRect(rcView, &rcClient);
if(psel && !psel->PuttingChar())
psel->ClearCchPending();
if(!RecalcLine())
{
// the recalc failed
// let's try to get out of this with our head still mostly attached
fReturn = FALSE;
}
// An update has occurred. If it isn't already off screen make it
// off screen so that there is no flicker.
if ((_bFlags & fliUseOffScreenDC) == 0)
{
_bFlags |= (fliUseOffScreenDC | fliOffScreenOnce);
}
if(_xWidth <= _xWidthView)
{
// x scroll range is smaller than the view width
// force x scrolling position = 0
_xScroll = 0;
SetCpFirstVisible(0);
_fViewChanged = TRUE;
fUpdateScrollBarHorz = TRUE;
}
_fRectInvalid = TRUE;
// We will only resize a Single Line edit control if the width has changed.
if ((_xWidth + _xLineOverhang) != xWidthOld)
{
if(FAILED(RequestResize()))
{
_ped->GetCallMgr()->SetOutOfMemory();
}
}
// if the view changed update the scroll bars
if(_fViewChanged)
{
_fViewChanged = FALSE;
fScrollChanged = UpdateScrollBar(SB_HORZ);
}
if (!fScrollChanged)
{
// Scroll bar state did not change so we
// need to update the screen.
// Build an invalidation rectangle.
rc = rcClient;
if (yHeightOld == _yHeight)
{
// Height of control did not change so we can minimize the update
// rectangle to the height of the control.
rc.bottom = rcView.top + _yHeight;
}
// Tell the display to update when it gets a chance
_ped->TxInvalidateRect(&rc, FALSE);
}
return fReturn;
}
/*
* CDisplaySL::ScrollView(xScroll, yScroll, fTracking)
*
* @mfunc
* Scroll view to new x and y position
*
* @devnote
* This method tries to adjust the y scroll pos before
* scrolling to display complete line at top. x scroll
* pos is adjusted to avoid scrolling all text off the
* view rectangle.
*
* Must be able to handle yScroll <gt> pdp->yHeight and yScroll <lt> 0
*
* @rdesc
* TRUE if actual scrolling occurred,
* FALSE if no change
*/
BOOL CDisplaySL::ScrollView (
LONG xScroll, //@parm New x scroll position
LONG yScroll, //@parm New y scroll position
BOOL fTracking, //@parm TRUE indicates we are tracking scrollbar thumb
BOOL fFractionalScroll)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::ScrollView");
// (don't update the scrollbar pos)
BOOL fTryAgain = TRUE;
RECT rcUpdate; // ??? we may want use a region here but ScrollView is
// rarely called with both a xScroll and yScroll value.
LONG xWidthMax;
LONG dx = 0;
RECT rcView;
CTxtSelection *psel = _ped->GetSelNC();
COleObject *pipo;
AssertSz(_ped->_fInPlaceActive, "CDisplaySL::ScrollView() called when not in-place");
if (xScroll == -1)
return FALSE;
GetViewRect(rcView);
// Determine horizontal scrolling pos.
xWidthMax = _xWidth;
xScroll = min(xScroll, xWidthMax);
xScroll = max(0, xScroll);
dx = _xScroll - xScroll;
if(dx)
{
_xScroll = xScroll;
// Calculate the new first visible
// Create measurer at cp(0)
CMeasurer me(this);
// Initialize the measurer.
me.NewLine(TRUE);
// Measure the scroll width
me.Measure(xScroll, _cch,
MEASURE_BREAKATWIDTH | MEASURE_FIRSTINPARA);
// Save the character position
SetCpFirstVisible(me.GetCp());
}
AssertSz(IsMain(), "CDisplaySL::ScrollView non-main SL control");
// Now perform the actual scrolling
if(dx)
{
if (!_fRectInvalid)
{
// Scroll only if scrolling < view dimensions and we are in-place
// Note that we only scroll the active view and we can be in-place
// active and have multiple inactive views.
if(IsActive() && !_ped->_fTransparent && dx < _xWidthView)
{
if(psel)
psel->ShowCaret(FALSE);
_ped->TxScrollWindowEx((INT) dx, 0, NULL, &rcView,
NULL, &rcUpdate, 0);
_ped->TxInvalidateRect(&rcUpdate, FALSE);
if(psel)
psel->ShowCaret(TRUE);
}
else
{
_ped->TxInvalidateRect(&rcView, FALSE);
}
}
if (psel)
psel->UpdateCaret(FALSE);
if(!fTracking && dx)
{
_ped->SendScrollEvent(EN_HSCROLL);
UpdateScrollBar(SB_HORZ);
}
_ped->TxUpdateWindow();
// FUTURE: since we're now repositioning in place active
// objects every time we draw, this call seems to be
// superfluous (AndreiB)
// Tell object subsystem to reposition any in place objects
if( _ped->GetObjectCount() )
{
pipo = _ped->GetObjectMgr()->GetInPlaceActiveObject();
if (NULL != pipo)
{
pipo->OnReposition( dx, 0 );
}
}
}
return dx;
}
/*
* CDisplaySL::InvertRange(cp, cch)
*
* @mfunc
* Invert a given range on screen (for selection)
*
* @devnote
* --- Use when in-place active only ---
*
* @rdesc
* TRUE if success
*/
BOOL CDisplaySL::InvertRange (
LONG cp, //@parm Active end of range to invert
LONG cch, //@parm Signed length of range
SELDISPLAYACTION selAction ) //@parm What we are doing to the selection
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::InvertRange");
RECT rcView;
RECT rc;
if( _padc )
{
return TRUE;
}
// Ensure all visible lines are recalced
if (!WaitForRecalcView ())
return FALSE;
// If an object is being inverted, and that is all that
// is being inverted, delegate to the ObjectMgr.
if( cch == 1 && _ped->GetObjectCount() &&
(selAction == selSetNormal || selAction == selSetHiLite) )
{
CObjectMgr* pobjmgr = _ped->GetObjectMgr();
LONG cpMin = cch < 0 ? cp : cp - cch;
CTxtPtr tp(_ped, cpMin);
if(tp.GetChar() == WCH_EMBEDDING)
{
if (pobjmgr)
{
pobjmgr->HandleSingleSelect(_ped, cpMin, selAction == selSetHiLite);
}
}
}
// Get view rectangle
AssertSz(_ped->_fInPlaceActive, "CDisplaySL::InvertRange() called when not in-place active");
_ped->TxGetClientRect(&rc);
GetViewRect(rcView, &rc);
_ped->TxInvalidateRect(NULL, FALSE);
return TRUE;
}
/*
* CDisplaySL::InitLinePtr ( CLinePtr & plp )
*
* @mfunc
* Initialize a CLinePtr properly
*/
void CDisplaySL::InitLinePtr (
CLinePtr & lp ) //@parm Ptr to line to initialize
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::InitLinePtr");
lp.Init( * this );
}
/*
* CDisplaySL::GetNaturalSize(hdcDraw, hicTarget, dwMode, pwidth, pheight)
*
* @mfunc
* Recalculate display to input width & height
*
*
* @rdesc
* S_OK - Call completed successfully <nl>
*
*/
HRESULT CDisplaySL::GetNaturalSize(
HDC hdcDraw, //@parm DC for drawing
HDC hicTarget, //@parm DC for information
DWORD dwMode, //@parm Type of natural size required
LONG *pwidth, //@parm On input
LONG *pheight) //@parm
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::GetNaturalSize");
// Assume this won't work
HRESULT hr = E_FAIL;
// Set the height temporarily so the zoom factor will work out
LONG yOrigHeightClient = SetClientHeight(*pheight);
// Adjust the height and width by the view inset
LONG widthView = *pwidth;
LONG heightView = *pheight;
GetViewDim(widthView, heightView);
// Store the adjustment so we can restore it to the height & width
LONG widthAdj = *pwidth - widthView;
LONG heightAdj = *pheight - heightView;
// Recalculate the size needed.
// Create a measurer starting at cp = 0
CMeasurer me(this);
CLine liNew;
me.NewLine(TRUE);
BOOL fMeasured = me.MeasureLine(-1, -1, MEASURE_FIRSTINPARA);
if (fMeasured)
{
liNew = me;
*pwidth = liNew._xWidth + liNew._xLineOverhang;
*pheight = liNew._yHeight;
hr = S_OK;
}
// Restore insets so the output reflects the true client rect needed.
*pwidth += (widthAdj + dxCaret);
*pheight += heightAdj;
// Restore the client height to match the current cache.
SetClientHeight(yOrigHeightClient);
return hr;
}
/*
* CDisplaySL::GetWordWrap()
*
* @mfunc
* Gets the wrap flag
*
* @rdesc
* TRUE - Word wrap
* FALSE - No word Word wrap
*
* @devnote
* Single line controls cannot word wrap.
*/
BOOL CDisplaySL::GetWordWrap() const
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::GetNoWrap");
return FALSE;
}
/*
* CDisplaySL::Clone()
*
* @mfunc
* Make a copy of this object
*
* @rdesc
* NULL - failed
* CDisplay *
*
*/
CDisplay *CDisplaySL::Clone() const
{
CDisplaySL *pdp = new CDisplaySL(_ped);
if (pdp != NULL)
{
// Initialize our base class
if (!pdp->CDisplay::Init())
{
pdp->InitFromDisplay(this);
// Setting scroll to 0 means use the first visible character
pdp->_xScroll = CALC_XSCROLL_FROM_FIRST_VISIBLE;
pdp->_fVScrollEnabled = _fVScrollEnabled;
pdp->_fWordWrap = _fWordWrap;
pdp->ResetDrawInfo(this);
pdp->SetCpFirstVisible(GetFirstVisibleCp());
// This can't be the active view since it is a clone
// of some view.
pdp->SetActiveFlag(FALSE);
}
}
return pdp;
}
/*
* CDisplaySL::GetMaxXScroll()
*
* @mfunc
* Get the maximum x scroll value
*
* @rdesc
* Maximum x scroll value
*
*/
LONG CDisplaySL::GetMaxXScroll() const
{
return _xWidth + dxCaret;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -