예제 #1
0
/*----------------------------------------------------------------------------------------------
	With no scroll bar, the only way this happens is when the user drags outside the window.
	We need to override because the superclass does nothing when there is no scroll bar.
----------------------------------------------------------------------------------------------*/
bool TssEdit::OnHScroll(int nSBCode, int nPos, HWND hwndSbar)
{
	// NB - DON'T use nPos; it has only a 16-bit range.
	int dxdPos = m_dxpScrollOffset; // Where the window thinks it is now.
	// ENHANCE JohnT: use actual resolution.
	int dxdLine = 30 * 96/72; // 30 points seems a useful size increment.

	switch (nSBCode)
	{
	case SB_LINELEFT:
		dxdPos -= dxdLine;
		break;
	case SB_LINERIGHT:
		dxdPos += dxdLine;
		break;
	default:
		dxdPos = 0;
		Assert(false); // others should not happen
		break;
	}
	// Try to stop it scrolling too far. This is unfortunately not easy to do. Try getting
	// the width of a selection of the whole thing and limit it to a bit more than that.
	IVwSelectionPtr qvwsel;
	CheckHr(m_qrootb->MakeSimpleSel(true, false, true, false, &qvwsel));
	HoldGraphics hg(this);
	Rect rdPrimary;
	Rect rdSecondary;
	ComBool fSplit;
	ComBool fEndBeforeAnchor;
	CheckHr(qvwsel->Location(hg.m_qvg, hg.m_rcSrcRoot, hg.m_rcDstRoot, &rdPrimary,
		&rdSecondary, &fSplit, &fEndBeforeAnchor));
	Rect rcClient;
	::GetClientRect(m_hwnd, &rcClient);
	int dxpMax = rdPrimary.Width() - rcClient.Width() + 20;
	if (dxdPos > dxpMax)
		dxdPos = dxpMax;

	// In this class we don't have to worry about a max.
	if (dxdPos < 0)
		dxdPos = 0;

	int dxdScrollBy = dxdPos - m_dxpScrollOffset;

	// Update the scroll position.
	m_dxpScrollOffset = dxdPos;

	ScrollBy(dxdScrollBy, 0);
	return true;
}
예제 #2
0
/*----------------------------------------------------------------------------------------------
	Scroll to make the selection visible.
	In general, scroll the minimum distance to make it entirely visible.
	If the selection is higher than the window, scroll the minimum distance to make it
	fill the window.
	If the window is too small to show both primary and secondary, show primary.
	Note: subclasses for which scrolling is disabled should override.
	If psel is null, make the current selection visible.
----------------------------------------------------------------------------------------------*/
void TssEdit::MakeSelectionVisible1(IVwSelection * psel)
{
	//Assert(m_fVScrollEnabled);
	IVwSelectionPtr qvwsel;
	if (!m_qrootb)
	{
		return; // For paranoia.
	}
	if (psel)
		qvwsel = psel;
	else
	{
		CheckHr(m_qrootb->get_Selection(&qvwsel));
		if (!qvwsel)
		{
			return; // Nothing we can do.
		}
	}
	Rect rdPrimary;
	Rect rdSecondary;
	ComBool fSplit;
	ComBool fEndBeforeAnchor;
	Rect rcSrcRoot;
	Rect rcDstRoot;
	Rect rdIdeal;
	HoldGraphics hg(this);
	GetCoordRects(m_qvg, &rcSrcRoot, &rcDstRoot);
	CheckHr(qvwsel->Location(m_qvg, rcSrcRoot, rcDstRoot, &rdPrimary, &rdSecondary, &fSplit,
		&fEndBeforeAnchor));
	rdIdeal = rdPrimary;

	Rect rcClient;
	m_pwndSubclass->GetClientRect(rcClient);
	if (fSplit)
	{
		rdIdeal.Sum(rdSecondary);
		if (rdIdeal.Width() > rcClient.Width())
			rdIdeal = rdPrimary;
	}
	// OK, we want rdIdeal to be visible.

	// dx gets added to the scroll offset. This means a positive dx causes there to be more
	// of the view hidden left of the screen. This is the same effect as clicking a
	// right arrow, which paradoxically causes the window contents to move left.
	int dx = 0;
	int xdLeft = m_dxpScrollOffset; // Where the window thinks it is now.
	rdIdeal.Offset(xdLeft, 0); // Was in drawing coords, adjusted by left.
	int xdRight = xdLeft + rcClient.Width();

	// Is the selection partly off the left of the screen?
	if (rdIdeal.left < xdLeft)
	{
		// Is it bigger than the screen?
		if (rdIdeal.Width() > rcClient.Width() && !fEndBeforeAnchor)
		{
			// Left is off, and though it is too big to show entirely, we can show
			// more. Move the window contents right (negative dx).
			dx = rdIdeal.right - xdRight;
		}
		else
		{
			// Partly off left, and fits: move window contents right (less is hidden,
			// neg dx).
			dx = rdIdeal.left - xdLeft;
		}
	}
	else
	{
		// Left of selection is right of (or at) the left side of the screen.
		// Is right of selection right of the right side of the screen?
		if (rdIdeal.right > xdRight)
		{
			if (rdIdeal.Width() > rcClient.Width() && fEndBeforeAnchor)
			{
				// Left is visible, right isn't: move until lefts coincide to show as much
				// as possible. This is hiding more text left of the window: positive dx.
				dx = rdIdeal.left - xdLeft;
			}
			else
			{
				// Fits entirely: scroll left minimum to make right visible. This involves
				// hiding more text at the left: positive dx.
				dx = rdIdeal.right - xdRight;
			}
		}
		// Else it is already entirely visible, do nothing.
	}
	if (dx + m_dxpScrollOffset < 0)
		dx = -m_dxpScrollOffset; // make offset 0 if it would have been less than that
	if (dx)
	{
		// Update the actual position.
		m_dxpScrollOffset += dx;
	}
	ScrollBy(dx, 0);
}