windows程序设计上4.4.3新的sysmets上的例子的部分源码
大概讲解一下这个例子的用途,使用了setscrollinfo等函数来滚动客户区域.  iPaintBeg ,iPaintEnd 分别是是什么意思呢?
为了彻底搞清楚意思,我用日志来记录其只,然后观察推测,(1)当程序执行后,日志里的值为:
iPaintBeg:0--------iPaintEnd:45, iVerPos:0(2)当我点击垂直滚动条的时候,日志的值为:
iPaintBeg:45--------iPaintEnd:46, iVerPos:1
注意45---46,说明循环执行两次!!! 你向下点击一下滚动条,结果执行2次循环
点击一次,其实根本就意味着客户区域里的内容向上移动一行!!! 所有内容都得移动,但是代码跟踪挑时候,发现才执行了2次, 请问如何做到,所有内容都向上移动一行??? case WM_PAINT :
{
hdc = BeginPaint (hwnd, &ps) ;

// Get vertical scroll bar position

si.cbSize = sizeof (si) ;
si.fMask  = SIF_POS ;
GetScrollInfo (hwnd, SB_VERT, &si) ;
iVertPos = si.nPos ;

// Get horizontal scroll bar position

GetScrollInfo (hwnd, SB_HORZ, &si) ;
iHorzPos = si.nPos ;

// Find painting limits



iPaintBeg = max (0, iVertPos + ps.rcPaint.top / cyChar) ;
iPaintEnd = min (NUMLINES - 1,
iVertPos + ps.rcPaint.bottom / cyChar) ; char buf[100]={0};
sprintf(buf,"iPaintBeg:%d--------iPaintEnd:%d, iVerPos:%d\r\n", iPaintBeg, iPaintEnd,iVertPos);
if(g_File.m_hFile!=INVALID_HANDLE_VALUE)
{
g_File.Write(buf,strlen(buf));
}

for (i = iPaintBeg ; i <= iPaintEnd ; i++)
{
x = cxChar * (1 - iHorzPos) ;
y = cyChar * (i - iVertPos) ;

TextOut (hdc, x, y,
sysmetrics[i].szLabel,
lstrlen (sysmetrics[i].szLabel)) ;

TextOut (hdc, x + 22 * cxCaps, y,
sysmetrics[i].szDesc,
lstrlen (sysmetrics[i].szDesc)) ;

SetTextAlign (hdc, TA_RIGHT | TA_TOP) ;

TextOut (hdc, x + 22 * cxCaps + 40 * cxChar, y, szBuffer,
wsprintf (szBuffer, TEXT ("%5d"),
GetSystemMetrics (sysmetrics[i].iIndex))) ;

SetTextAlign (hdc, TA_LEFT | TA_TOP) ;
}

EndPaint (hwnd, &ps) ;

}
return 0 ;

解决方案 »

  1.   

    设置映射text!
    然后设置setwindoworign
    之后刷新
      

  2.   

    ScrollWindow(Ex),MSDN上有个滚动文本的例子代码
      

  3.   


    我知道scrollwindow这个函数 msdn有例子。but,,but我问的不是这个,我是在问:你当你点击垂直滚动条的时候,  getscrollinfo,setscrollinfo , getscrollinfo等操作设置滚动条,然后调用scrollwindo( 距离)  触发wm_paint开始执行case wm_paint里的代码。我的问题是 wm_paint里的那2个变量到底是什么???为什么只需要执行2次,就可以把所有的内容都向上移动一行?
      

  4.   

    “所有内容都向上移动一行”
    这个 任务 是 SCrollWindow 完成的,SCrollWindow 对 显示器 直接 操作,操作完成后(非常快),就 产生了 下面 一行 空 的 区域,这个 是 程序 需要 重绘的 区域。注意只有 一行 要 重绘
    所以 如果 控件 有 背景图的 话, 最后那行的背景 要 根据 滚动条 位置来 确定 相应 位置。
      

  5.   

    请参考“带固定行的ListBox.rar”0 分
    http://download.csdn.net/detail/schlafenhamster/5019808
      

  6.   


    就算scrollwindow帮你完成了这些工作, 可是  for循环为什么执行2次,而不是一次?提供一段代码: case WM_VSCROLL:
    // Get all the vertial scroll bar information

    si.cbSize = sizeof (si) ;
    si.fMask  = SIF_ALL ;
    GetScrollInfo (hwnd, SB_VERT, &si) ;

    // Save the position for comparison later on

    iVertPos = si.nPos ;

    switch (LOWORD (wParam))
    {
    case SB_TOP:
    si.nPos = si.nMin ;
    break ;

    case SB_BOTTOM:
    si.nPos = si.nMax ;
    break ;

    case SB_LINEUP:
    si.nPos -= 1 ;
    break ;

    case SB_LINEDOWN:
    si.nPos += 1 ;
    break ;

    case SB_PAGEUP:
    si.nPos -= si.nPage ;
    break ;

    case SB_PAGEDOWN:
    si.nPos += si.nPage ;
    break ;

    case SB_THUMBTRACK:
    si.nPos = si.nTrackPos ;
    break ;

    default:
    break ;         
    }
    // Set the position and then retrieve it.  Due to adjustments
    //   by Windows it may not be the same as the value set.

    si.fMask = SIF_POS ;
    SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;
    GetScrollInfo (hwnd, SB_VERT, &si) ;

    // If the position has changed, scroll the window and update it

    if (si.nPos != iVertPos)
    {   char buf[100]={0};
    sprintf(buf,"ScrollWindow函数中的第3个参数的 iVertPos - si.nPos的值为:%d\r\n",iVertPos - si.nPos); if(g_File.m_hFile!=INVALID_HANDLE_VALUE)
    {
    g_File.Write(buf,strlen(buf));
    }
    ScrollWindow (hwnd, 0, cyChar * (iVertPos - si.nPos), 
    NULL, NULL) ;
    UpdateWindow (hwnd) ;
    }
    return 0 ;日志记录可以显示 ,当你点击向下的滚动条的时候,iVerPos-si.nPos 的值为-1, 则说明待需要滚动的是一样。而for循环2次。       这个逻辑我难以理解
      

  7.   

    说明“for (i = iPaintBeg ; i <= iPaintEnd ; i++)”有问题,
    是不是 i <= iPaintEnd 应该是 i < iPaintEnd
      

  8.   

    哎, 怎么都跟扯淡似的, 这很复杂吗?  滚动条只是一个记录了滚动块当前位置的控件, 当用户点击滚动条, 它向窗口发送一个WM_VSCROLL或WM_HSCROLL消息, 用户可以在这两个消息里面完成窗口的相应绘制或者调用InvalidateRect函数然后再WM_PAINT里面绘制;比如楼主贴的例子, iPaintBeg 和 iPaintEnd不过是记录了需要输出内容的行号而已, 这两个值根据滚动条的位置来确定, 然后把这些行输出到窗口中。
     这种方法与ScrollWindow是不同的, ScrollWindow是改变窗口到视口坐标的映射, 然后重绘以达到滚动窗口的效果。
    就是这么简单, 不要想太复杂了。
      

  9.   

    WM_VSCROLL或WM_HSCROLL消息
    最后调ScrollWindow明白吗?
      

  10.   


    这里你当然可以调用, 但是这个不是必然的, SrollWindow只是一种方法,其原理是改变窗口视口坐标映射, 你也可以自己用SetROP2, SetWindowOrigin, SetViewportOrigin等函数+加上InvalidateRect达到同样效果, 另外你也可以根据滚动条的位置自己重画, 方法是多种多样的, 楼主的例子明显就是重画的。 
      

  11.   

    "SrollWindow只是一种方法,其原理是改变窗口视口坐标映射"
    WM_VSCROLL或WM_HSCROLL 前 后
    调用GetWindowOrigin, GetViewportOrigin 看看变了没有