如何实现CScrollView持续滚动,在线等,顶贴有分 很多软件都是这样,当出现滚动条的时候,拖动某一个对象,如windows的窗口,图标较多时,拖住其中一个不放移至窗口边缘时,滚动条自动持续滚动,直到结束。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 就是如何让它持续滚动,难不成是用个timer,不停的ScrollToPosition? 求鼠标位置,或者求移动后物体的位置,根据位置判断是否已经到当前clientrect的边了,如果在边上,那么,移动,也就是取得当前的scroll的位置,然后加上偏移量,调用ScrollToPosition这些应该在onmousemove里面做的 选中物体,按住鼠标左键拖动物体,在onmousemove里面,根据当前鼠标点判断当前物体的偏移量,然后,改变物体的位置,当到达边界的时候,通过改动当前的scroll来确定新位置。 对啊,判断是否到边界了,这个是好办的,关键是,如果到了以后,就要让滚动条一直不停的滚动,问题就是如何让CScorllBar不停的滚动,直到不能滚动了为止。难不成是用个timer,不停的ScrollToPosition? 如果想要不停的动,最好用定时器,隔段时间判断一次,执行一次实际上,如果scrollbar范围比较大的话,要翻很多页的时候,我们点击scroll的一端,scroll不停的滚动,这也是用的定时器。 当然是Timer了。在Timer里面控制 Scroll view的POS。 当第一次判断到边界的时候,同时也启动timer,一直到鼠标松开或者scroll移动的极限值的时候,再干掉timer(这是ontime里面调用killtimer). 当鼠标点下开始拖动的时候,要setcapture,然后,即使鼠标移动到方框外,也不要紧,鼠标松开的时候,也一样要判断timer是否被干掉,如果没有被干掉,要干掉timer;不过,有一种是这样的,拖动到边缘的时候,scroll改变一下位置后,同时把鼠标设置到clientrect里面,如果人为不动鼠标,就不改变scroll.........所以,应该是两种情况,一种是靠近边缘,那么,只是改变scroll一次,同时设置鼠标到clientrect里面的一定位置(一般为scroll改变的距离),等待用户再次移动鼠标。另外一种,当达到scroll的边界的时候或者已经移出clientrect的时候,这时要用定时器了。 当然要明白处理对象的大小,位置,才能决定怎样scroll 感谢各位在牛!我ScrollToPosition(10,10),我怎么知道移动了多少像素,因为我移动的时候画了一个虚框,改变滚动条位置的时候,这个框的位置也要变化。 首先取得当前scroll的位置,用 POINT ptScroll = GetScrollPosition()得到当前的scroll的左上点,然后,加上你的平移量,ptScroll+POINT(10,0);//向右偏移10再设置回去ScrollToPosition(ptScroll);你计算你的数据的时候,必须要考虑到GetScrollPosition(),当前clientrect里面显示的,应该是GetClientRect偏移GetScrollPosition()所包含的所有数据所以,改变了scroll后,你只需要重新设置鼠标位置即可。 比如我拖动一个对象时,这个时候移动鼠标,在新的位置出现一个虚框,当虚框移至边界时,触发定时器, CPoint _point = GetScrollPosition(); CPoint pt(_point.x+10,_point.y); ScrollToPosition(pt);这个时候我只需要计算这个虚框的位置,重画它,对吧。现在是如何计算这个虚框的坐标,比如ScrollToPosition(10,0);这个虚框要移动多少像素呢? 实际物体的坐标,应该是当前的mousemove的鼠标点加上GetScrollPosition()而在画的时候,是鼠标的坐标减去GetScrollPosition() 现在的问题是当滚动条滚动时,我画的虚框总是有重影。我的虚框是这样画的。进入到timer后,首先擦掉最后一次的虚框。CClientDC dc(this);dc.DrawFocusRect(rect);//CPoint point = GetScrollPosition();CPoint pt(point.x+10,point.y);ScrollToPosition(pt);//在新的地方再画,其实和上面的坐标一样,都是逻辑坐标dc.DrawFocusRect(rect);大致是这样,我看了坐标都没错,但是就是有重影,不知道为啥。 下面我是我做的现成例子,用于拖动和改变大小。BOOL CPlotsView::Track(const HWND hWnd, LPRECT lprcTracker, const int iFlags, const POINT point){ // get DC for drawing HDC hDC = ::GetDC(hWnd); RECT rectOld = *lprcTracker; if (iFlags & 1)//sizing the left of rectangle { lprcTracker->left = point.x; } if (iFlags & 2)//sizing the top of rectangle { lprcTracker->top = point.y; } if (iFlags & 4)//sizing the right of rectangle { lprcTracker->right = point.x; } if (iFlags & 8)//sizing the bottom of rectangle { lprcTracker->bottom = point.y; } if (iFlags & 16)//moving the rectangle { int dx = point.x - lprcTracker->left - m_ptOff.x; int dy = point.y - lprcTracker->top - m_ptOff.y; ::OffsetRect(lprcTracker, dx, dy); } if (!::EqualRect(&rectOld, lprcTracker)) { ::DrawFocusRect(hDC, &rectOld); SIZE sizeLine,sizeTotal,sizePage; int nMapMode; GetDeviceScrollSizes(nMapMode, sizeTotal, sizePage, sizeLine); int xPos = ::GetScrollPos(m_hWnd, SB_HORZ); int yPos = ::GetScrollPos(m_hWnd, SB_VERT); RECT rcClient; ::GetClientRect(m_hWnd, &rcClient); if (xPos !=0 && lprcTracker->left <= 0 ) { ::SendMessage(m_hWnd, WM_HSCROLL, (WPARAM)SB_LINELEFT, 0); ::OffsetRect(lprcTracker, sizeLine.cx, 0); } if (xPos + rcClient.right < sizeTotal.cx && lprcTracker->right >= rcClient.right) { ::SendMessage(m_hWnd, WM_HSCROLL, SB_LINERIGHT, 0); ::OffsetRect(lprcTracker, -sizeLine.cx, 0); } if (yPos !=0 && lprcTracker->top <= 0 ) { ::SendMessage(m_hWnd, WM_VSCROLL, (WPARAM)SB_LINEUP, 0); ::OffsetRect(lprcTracker, 0, sizeLine.cy); } if (yPos + rcClient.bottom < sizeTotal.cy && lprcTracker->bottom >= rcClient.bottom) { ::SendMessage(m_hWnd, WM_VSCROLL, SB_LINEDOWN, 0); ::OffsetRect(lprcTracker, 0, -sizeLine.cy); } ::DrawFocusRect(hDC, lprcTracker); } ::ReleaseDC(hWnd, hDC); return TRUE;} 真奇怪,用ScrollToPosition(pt);不行,向滚动条发消息则可以。 ScrollToPosition后面,好像要调用Invalidate之类的刷新吧 如果是这样的话,那还必须调整光标的位置,是吧。因为滚动后,光标的位置没变,DrawFocusRect的位置变了。 SetScrollSizes(MM_TEXT, m_layout, m_page, m_line);int yPos = GetScrollPos(SB_VERT);ypos的值为什么会超过m_page.cy的值呢,而且还超过很多。 SetScrollSizes(...)ResizeParentToFit();int yPos = GetScrollPos(SB_VERT);这样试试 原理很简单,发现到边界,先用以前的值重绘一下焦点矩形,因为焦点矩形有XOR的特性,所以用相同坐标绘,是擦除,然后根据边界情况,发滚屏消息,滚屏后重新计算焦点矩形的新位置,再绘,这时就是绘了,因为是第一绘。不要用ScrollView提供的那些来操作滚动条,包括获得滚动条信息,用API的,我一直这样用 关于colestreamfile的,大家帮我看看 如何用DirectX来模拟出VC里Edit Box那样的控件呢? VC6 vs VC7.1 急!!!如何判断对端关闭了socket block 键盘,鼠标消息- 急急!!!!!!!!!!!!! 谁给讲一下?????? 在VC中使用ODBC,ADO编程如何使用事务处理功能 请问有无现存的四舍五入函数?(in vc) 程序如何改才行呀,帮忙下,谢谢 一个有关.bmp文件的问题 dc.FillRect异常 请指点
这些应该在onmousemove里面做的
实际上,如果scrollbar范围比较大的话,要翻很多页的时候,我们点击scroll的一端,scroll不停的滚动,这也是用的定时器。
不过,有一种是这样的,拖动到边缘的时候,scroll改变一下位置后,同时把鼠标设置到clientrect里面,如果人为不动鼠标,就不改变scroll.........所以,应该是两种情况,一种是靠近边缘,那么,只是改变scroll一次,同时设置鼠标到clientrect里面的一定位置(一般为scroll改变的距离),等待用户再次移动鼠标。另外一种,当达到scroll的边界的时候或者已经移出clientrect的时候,这时要用定时器了。
我ScrollToPosition(10,10),我怎么知道移动了多少像素,因为我移动的时候画了一个虚框,改变滚动条位置的时候,这个框的位置也要变化。
再设置回去ScrollToPosition(ptScroll);你计算你的数据的时候,必须要考虑到GetScrollPosition(),当前clientrect里面显示的,应该是GetClientRect偏移GetScrollPosition()所包含的所有数据
所以,改变了scroll后,你只需要重新设置鼠标位置即可。
CPoint _point = GetScrollPosition();
CPoint pt(_point.x+10,_point.y);
ScrollToPosition(pt);
这个时候我只需要计算这个虚框的位置,重画它,对吧。现在是如何计算这个虚框的坐标,比如ScrollToPosition(10,0);这个虚框要移动多少像素呢?
而在画的时候,是鼠标的坐标减去GetScrollPosition()
我的虚框是这样画的。
进入到timer后,首先擦掉最后一次的虚框。CClientDC dc(this);
dc.DrawFocusRect(rect);
//
CPoint point = GetScrollPosition();
CPoint pt(point.x+10,point.y);
ScrollToPosition(pt);
//在新的地方再画,其实和上面的坐标一样,都是逻辑坐标
dc.DrawFocusRect(rect);大致是这样,我看了坐标都没错,但是就是有重影,不知道为啥。
BOOL CPlotsView::Track(const HWND hWnd, LPRECT lprcTracker, const int iFlags, const POINT point)
{
// get DC for drawing
HDC hDC = ::GetDC(hWnd);
RECT rectOld = *lprcTracker;
if (iFlags & 1)//sizing the left of rectangle
{
lprcTracker->left = point.x;
}
if (iFlags & 2)//sizing the top of rectangle
{
lprcTracker->top = point.y;
}
if (iFlags & 4)//sizing the right of rectangle
{
lprcTracker->right = point.x;
}
if (iFlags & 8)//sizing the bottom of rectangle
{
lprcTracker->bottom = point.y;
}
if (iFlags & 16)//moving the rectangle
{
int dx = point.x - lprcTracker->left - m_ptOff.x;
int dy = point.y - lprcTracker->top - m_ptOff.y;
::OffsetRect(lprcTracker, dx, dy);
} if (!::EqualRect(&rectOld, lprcTracker))
{
::DrawFocusRect(hDC, &rectOld);
SIZE sizeLine,sizeTotal,sizePage;
int nMapMode;
GetDeviceScrollSizes(nMapMode, sizeTotal, sizePage, sizeLine);
int xPos = ::GetScrollPos(m_hWnd, SB_HORZ);
int yPos = ::GetScrollPos(m_hWnd, SB_VERT);
RECT rcClient;
::GetClientRect(m_hWnd, &rcClient);
if (xPos !=0 && lprcTracker->left <= 0 )
{
::SendMessage(m_hWnd, WM_HSCROLL, (WPARAM)SB_LINELEFT, 0);
::OffsetRect(lprcTracker, sizeLine.cx, 0);
}
if (xPos + rcClient.right < sizeTotal.cx && lprcTracker->right >= rcClient.right)
{
::SendMessage(m_hWnd, WM_HSCROLL, SB_LINERIGHT, 0);
::OffsetRect(lprcTracker, -sizeLine.cx, 0);
}
if (yPos !=0 && lprcTracker->top <= 0 )
{
::SendMessage(m_hWnd, WM_VSCROLL, (WPARAM)SB_LINEUP, 0);
::OffsetRect(lprcTracker, 0, sizeLine.cy);
}
if (yPos + rcClient.bottom < sizeTotal.cy && lprcTracker->bottom >= rcClient.bottom)
{
::SendMessage(m_hWnd, WM_VSCROLL, SB_LINEDOWN, 0);
::OffsetRect(lprcTracker, 0, -sizeLine.cy);
}
::DrawFocusRect(hDC, lprcTracker);
}
::ReleaseDC(hWnd, hDC);
return TRUE;
}
SetScrollSizes(MM_TEXT, m_layout, m_page, m_line);
int yPos = GetScrollPos(SB_VERT);ypos的值为什么会超过m_page.cy的值呢,而且还超过很多。
ResizeParentToFit();
int yPos = GetScrollPos(SB_VERT);这样试试
不要用ScrollView提供的那些来操作滚动条,包括获得滚动条信息,用API的,我一直这样用