(WIN32 滚动条) SetScrollInfo 函数

分析SetScrollInfo 中不懂的部分

WM_SIZE:
cyClient = HIWORD(lParam);

si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE;
si.nMin = 0;
si.nMax = NUMLINES-1;
si.nPage = cyClient/cyChar;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);

这里的 si.nMax 自动设置为 si.nMax - si.nPage + 1  即 NUMLINES - 1 - cyClient / cyChar + 1

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

GetScrollInfo()获取滚动条的信息

iVertPos = si.nPos; //保存改变前的si.nPos值

//省略....进入switch判断,根据在滚动框上的相应的操作,把结果保存在si.nPos中

si.fMask = SIF_POS;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);	//设置滚动条位置为si.nPos
GetScrollInfo(hwnd, SB_VERT, &si);		//获取滚动条信息
if(si.nPos != iVertPos)
{
	ScrollWindows(hwnd,0,cyChar * (iVertPos - si.nPos),NULL,NULL);  //滚动客户区的内容
	UpdateWindow(hwnd);
}
WM_PAINT:

假设,一共有75行信息(0行到74行)需要显示,客户区能显示50行(0行到49行)。滚动条原来的位置是0。

用户把滚动条向下移动了两行,也就是说客户区的信息要向上移动两行,这个时候第0行,第1行已经看不见了,

客户区顶部显示的是第2行的信息,而原来显示在客户区最后一行的第49行升到第47行了。

这个时候第48行,第49行变成了空白区域

ps.rcPaint.top   	//是该空白区域的左上角坐标。
ps.rcPaint.top/cyChar 	//就成了空白区域最上面一行的行数,跟据上面的假设,这是第48行。

客户区内容上移了两行,所以原来48行的位置上显示第50行的内容。然后在第49行显示的是第51行的内容。

现在客户区显示了第2 ----- 51行的内容。

ps.rcPaint.bottom/cyChar 	//是空白区域最后一行的显示位置。
iPaintBeg = max (0, iVertPos + ps.rcPaint.top / cyChar) ;
iPaintEnd = min (NUMLINES - 1, iVertPos + ps.rcPaint.bottom / cyChar) ;

但是我们可以看到在 ps.rcPaint.top / cyChar 前面还要加上iVertPos,这是为什么呢?

虽然是第48行,但是要显示的内容是原来第50行的。在第48行显示第50行的内容,所以要加上移动的行数iVertPos,

这里iVertPos是2,所以正好能在第48行显示50行的内容。

进入for循环:这个时候iPaintBeg的值是50,iPaintEnd的值是52。

y = cyChar * (i-iVertPos);

 y的值变成了48,第50行信息的显示位置是48,

然后就是使用TextOut()显示文本串了。

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

要显示的是第i行的内容,也就是第50行的内容,显示坐标y是第48行的坐标,所以程序将第50行的内容显示到第48行上,以此类推。

WM_PAINT代码确定无效区域中的行,并仅仅重画这些行。代码复杂但速度快。

你可能感兴趣的:(Windows程序设计)