很多软件都是这样,当出现滚动条的时候,拖动某一个对象,如windows的窗口,图标较多时,拖住其中一个不放移至窗口边缘时,滚动条自动持续滚动,直到结束。

解决方案 »

  1.   

    就是如何让它持续滚动,难不成是用个timer,不停的ScrollToPosition?
      

  2.   

    求鼠标位置,或者求移动后物体的位置,根据位置判断是否已经到当前clientrect的边了,如果在边上,那么,移动,也就是取得当前的scroll的位置,然后加上偏移量,调用ScrollToPosition
    这些应该在onmousemove里面做的
      

  3.   

    选中物体,按住鼠标左键拖动物体,在onmousemove里面,根据当前鼠标点判断当前物体的偏移量,然后,改变物体的位置,当到达边界的时候,通过改动当前的scroll来确定新位置。
      

  4.   

    对啊,判断是否到边界了,这个是好办的,关键是,如果到了以后,就要让滚动条一直不停的滚动,问题就是如何让CScorllBar不停的滚动,直到不能滚动了为止。难不成是用个timer,不停的ScrollToPosition?
      

  5.   

    如果想要不停的动,最好用定时器,隔段时间判断一次,执行一次
    实际上,如果scrollbar范围比较大的话,要翻很多页的时候,我们点击scroll的一端,scroll不停的滚动,这也是用的定时器。
      

  6.   

    当然是Timer了。在Timer里面控制 Scroll view的POS。
      

  7.   

    当第一次判断到边界的时候,同时也启动timer,一直到鼠标松开或者scroll移动的极限值的时候,再干掉timer(这是ontime里面调用killtimer).
      

  8.   

    当鼠标点下开始拖动的时候,要setcapture,然后,即使鼠标移动到方框外,也不要紧,鼠标松开的时候,也一样要判断timer是否被干掉,如果没有被干掉,要干掉timer;
    不过,有一种是这样的,拖动到边缘的时候,scroll改变一下位置后,同时把鼠标设置到clientrect里面,如果人为不动鼠标,就不改变scroll.........所以,应该是两种情况,一种是靠近边缘,那么,只是改变scroll一次,同时设置鼠标到clientrect里面的一定位置(一般为scroll改变的距离),等待用户再次移动鼠标。另外一种,当达到scroll的边界的时候或者已经移出clientrect的时候,这时要用定时器了。
      

  9.   

    当然要明白处理对象的大小,位置,才能决定怎样scroll
      

  10.   

    感谢各位在牛!
    我ScrollToPosition(10,10),我怎么知道移动了多少像素,因为我移动的时候画了一个虚框,改变滚动条位置的时候,这个框的位置也要变化。
      

  11.   

    首先取得当前scroll的位置,用 POINT ptScroll = GetScrollPosition()得到当前的scroll的左上点,然后,加上你的平移量,ptScroll+POINT(10,0);//向右偏移10
    再设置回去ScrollToPosition(ptScroll);你计算你的数据的时候,必须要考虑到GetScrollPosition(),当前clientrect里面显示的,应该是GetClientRect偏移GetScrollPosition()所包含的所有数据
    所以,改变了scroll后,你只需要重新设置鼠标位置即可。
      

  12.   

    比如我拖动一个对象时,这个时候移动鼠标,在新的位置出现一个虚框,当虚框移至边界时,触发定时器,
    CPoint _point = GetScrollPosition();
    CPoint pt(_point.x+10,_point.y);
    ScrollToPosition(pt);
    这个时候我只需要计算这个虚框的位置,重画它,对吧。现在是如何计算这个虚框的坐标,比如ScrollToPosition(10,0);这个虚框要移动多少像素呢?
      

  13.   

    实际物体的坐标,应该是当前的mousemove的鼠标点加上GetScrollPosition()
    而在画的时候,是鼠标的坐标减去GetScrollPosition()
      

  14.   

    现在的问题是当滚动条滚动时,我画的虚框总是有重影。
    我的虚框是这样画的。
    进入到timer后,首先擦掉最后一次的虚框。CClientDC dc(this);
    dc.DrawFocusRect(rect);
    //
    CPoint point = GetScrollPosition();
    CPoint pt(point.x+10,point.y);
    ScrollToPosition(pt);
    //在新的地方再画,其实和上面的坐标一样,都是逻辑坐标
    dc.DrawFocusRect(rect);大致是这样,我看了坐标都没错,但是就是有重影,不知道为啥。
      

  15.   

    下面我是我做的现成例子,用于拖动和改变大小。
    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;
    }
      

  16.   

    真奇怪,用ScrollToPosition(pt);不行,向滚动条发消息则可以。
      

  17.   

    ScrollToPosition后面,好像要调用Invalidate之类的刷新吧
      

  18.   

    如果是这样的话,那还必须调整光标的位置,是吧。因为滚动后,光标的位置没变,DrawFocusRect的位置变了。
      

  19.   


    SetScrollSizes(MM_TEXT, m_layout, m_page, m_line);
    int yPos = GetScrollPos(SB_VERT);ypos的值为什么会超过m_page.cy的值呢,而且还超过很多。
      

  20.   

    SetScrollSizes(...)
    ResizeParentToFit();
    int yPos = GetScrollPos(SB_VERT);这样试试
      

  21.   

    原理很简单,发现到边界,先用以前的值重绘一下焦点矩形,因为焦点矩形有XOR的特性,所以用相同坐标绘,是擦除,然后根据边界情况,发滚屏消息,滚屏后重新计算焦点矩形的新位置,再绘,这时就是绘了,因为是第一绘。
    不要用ScrollView提供的那些来操作滚动条,包括获得滚动条信息,用API的,我一直这样用