📄 disp.cpp
字号:
switch(dwScroll)
{
case dwAutoScrollUp:
wScrollCode = SB_LINEUP;
// fall through to dwAutoScrollDown
case dwAutoScrollDown:
// OnVScroll() doesn't scroll enough for our desires
VScroll(wScrollCode, 0);
VScroll(wScrollCode, 0);
break;
case dwAutoScrollLeft:
wScrollCode = SB_LINEUP;
// fall through to dwAutoScrollRight
case dwAutoScrollRight:
// HScroll() doesn't scroll enough for our desires
HScroll(wScrollCode, 0);
HScroll(wScrollCode, 0);
HScroll(wScrollCode, 0);
HScroll(wScrollCode, 0);
break;
#ifdef DEBUG
default:
Tracef(TRCSEVWARN, "Unexpected dwScroll %lx", dwScroll);
TRACEERRSZSC("Unexpected dwScroll", E_INVALIDARG);
break;
#endif
}
// reset interval counter
_dwTimeScrollNext = dwTime + cmsecScrollInterval;
fScrolled = TRUE;
}
}
#ifdef DEBUG
else if(_dwScrollLast)
TRACEINFOSZ("moved out of auto scroll area");
#endif
_dwScrollLast = dwScroll;
return fScrolled;
}
/*
* CDisplay::AutoScroll(pt, xScrollInset, yScrollInset)
*
* @mfunc:
* Given the current point, determine whether we need to
* scroll the client area.
*
* Requires:
* This function should only be called during a drag drop
* operation.
*
* @rdesc
* True if we are in the drag scrolling hot zone, false otherwise.
*
*/
#define ScrollUp 0x0001 //These eight macros indicate the areas
#define ScrollDown 0x0010 //of the drag scrolling hot zone that tell
#define ScrollLeft 0x0100 //which direction to scroll.
#define ScrollRight 0x1000 //The last four are ambiguous (the corners)
#define ScrollUL 0x0101 //and require a little extra work.
#define ScrollUR 0x1001
#define ScrollDL 0x0110
#define ScrollDR 0x1010
BOOL CDisplay::AutoScroll(
POINT pt, //@parm Cursor location in client coordinates
const WORD xScrollInset,
const WORD yScrollInset)
{
TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CDisplay::AutoScroll");
static DWORD hotticks = 0; //Ticks when we entered hot zone.
static DWORD lastscrollticks = 0; //Ticks when we last scroll.
static DWORD lastticks = 0; //Ticks when last called.
DWORD delta; //Ticks since last called.
DWORD ticks; //GetTickCount ticks.
RECT rcClient; //Client rect of control.
WORD wScrollDir = 0; //Scroll direction.
BOOL fScroll = FALSE; //TRUE if we should try to scroll this time.
BOOL fEnabled = FALSE; //TRUE if scrolling is possible
//Get the current ticks and calculate ticks since last called.
//Note that if _drags does not have valid data this will be a
//bogus value, but that is handled later.
ticks = GetTickCount();
delta = ticks - lastticks;
lastticks = ticks;
//Don't do anything if no ticks since last time we were called.
if (delta)
{
// Get our client rect.
_ped->TxGetClientRect(&rcClient);
//Find out if we are in the hot zone.
//Note that if we are in one of the corners
//we will indicate two scrolling directions.
//This ambiguity will be sorted out later.
//For now we just want to know if we are in
//the zone.
if (pt.x <= (LONG)(rcClient.left + xScrollInset))
wScrollDir |= (WORD)ScrollLeft;
else if (pt.x >= (LONG)(rcClient.right - xScrollInset))
wScrollDir |= (WORD)ScrollRight;
if (pt.y <= (LONG)(rcClient.top + yScrollInset))
wScrollDir |= (WORD)ScrollUp;
else if (pt.y >= (LONG)(rcClient.bottom - yScrollInset))
wScrollDir |= (WORD)ScrollDown;
//If we are somewhere in the hot zone.
if (wScrollDir)
{
//If we just entered hotzone remember the current ticks.
if (!hotticks)
hotticks = ticks;
//If we have been in the hot zone long enough, and
//the required interval since the last scroll has elapsed
//allow another scroll. Note that if we haven't scrolled yet,
//lastscrollticks will be zero so the delta is virtually
//guaranteed to be greater than ScrollInterval.
if ((ticks - hotticks) >= (DWORD)sysparam.GetScrollDelay() &&
(ticks - lastscrollticks) >= (DWORD)sysparam.GetScrollInterval())
fScroll = TRUE;
//If we are in one of the corners, we scroll
//in the direction of the edge we are closest
//to.
switch (wScrollDir)
{
case ScrollUL:
{
if ((pt.y - rcClient.top) <= (pt.x - rcClient.left))
wScrollDir = ScrollUp;
else
wScrollDir = ScrollLeft;
break;
}
case ScrollUR:
{
if ((pt.y - rcClient.top) <= (rcClient.right - pt.x))
wScrollDir = ScrollUp;
else
wScrollDir = ScrollRight;
break;
}
case ScrollDL:
{
if ((rcClient.bottom - pt.y) <= (pt.x - rcClient.left))
wScrollDir = ScrollDown;
else
wScrollDir = ScrollLeft;
break;
}
case ScrollDR:
{
if ((rcClient.bottom - pt.y) <= (rcClient.right - pt.x))
wScrollDir = ScrollDown;
else
wScrollDir = ScrollRight;
break;
}
}
}
else
{
//We aren't in the hot zone so reset hotticks as a
//flag so we know the first time we reenter it.
hotticks = 0;
}
//Do processing for horizontal scrolling if necessary
if (wScrollDir == ScrollLeft || wScrollDir == ScrollRight)
{
LONG xRange, xScroll, dx;
xScroll = ConvertXPosToScrollPos(GetXScroll());
xRange = GetScrollRange(SB_HORZ);
dx = sysparam.GetScrollHAmount();
fEnabled = IsHScrollEnabled();
if (wScrollDir == ScrollLeft)
{
fEnabled = fEnabled && (xScroll > 0);
xScroll -= dx;
xScroll = max(xScroll, 0);
}
else
{
fEnabled = fEnabled && (xScroll < xRange);
xScroll += dx;
xScroll = min(xScroll, xRange);
}
//Do the actual scrolling if necessary.
if (fEnabled && fScroll)
{
HScroll(SB_THUMBPOSITION, xScroll);
lastscrollticks = ticks;
}
}
//Do processing for Vertical scrolling if necessary
else if (wScrollDir == ScrollUp || wScrollDir == ScrollDown)
{
LONG yRange, yScroll, dy;
yScroll = ConvertYPosToScrollPos(GetYScroll());
yRange = GetScrollRange(SB_VERT);
dy = sysparam.GetScrollVAmount();
fEnabled = IsVScrollEnabled();
if (wScrollDir == ScrollUp)
{
fEnabled = fEnabled && (yScroll > 0);
yScroll -= dy;
yScroll = max(yScroll, 0);
}
else
{
fEnabled = fEnabled && (yScroll < yRange);
yScroll += dy;
yScroll = min(yScroll, yRange);
}
//Do the actual scrolling if necessary.
if (fEnabled && fScroll)
{
// We need to scroll fractionally because the scroll logic tries
// to put a full line on the top and if the scroll amount is less
// than a full line, the scrolling will get stuck on that line.
ScrollView(_xScroll, yScroll, FALSE, TRUE);
lastscrollticks = ticks;
}
}
}
return fEnabled;
}
/*
* CDisplay::AdjustToDisplayLastLine(yBase, yScroll)
*
* @mfunc
* Calculate the yscroll necessary to get the last line to display
*
* @rdesc
* Updated yScroll
*
* @devnote:
* This method is only really useful for ML displays. This method
* here is a placeholder which does nothing which is useful for
* all other displays.
*
*/
LONG CDisplay::AdjustToDisplayLastLine(
LONG yBase, //@parm actual yScroll to display
LONG yScroll) //@parm proposed amount to scroll
{
return yScroll;
}
/*
* CDisplay::GetScrollRange()
*
* Purpose
* Returns the max part of a scrollbar range
* No scrollbar support in the base class: returns 0.
*
*/
LONG CDisplay::GetScrollRange(INT nBar) const
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplay::GetScrollRange");
_TEST_INVARIANT_
return 0;
}
/*
* CDisplay::UpdateScrollBar(nBar, fUpdateRange)
*
* Purpose:
* Update either the horizontal or vertial scroll bar
* Also figure whether the scroll bar should be visible or not
* No scrollbar support in the base class: no action.
*/
BOOL CDisplay::UpdateScrollBar(
INT nBar,
BOOL fUpdateRange)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplay::UpdateScrollBar");
_TEST_INVARIANT_
return TRUE;
}
/*
* CDisplay::GetZoomDenominator()
*
* @mfunc
* Get zoom denominator
*
* @rdesc
* Returns zoom denominator
*
* @devnote:
* FUTURE: (Ricksa) we should investigate how to cache this data since
* the display needs to keep a temporary zoom denominator anyway.
*/
LONG CDisplay::GetZoomDenominator() const
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplay::GetZoomDenominator");
if(_ped->GetZoomDenominator()) // Simple EM_SETZOOM API
return _ped->GetZoomDenominator(); // supercedes complicated
// Forms^3 API
SIZEL sizelExtent;
// Default zoom to error case. The error case is a very low
// probability event that we can do nothing to recover. So we
// just set the value to something reasonable and continue.
LONG lZoomDenominator = _yHeightClient;
// Is the temporary zoom denominator set?
if (INVALID_ZOOM_DENOMINATOR == _lTempZoomDenominator)
{
// No - Get the extent size from the host.
if (SUCCEEDED(_ped->TxGetExtent(&sizelExtent)))
{
// Convert height to device units. Note that by definition, we
// can ignore horizontal extents so we do. Use CDevDesc conversion
// to avoid infinite recursion
lZoomDenominator = CDevDesc::HimetricYtoDY(sizelExtent.cy);
}
}
else // Temporary zoom denominator is set: use it
lZoomDenominator = CDevDesc::HimetricYtoDY(_lTempZoomDenominator);
return lZoomDenominator > 0 ? lZoomDenominator : 1;
}
/*
* CDisplay::GetZoomNumerator()
*
* @mfunc
* Get zoom numerator
*
* @rdesc
* Returns zoom numerator
*/
LONG CDisplay::GetZoomNumerator() const
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplay::GetZoomNumerator");
if(_ped->GetZoomNumerator()) // Simple EM_SETZOOM API
return _ped->GetZoomNumerator(); // supercedes complicated
// Forms^3 API
return _yHeightClient > 0 ? _yHeightClient : 1;
}
/*
* CDisplay::Zoom(x)
*
* @mfunc
* Get zoomed x
*
* @rdesc
* Returns zoomed x
*/
LONG CDisplay::Zoom(LONG x) const
{
return MulDiv(x, GetZoomNumerator(), GetZoomDenominator());
}
/*
* CDisplay::UnZoom(x)
*
* @mfunc
* Get unzoomed x
*
* @rdesc
* Returns unzoomed x
*/
LONG CDisplay::UnZoom(LONG x) const
{
return MulDiv(x, GetZoomDenominator(), GetZoomNumerator());
}
/*
* CDisplay::HimetricXtoDX(xHimetric)
*
* @mfunc
* Get device x coordinate corresponding to Himetric x coordinate
*
* @rdesc
* Returns device coordinate
*/
LONG CDisplay::HimetricXtoDX(
LONG xHimetric) const
{
return CDevDesc::HimetricXtoDX(Zoom(xHimetric));
}
/*
* CDisplay::HimetricYtoDY(yHimetric)
*
* @mfunc
* Get device y coordinate corresponding to Himetric y coordinate
*
* @rdesc
* Returns device coordinate
*/
LONG CDisplay::HimetricYtoDY(
LONG yHimetric) const
{
return CDevDesc::HimetricYtoDY(Zoom(yHimetric));
}
/*
* CDisplay::DXtoHimetricX(dx)
*
* @mfunc
* Get Himetric x coordinate corresponding to device x coordinate
*
* @rdesc
* Returns Himetric coordinate
*/
LONG CDisplay::DXtoHimetricX(
LONG dx) const
{
return UnZoom(CDevDesc::DXtoHimetricX(dx));
}
/*
* CDisplay::DXtoHimetricX(dy)
*
* @mfunc
* Get Himetric y coordinate corresponding to device y coordinate
*
* @rdesc
* Returns Himetric coordinate
*/
LONG CDisplay::DYtoHimetricY(
LONG dy) const
{
return UnZoom(CDevDesc::DYtoHimetricY(dy));
}
/*
* CDisplay::SetClientHeight(yNewClientHeight)
*
* @mfunc
* Reset the height of the client rectangle
*
* @rdesc
* Returns previous height of the client rectangle
*/
LONG CDisplay::SetClientHeight(
LONG yNewClientHeight) //@parm New height for the client rectangle.
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplay::SetClientHeight");
LONG yOldHeight = _yHeightClient;
_yHeightClient = yNewClientHeight;
return yOldHeight;
}
/*
* CDisplay::GetCachedSize
*
* @mfunc calculates the cached client size (since it's not really
* cached :-)
*/
HRESULT CDisplay::GetCachedSize(
DWORD *pdwWidth, //@parm where to put the width
DWORD *pdwHeight) //@parm where to put the height
{
RECT rcInset;
_ped->TxGetViewInset(&rcInset, this);
*pdwHeight = _yHeightClient;
*pdwWidth = _xWidthView + rcInset.left + rcInset.right
+ GetSelBarInPixels();
return NOERROR;
}
/*
* CDisplay::TransparentHitTest(hdc, prcClient, pt, pHitResult)
*
* @mfunc
* Determine if the hit is on a transparent control
*
* @rdesc
* Returns HRESULT of call usually S_OK.
*
* @devnote
* FUTURE: This code needs to be investigated for possible optimizations.
*
* This code is assumes that all remeasuring needed has been done before
* this routine is called.
*/
HRESULT CDisplay::TransparentHitTest(
HDC hdc, //@parm DC for actual drawing
LPCRECT prcClient, //@parm Client rectangle for rendering
POINT pt, //@parm Point to hittest against
DWORD *pHitResult) //@parm Result of the hit test see TXTHITRESULT
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplay::TransparentHitTest");
RECT rcClient;
HDC hdcMem = NULL;
HRESULT hr = E_FAIL;
HBITMAP hbmp = NULL;
HBITMAP hbmpOld = NULL;
RECT rcView;
int iRow;
RECT rcRender;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -