📄 disp.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*
* DISP.C
*
* Purpose:
* CDisplay class
*
* Owner:
* Original RichEdit code: David R. Fulmer
* Christian Fortini
* Murray Sargent
* Jon Matousek - smooth scrolling.
*
*/
#include "_common.h"
#include "_disp.h"
#include "_edit.h"
#include "_select.h"
#include "_font.h"
#include "_measure.h"
#include "_ime.h"
#include "_osdc.h"
#include "_dfreeze.h"
ASSERTDATA
// Decimal point precision of smooth scrolling calculations.
#define SMOOTH_PRECISION (100000L)
// =========================== Invariant stuff ======================================================
#define DEBUG_CLASSNAME CDisplay
#include "_invar.h"
#ifdef DEBUG
BOOL
CDisplay::Invariant( void ) const
{
AssertSz(_yHeightView >= 0, "CDisplay::Invariant invalid _yHeightView");
AssertSz(_yHeightClient >= 0,
"CDisplay::Invariant invalid _yHeightClient");
return TRUE;
}
#endif
// Constant used to build the rectangle used for determining if a hit is close
// to the text.
#define HIT_CLOSE_RECT_INC 5
// Auto scroll constants
#define dwAutoScrollUp 1
#define dwAutoScrollDown 2
#define dwAutoScrollLeft 3
#define dwAutoScrollRight 4
// =========================== CLed =====================================================
VOID CLed::SetMax(const CDisplay * const pdp)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CLed::SetMax");
_cpMatchNew = _cpMatchOld = pdp->_ped->GetTextLength();
_iliMatchNew = _iliMatchOld = max(0, pdp->LineCount() - 1);
_yMatchNew = _yMatchOld = pdp->GetHeight();
}
// =========================== CDisplay =====================================================
DWORD CDisplay::_dwTimeScrollNext; // time for next scroll step
DWORD CDisplay::_dwScrollLast; // last scroll action
/*
* CDisplay::ConvertYPosToMax()
*
* @mfunc
* Calculate the real scroll position from the scroll position
*
* @rdesc
* X position from scroll
*
* @devnote
* This routine exists because the thumb position messages
* are limited to 16-bits so we extrapolate when the Y position
* gets greater than that.
*
*/
LONG CDisplay::ConvertScrollToXPos(
LONG xPos) //@parm Scroll position
{
LONG xMax = GetMaxXScroll();
// Has the maximum scroll range exceeded 16-bits?
if (xMax >= _UI16_MAX)
{
// Yes - Extrapolate to the "real" x Positioin
xPos = MulDiv(xPos, xMax, _UI16_MAX);
}
return xPos;
}
/*
* CDisplay::ConvertXPosToScrollPos()
*
* @mfunc
* Calculate the scroll position from the X position in the document.
*
* @rdesc
* Scroll position from X position
*
* @devnote
* This routine exists because the thumb position messages
* are limited to 16-bits so we extrapolate when the Y position
* gets greater than that.
*
*/
LONG CDisplay::ConvertXPosToScrollPos(
LONG xPos) //@parm Y position in document
{
LONG xMax = GetMaxXScroll();
// Has the maximum scroll range exceeded 16-bits?
if (xMax >= _UI16_MAX)
{
// Yes - Extrapolate to the scroll bar position
xPos = MulDiv(xPos, _UI16_MAX, xMax);
}
return xPos;
}
/*
* CDisplay::ConvertYPosToMax(yPos)
*
* @mfunc
* Calculate the real scroll position from the scroll position
*
* @rdesc
* Y position from scroll
*
* @devnote
* This routine exists because the thumb position messages
* are limited to 16-bits so we extrapolate when the Y position
* gets greater than that.
*/
LONG CDisplay::ConvertYPosToScrollPos(
LONG yPos) //@parm Scroll position
{
// Default is single line edit control which cannot have Y-Scroll bars
return 0;
}
CDisplay::CDisplay (CTxtEdit* ped) : CDevDesc (ped)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplay::CDisplay");
_TEST_INVARIANT_
_fRecalcDone = TRUE;
}
CDisplay::~CDisplay()
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplay::~CDisplay");
_TEST_INVARIANT_
CNotifyMgr *pnm = _ped->GetNotifyMgr();
if (pnm != NULL)
{
pnm->Remove(this);
}
CheckRemoveSmoothVScroll();
}
/*
* CDisplay::InitFromDisplay
*
* @mfunc initialize this display from another display instance.
*
* @comment
* copy *only* the members that will remain constant
* between two different display instances. Currently, that
* is only the view variables and device descriptor info.
*/
void CDisplay::InitFromDisplay(const CDisplay *pdp)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplay::InitFromDisplay");
_xWidthView = pdp->_xWidthView;
_yHeightView = pdp->_yHeightView;
_yHeightClient = pdp->_yHeightClient;
// don't save the DC; just the coordinate information.
_xPerInch = pdp->_xPerInch;
_yPerInch = pdp->_yPerInch;
// If the display we are copying from is the active display
// then this new display is the active display.
_fActive = pdp->_fActive;
}
/*
* CDisplay::Init()
*
* @mfunc Initializes CDisplay
*
* @rdesc
* TRUE - initialization succeeded
* FALSE - initalization failed
*/
BOOL CDisplay::Init()
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplay::Init");
BOOL fResult = FALSE;
CNotifyMgr *pnm = _ped->GetNotifyMgr();
if (pnm != NULL)
{
pnm->Add(this);
}
return fResult;
}
/*
* CDisplay::GetSelBarInPixels()
*
* @mfunc
* Helper that returns the size of the selection bar in device units.
*
* @rdesc
* Size of selection bar (is 0 if none).
*
*/
LONG CDisplay::GetSelBarInPixels()
{
LONG lSelBarWidth;
(_ped->GetHost())->TxGetSelectionBarWidth(&lSelBarWidth);
return HimetricXtoDX(lSelBarWidth);
}
//================================ Device drivers ===================================
/*
* CDisplay::SetMainTargetDC(hdc, xWidthMax)
*
* Purpose:
* Sets a target device for this display and updates view
*
* Note:
* No support for targetDC in the base CDisplay class.
*
* Arguments:
* hdc target DC, NULL for same as rendering device
* xWidthMax max width of lines (not used if target device is screen)
*
* Note:
* Target device can't be a metafile (can get char width out of a
* metafile)
*
* Return
* TRUE if success
*/
BOOL CDisplay::SetMainTargetDC(HDC hdc, LONG xWidthMax)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplay::SetMainTargetDC");
_TEST_INVARIANT_
return TRUE;
}
BOOL CDisplay::SetTargetDC( HDC hdc )
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplay::SetTargetDC");
_TEST_INVARIANT_
return TRUE;
}
/*
* CDisplay::SetDrawInfo(pdi, dwDrawAspect, lindex, pvAspect, ptd, hicTargetDev)
*
* @mfunc
* Sets the drawing information into the display
*
* @rdesc
* void - this cannot fail
*
* @devnote
* The key point to this routine is that the caller of this routine
* is the owner of the memory for the drawing information. It is the
* callers responsiblity to call ReleaseDrawInfo to tell the display
* that it is done with the drawing information.
*/
void CDisplay::SetDrawInfo(
CDrawInfo *pdi, //@parm memory for draw info if there is not one already
DWORD dwDrawAspect, //@parm draw aspect
LONG lindex, //@parm currently unused
void *pvAspect, //@parm info for drawing optimizations (OCX 96)
DVTARGETDEVICE *ptd,//@parm information on target device
HDC hicTargetDev) //@parm target information context
{
HDC hicTargetToUse = hicTargetDev;
const CDevDesc *pdd;
// Set up the target device if we need to use the default
if ((NULL == hicTargetToUse))
{
pdd = GetDdTarget();
if (pdd != NULL)
{
hicTargetToUse = pdd->GetDC();
}
}
if (NULL == _pdi)
{
// Draw structure not yet allocated so use the one
// passed in
_pdi = pdi;
}
// Reset the parameters
_pdi->Init(
dwDrawAspect,
lindex,
pvAspect,
ptd,
hicTargetToUse);
}
/*
* CDisplay::ReleaseDrawInfo ()
*
* @mfunc
* Releases drawing information from display
*
* @rdesc
* void - this cannot fail
*
* @devnote
* Since the display does not own the memory for the drawing information,
* this only NULLs out the pointer in the drawing information pointer. It
* is the responsiblity of the caller to free the memory for the drawing
* information.
*/
void CDisplay::ReleaseDrawInfo()
{
if ((_pdi != NULL) && (_pdi->Release() == 0))
{
// This object is no longer referenced so we
// toss our reference.
_pdi = NULL;
}
}
/*
* CDisplay::GetTargetDev ()
*
* @mfunc
* Get the target device if one is available
*
* @rdesc
* Pointer to device description object or NULL if none is available.
*
* @devnote
* This uses the draw info if it is available and then the main target DC
* if it is available.
*/
const CDevDesc*CDisplay::GetTargetDev() const
{
const CDevDesc *pdd = NULL;
if ((_pdi != NULL) && _pdi->GetTargetDD())
{
pdd = _pdi->GetTargetDD();
}
return (pdd != NULL) ? pdd : GetDdTarget();
}
//================================ Background Recalc ===================================
/*
* CDisplay::StepBackgroundRecalc()
*
* Purpose
* Steps background line recalc (at GetCp()CalcMax position)
* Called by timer proc. No effect for base class
*
* ??? CF - Should use an idle thread
*/
VOID CDisplay::StepBackgroundRecalc()
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplay::StepBackgroundRecalc");
_TEST_INVARIANT_
}
/*
* CDisplay::WaitForRecalc(cpMax, yMax)
*
* @mfunc
* Ensures that lines are recalced until a specific character
* position or ypos. Always TRUE for base CDisplay class.
*
* @rdesc
* TRUE if success
*/
BOOL CDisplay::WaitForRecalc(
LONG cpMax, //@parm Position recalc up to (-1 to ignore)
LONG yMax) //@parm ypos to recalc up to (-1 to ignore)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplay::WaitForRecalc");
_TEST_INVARIANT_
return TRUE;
}
/*
* CDisplay::WaitForRecalcIli(ili)
*
* @mfunc
* Returns TRUE if lines were recalc'd up to ili
* Always the case for base CDisplay class.
*/
BOOL CDisplay::WaitForRecalcIli(LONG ili)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplay::WaitForRecalcIli");
_TEST_INVARIANT_
return TRUE;
}
/*
* CDisplay::WaitForRecalcView()
*
* Purpose
* Ensure visible lines are completly recalced
* Always the case for base CDisplay class
*/
BOOL CDisplay::WaitForRecalcView()
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplay::WaitForRecalcView");
_TEST_INVARIANT_
return TRUE;
}
//==================================== Rendering =======================================
/*
* CDisplay::Draw(hdcDraw, hicTargetDev, prcClient, prcWBounds,
* prcUpdate, pfnContinue, dwContinue)
* @mfunc
* General drawing method
* To be called in response to IViewObject::Draw() or WM_PAINT
*
* @rdesc
* HRESULT
*/
HRESULT CDisplay::Draw(
HDC hdcDraw,
HDC hicTargetDev,
LPCRECT prcClient,
LPCRECT prcWBounds,
LPCRECT prcUpdate,
BOOL (CALLBACK * pfnContinue) (DWORD),
DWORD dwContinue)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplay::Draw");
_TEST_INVARIANT_
HRESULT hr = S_OK;
HDC hdcMeasure = NULL;
LONG xMeasurePerInch = 0;
LONG yMeasurePerInch = 0;
// Save fonts currently in draw DC
HFONT hFontDraw = hdcDraw
? (HFONT) GetCurrentObject(hdcDraw, OBJ_FONT)
: NULL;
// Store the current depth in drawing locally so we can tell
// whether we need to actually render.
DWORD dwDepthThisDraw = _pdi->GetDrawDepth();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -