15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Repeating the scroll

Doncho Angelov -- alian@plovdiv.techno-link.com
Sunday, February 02, 1997

Environment: VC++ 4.0, Win 95

Hello everybody !

I have the following problem:
	I'm implementing drag operation in my CScrollView. It's simple dragging =
of graphical object from one place to another. But as you know the =
ScrollView has size, which is (sometimes) much bigger than the window's =
client area. So I want after I go outside the client area during =
dragging with the mouse, the CScrollView to scroll automatically while =
I'm 'away' from the client area and to finish scrolling at the end or =
when I return to the client area. I've checked some materials to find =
'ready' code, but I couldn't find even an idea. The only one idea which =
came into my mind was to initialize timer who's going to check and to =
send scrolling messages while the cursor is outside the client area, but =
this is a little 'confusing'.
	Any better ideas ?

Thanks in advance !

Doncho



Simon Salter -- Simon@chersoft.co.uk
Wednesday, February 05, 1997

Good scrolling is, imho, quite hard to do and also fairly rare. Here are
some ideas which build on what I suspect you are already thinking about.

When you are dragging the object you will have set capture to the view.
In OnMouseMove() you can test to see if you are outside or inside the
client rect and use this to start/stop scrolling of the view. You might
like to actually test a rect slightly smaller than the client area so
that scrolling starts when you get close to the edge.

To implement the scrolling you will first need to work out what
direction to scroll in (by looking where the mouse is in relation to the
client area). Controlling the scroll can be tricky. My preference is
that you do it in some controlled fashion which means when someone runs
your app on a super wizz cpu the scrolling does not rush past at an
unreasonable rate. (The MSDEV edit windows do this if you drag sideways
- it can sometimes need some deft mouse handling). So I'd use a timer to
set up a regular scrolling interval and start it from OnMouseMove(). I
might also calculate how far from the client area the cursor is and
increase the rate of scrolling proportionately. The OnTimer() would have
to calculate how much scrolling to do for one 'tick' and either do the
scroll or, if the mouse was back on the client area, kill the timer.

>-----Original Message-----
>From:	Doncho Angelov [SMTP:alian@plovdiv.techno-link.com]
>Sent:	Fri, 02 February 1996 23:22
>To:	'MFC-L'
>Subject:	Repeating the scroll
>
>Environment: VC++ 4.0, Win 95
>
>Hello everybody !
>
>I have the following problem:
>	I'm implementing drag operation in my CScrollView. It's simple dragging =
>of graphical object from one place to another. But as you know the =
>ScrollView has size, which is (sometimes) much bigger than the window's =
>client area. So I want after I go outside the client area during =
>dragging with the mouse, the CScrollView to scroll automatically while =
>I'm 'away' from the client area and to finish scrolling at the end or =
>when I return to the client area. I've checked some materials to find =
>'ready' code, but I couldn't find even an idea. The only one idea which =
>came into my mind was to initialize timer who's going to check and to =
>send scrolling messages while the cursor is outside the client area, but =
>this is a little 'confusing'.
>	Any better ideas ?
>
>Thanks in advance !
>
>Doncho



John Young -- jyoung@gol.com
Thursday, February 06, 1997

Hi Doncho,

At 11:21 pm 2/2/96 +-200, Doncho Angelov wrote:
>Environment: VC++ 4.0, Win 95
>
>Hello everybody !
>
>I have the following problem:
>	I'm implementing drag operation in my CScrollView. It's simple dragging =
>of graphical object from one place to another. But as you know the =
>ScrollView has size, which is (sometimes) much bigger than the window's =
>client area. So I want after I go outside the client area during =
>dragging with the mouse, the CScrollView to scroll automatically while =
>I'm 'away' from the client area and to finish scrolling at the end or =
>when I return to the client area. I've checked some materials to find =
>'ready' code, but I couldn't find even an idea. The only one idea which =
>came into my mind was to initialize timer who's going to check and to =
>send scrolling messages while the cursor is outside the client area, but =
>this is a little 'confusing'.
>	Any better ideas ?

I did this recently.  What I did was to capture the mouse in the view's 
OnLButtonDown() handler, detect when the mouse is dragged out of the 
client area in the OnMouse() handler and start a timer.  In the 
OnTimer() handler, simply calculate the new scroll and call 
ScrollToPosition().  When the mouse button is released, then release 
the capture and kill the timer.

The timer value can be varied so that the scrolling slows down when the 
mouse nears the client area, and speeds up when it is further away. 

Here's the heart of the code I use...


void CPredView::OnLButtonDown(UINT nFlags, CPoint point) 
{
    	theMouse.Capture (this);
	CScrollView::OnLButtonDown (nFlags, point);
}

void CPredView::OnMouseMove (UINT nFlags, CPoint point) 
{
	if ( nFlags & MK_LBUTTON )
	{
		CRect rectClient;
		GetClientRect (&rectClient);
		if ( point.y >= rectClient.top &&
			point.y <= rectClient.bottom )
		{			
			m_bMouseScrolling = FALSE;
			KillTimer (TIMER_MOUSESCROLL);
		}
		else 
		{
			// Mouse is outside the client area, so scroll
			if ( !m_bMouseScrolling )
			{
				m_bMouseScrolling = TRUE;
				SetTimer (TIMER_MOUSESCROLL, 50, NULL);
			}
		}
	}
	
	CScrollView::OnMouseMove(nFlags, point);
}



void CPredView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	m_bMouseScrolling = FALSE;
	KillTimer (TIMER_MOUSESCROLL);
	theMouse.Release();
	CScrollView::OnLButtonUp(nFlags, point);
}


void CPredView::OnTimer (UINT nIDEvent) 
{
	if ( nIDEvent == TIMER_MOUSESCROLL )
	{
		CPoint pt = theMouse;
		ScreenToClient (&pt);
		OnMouseScroll (pt);
	}
	
	CScrollView::OnTimer(nIDEvent);
}

void CPredView::OnMouseScroll (CPoint ptMouse)
{
	// Mouse is outside the client window.
	CPoint ptScroll = GetScrollPosition();

	if ( IsBelowClient (ptMouse) )
	{
		// Scroll up by some amount
		ptScroll += ?

		ScrollToPosition (ptScroll);

		// Adjust speed
		if ( ptMouse.y > rectClient.bottom + m_nSpeedThreshold )
			SetTimer (TIMER_MOUSESCROLL, 10, NULL);	// Fast
		else	SetTimer (TIMER_MOUSESCROLL, 300, NULL);	// Slow
	}
	else if ( IsAboveClient (ptMouse) )
	{
		// Scroll down
		ptScroll -= ?

		ScrollToPosition (ptScroll);

		// Adjust speed
		if ( ptMouse.y < rectClient.top - m_nSpeedThreshold )
			SetTimer (TIMER_MOUSESCROLL, 10, NULL);	// Fast
		else SetTimer (TIMER_MOUSESCROLL, 300, NULL);	// Slow
	}
}

HTH

-John


John Young, Yaesu Musen Co., Ltd., Japan.
If only computers did what you wanted, not what you tell them.





Become an MFC-L member | Вернуться в корень Архива |