鱼C论坛

 找回密码
 立即注册
查看: 15284|回复: 23

[API档案] ScrollWindow

[复制链接]
发表于 2014-8-8 15:45:43 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
函数功能:

ScrollWindow 函数滚动指定窗口的客户区内容。

注意:该函数提供了向后兼容性,新的应用程序应该使用 ScrollWindowsEx 函数代替。


API 函数原型:

注释:_In_ 说明该参数是输入的,_opt_ 说明该参数是可选参数。

  1. BOOL ScrollWindow(
  2.   _In_  HWND hWnd,
  3.   _In_  int XAmount,
  4.   _In_  int YAmount,
  5.   _In_  const RECT *lpRect,
  6.   _In_  const RECT *lpClipRect
  7. );
复制代码


参数解析:

参数 含义
hWnd 指向客户区将被滚动的窗口句柄
XAmount 1. 在设备单元中,指定水平滚动的数量
2. 如果窗口类风格为 CS_OWNDC 或 CS_CLASSDC,则此参数则使用逻辑单元而非设备单元
3. 当向左滚动窗口的内容时,该参数的值必须是负数
YAmount 1. 在设备单元中,指定垂直滚动的数量
2. 如果窗口类风格为 CS_OWNDC 或 CS_CLASSDC,则此参数则使用逻辑单元而非设备单元
3. 当向上滚动窗口的内容时,该参数的值必须是负数
lpRect 1. 指向 RECT 结构指针,该结构指定了将要滚动的客户区范围
2. 如果此参数为 NULL,则整个客户区域将被滚动
lpClipRect 1. 指向 RECT 结构指针,该结构指定了要滚动的裁剪区域
2. 只有这个矩形中的内容才会被滚动(在矩形之外的内容不会被影响,即使它们是在 lpRect 指定的矩形之内)


返回值:

1. 如果函数调用成功,返回值是非 0;

2. 如果函数调用失败,返回值是 0。


备注:

1. 如果在被滚动的窗口中含有插入符,ScrollWindow 函数将自动隐藏插入符,以防它被擦掉。当滚动结束后再恢复插入符,插入符的位置相应的被调整。

2. 未被 ScrollWindow 函数覆盖的区域不会被重绘,但该区域会与窗口更新区域组合,当应用程序最终收到 WM_PAINT 的消息时,组合区域统一重绘。为了在滚动操作的同时重画未覆盖区域,则应在调用 ScrollWindow 函数后马上调用 UpdateWindow 函数。

3. 如果 lpRect 参数的值为 NULL,则窗口中的任何子窗口的位置由参数 XAmount 和 Yamount 的数值决定移动距离;窗口中无效的区域(未重绘)也会移动。

4. 当 lpRect 参数为 NULL 时,ScrollWindow 函数可以执行得更快。

5. 如果 lpRect 参数不为 NULL,则窗口中的子窗口的位置不改变,窗口中无效的区域(未重绘)也不移动。为了防止 lpRect 参数不为 NULL 时更新的问题,需要在调用 ScrollWindow 函数调用 UpdateWindow 函数重绘窗口。

【API档案】版权归鱼C工作室(www.fishc.com)所有,转载请注明来源。

感叹下:能把例子都认真翻译过来的...才是真正的情怀吖......


  1. /* -------------------------------------------------------------------
  2.                  【API档案】ScrollWindow 函数使用例子
  3.                      鱼C工作室 -- www.fishc.com
  4. --------------------------------------------------------------------*/
  5. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  6. {
  7.         HDC hdc;
  8.         PAINTSTRUCT ps;
  9.         TEXTMETRIC tm;
  10.         SCROLLINFO si;

  11.         static int xClient;     // 客户区的宽度
  12.         static int yClient;     // 客户区的高度
  13.         static int xClientMax;  // 客户区内容显示的最大宽度(超过此宽度则加入滚动条)

  14.         static int xChar;       // 字体的平均水平宽度
  15.         static int yChar;       // 字体的垂直高度
  16.         static int xUpper;      // 字体的大写字符的水平宽度

  17.         static int xPos;        // 当前水平滚动条滑块的位置
  18.         static int yPos;        // 当前垂直滚动条滑块的位置

  19.         int i;                  // 循环计数器
  20.         int x, y;               // 水平和垂直的坐标

  21.         int FirstLine;          // 失效区域的第一行(需重绘的第一行)
  22.         int LastLine;           // 失效区域的最后一行((需重绘的最后一行))
  23.         HRESULT hr;
  24.         size_t abcLength;       // 用于存放 abc 数组的长度

  25.         // 创建要显示的行(呃,打印的内容我就不翻译了吧...)
  26.         #define LINES 28
  27.         static TCHAR *abc[] = {
  28.                 TEXT("anteater"), TEXT("bear"), TEXT("cougar"),
  29.                 TEXT("dingo"), TEXT("elephant"), TEXT("falcon"),
  30.                 TEXT("gazelle"), TEXT("hyena"), TEXT("iguana"),
  31.                 TEXT("jackal"), TEXT("kangaroo"), TEXT("llama"),
  32.                 TEXT("moose"), TEXT("newt"), TEXT("octopus"),
  33.                 TEXT("penguin"), TEXT("quail"), TEXT("rat"),
  34.                 TEXT("squid"), TEXT("tortoise"), TEXT("urus"),
  35.                 TEXT("vole"), TEXT("walrus"), TEXT("xylophone"),
  36.                 TEXT("yak"), TEXT("zebra"),
  37.                 TEXT("This line contains words, but no character. Go figure."),
  38.                 TEXT("")
  39.         };

  40.         switch (message)
  41.         {
  42.         case WM_CREATE:
  43.                 // 获得设备环境句柄
  44.                 hdc = GetDC(hwnd);

  45.                 // 获得文本中字体的大小
  46.                 GetTextMetrics(hdc, &tm);
  47.                 xChar = tm.tmAveCharWidth;
  48.                 xUpper = (tm.tmPitchAndFamily & 1 ? 3 : 2) * xChar / 2;
  49.                 yChar = tm.tmHeight + tm.tmExternalLeading;

  50.                 // 释放设备环境句柄
  51.                 ReleaseDC(hwnd, hdc);

  52.                 // 设置客户区的最大宽度
  53.                 // (我们这里设置为 48 个小写字符的宽度 + 12 个大写字符的宽度)
  54.                 xClientMax = 48 * xChar + 12 * xUpper;

  55.                 return 0;

  56.         case WM_SIZE:
  57.                 // 获得客户区的尺寸
  58.                 yClient = HIWORD(lParam);
  59.                 xClient = LOWORD(lParam);

  60.                 // 设置垂直滚动条范围和页面大小(设置页面大小将决定滑块的粗细)
  61.                 si.cbSize = sizeof(si);
  62.                 si.fMask = SIF_RANGE | SIF_PAGE;
  63.                 si.nMin = 0;
  64.                 si.nMax = LINES - 1;
  65.                 si.nPage = yClient / yChar;
  66.                 SetScrollInfo(hwnd, SB_VERT, &si, TRUE);

  67.                 // 设置水平滚动条范围和页面大小(设置页面大小将决定滑块的粗细)
  68.                 si.cbSize = sizeof(si);
  69.                 si.fMask = SIF_RANGE | SIF_PAGE;
  70.                 si.nMin = 0;
  71.                 si.nMax = 2 + xClientMax / xChar;
  72.                 si.nPage = xClient / xChar;
  73.                 SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);

  74.                 return 0;
  75.         case WM_HSCROLL:
  76.                 // 获得水平滚动条的所有信息
  77.                 si.cbSize = sizeof (si);
  78.                 si.fMask = SIF_ALL;
  79.                 GetScrollInfo(hwnd, SB_HORZ, &si);

  80.                 // 保存当前滑块位置,迟些进行比较
  81.                 xPos = si.nPos;
  82.                 switch (LOWORD(wParam))
  83.                 {
  84.                         // 用户点击滚动条左边的三角形
  85.                 case SB_LINELEFT:
  86.                         si.nPos -= 1;
  87.                         break;

  88.                         // 用户点击滚动条右边的三角形
  89.                 case SB_LINERIGHT:
  90.                         si.nPos += 1;
  91.                         break;

  92.                         // 用户点击滑块左边的滚动条轴
  93.                 case SB_PAGELEFT:
  94.                         si.nPos -= si.nPage;
  95.                         break;

  96.                         // 用户点击滑块右边的滚动条轴
  97.                 case SB_PAGERIGHT:
  98.                         si.nPos += si.nPage;
  99.                         break;

  100.                         // 用户拖动滚动条
  101.                 case SB_THUMBTRACK:
  102.                         si.nPos = si.nTrackPos;
  103.                         break;

  104.                 default:
  105.                         break;
  106.                 }

  107.                 // 设置滚动条滑块的新位置
  108.                 si.fMask = SIF_POS;
  109.                 SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);

  110.                 // 获得滚动条滑块的位置,由于窗口调整,它可能不是同一个值
  111.                 GetScrollInfo(hwnd, SB_HORZ, &si);

  112.                 // 与此前的保存的值进行比较,如果不同则滚动窗口
  113.                 if (si.nPos != xPos)
  114.                 {
  115.                         ScrollWindow(hwnd, xChar * (xPos - si.nPos), 0, NULL, NULL);
  116.                 }

  117.                 return 0;

  118.         case WM_VSCROLL:
  119.                 // 获得垂直滚动条的所有信息
  120.                 si.cbSize = sizeof (si);
  121.                 si.fMask = SIF_ALL;
  122.                 GetScrollInfo(hwnd, SB_VERT, &si);

  123.                 // 保存当前滑块位置,迟些进行比较
  124.                 yPos = si.nPos;
  125.                 switch (LOWORD(wParam))
  126.                 {
  127.                         // 用户点击键盘 Home 按键
  128.                 case SB_TOP:
  129.                         si.nPos = si.nMin;
  130.                         break;

  131.                         // 用户点击键盘 End 按键
  132.                 case SB_BOTTOM:
  133.                         si.nPos = si.nMax;
  134.                         break;

  135.                         // 用户点击滚动条上边的三角形
  136.                 case SB_LINEUP:
  137.                         si.nPos -= 1;
  138.                         break;

  139.                         // 用户点击滚动条下边的三角形
  140.                 case SB_LINEDOWN:
  141.                         si.nPos += 1;
  142.                         break;

  143.                         // 用户点击滑块上边的滚动条轴
  144.                 case SB_PAGEUP:
  145.                         si.nPos -= si.nPage;
  146.                         break;

  147.                         // 用户点击滑块下边的滚动条轴
  148.                 case SB_PAGEDOWN:
  149.                         si.nPos += si.nPage;
  150.                         break;

  151.                         // 用户拖动滚动条
  152.                 case SB_THUMBTRACK:
  153.                         si.nPos = si.nTrackPos;
  154.                         break;

  155.                 default:
  156.                         break;
  157.                 }

  158.                 // 设置滚动条滑块的新位置
  159.                 si.fMask = SIF_POS;
  160.                 SetScrollInfo(hwnd, SB_VERT, &si, TRUE);

  161.                 // 获得滚动条滑块的位置,由于窗口调整,它可能不是同一个值
  162.                 GetScrollInfo(hwnd, SB_VERT, &si);

  163.                 // 与此前的保存的值进行比较,如果不同则滚动窗口
  164.                 if (si.nPos != yPos)
  165.                 {
  166.                         ScrollWindow(hwnd, 0, yChar * (yPos - si.nPos), NULL, NULL);
  167.                         UpdateWindow(hwnd);
  168.                 }

  169.                 return 0;

  170.         case WM_PAINT:
  171.                 // 准备绘制
  172.                 hdc = BeginPaint(hwnd, &ps);

  173.                 // 获得垂直滚动条的位置
  174.                 si.cbSize = sizeof (si);
  175.                 si.fMask = SIF_POS;
  176.                 GetScrollInfo(hwnd, SB_VERT, &si);
  177.                 yPos = si.nPos;

  178.                 // 获得水平滚动条的位置
  179.                 GetScrollInfo(hwnd, SB_HORZ, &si);
  180.                 xPos = si.nPos;

  181.                 // 计算需要重绘的区域
  182.                 FirstLine = max(0, yPos + ps.rcPaint.top / yChar);
  183.                 LastLine = min(LINES - 1, yPos + ps.rcPaint.bottom / yChar);

  184.                 for (i = FirstLine; i <= LastLine; i++)
  185.                 {
  186.                         x = xChar * (1 - xPos);
  187.                         y = yChar * (i - yPos);

  188.                         // 使用安全字符串函数获得字符串长度
  189.                         hr = StringCchLength(abc[i], 55, &abcLength);
  190.                         if ((FAILED(hr)) | (abcLength == NULL))
  191.                         {
  192.                                 // 获取字符串长度失败的提示...
  193.                         }

  194.                         // 在客户区绘制一行数据
  195.                         TextOut(hdc, x, y, abc[i], abcLength);
  196.                 }

  197.                 // 绘制完毕
  198.                 EndPaint(hwnd, &ps);
  199.                 return 0;

  200.         case WM_DESTROY:
  201.                 PostQuitMessage(0);
  202.                 return 0;
  203.         }

  204.         return DefWindowProc(hwnd, message, wParam, lParam);
  205. }
复制代码

如在使用上有任何不同,可以参考小甲鱼的《Windows程序设计(SDK)》第 14 讲:滚动条3


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-11-5 14:23:00 | 显示全部楼层
感叹下:能把例子都认真翻译过来的...才是真正的情怀吖......
    感谢!鱼哥!辛苦了.......
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-12-20 13:17:02 | 显示全部楼层
鱼哥,为什么我运行后好多错误?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-2-11 21:03:24 | 显示全部楼层
lver 发表于 2014-12-20 13:17
鱼哥,为什么我运行后好多错误?

字符打错了,检查下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-2-12 12:00:50 | 显示全部楼层
照着打 了一遍,记不住怎么办,尤其是计算字符宽高啊,滚动条的宽高啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-5-7 15:29:19 | 显示全部楼层
慢慢学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-7 18:35:58 | 显示全部楼层
再次多谢甲鱼
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-14 17:35:44 | 显示全部楼层
甲鱼哥,WM_PAINT中的x = cxChar  * (1 - xPos)这一行是怎么个情形不是很理解,就卡在着一行里了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-8-14 11:13:35 | 显示全部楼层
水平的坐标:1-xPos  这是相对水平第二个位置(第一个位置是0嘛,空两格,写文章开头都空两格啦)的距离,如果这里是i-xPos的话,那每一行的起始位置都不一样咯,文字就是斜的,就成了阶梯式了。说到底就是水平坐标要一致

而垂直坐标就不一样了,因为每一行的垂直坐标都不一行。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2015-8-14 11:14:33 | 显示全部楼层
倚窗听雨 发表于 2015-6-14 17:35
甲鱼哥,WM_PAINT中的x = cxChar  * (1 - xPos)这一行是怎么个情形不是很理解,就卡在着一行里了

水平的坐标:1-xPos  这是相对水平第二个位置(第一个位置是0嘛,空两格,写文章开头都空两格啦)的距离,如果这里是i-xPos的话,那每一行的起始位置都不一样咯,文字就是斜的,就成了阶梯式了。说到底就是水平坐标要一致

而垂直坐标就不一样了,因为每一行的垂直坐标都不一行。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-8-28 21:44:13 | 显示全部楼层
对于水平滚动条,有诸多不理解,为什么跟垂直滚动条不一样呢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-7-2 02:59:59 | 显示全部楼层
XAmount和yAmount解释有问题,明明是移动的负值,向右移动才是负数
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-7-11 16:43:07 | 显示全部楼层
在学这课的时候,明显体会到,一个程序或者是功能的完善是windows和程序员
协同完成的。滚动条的编程这一点体现的非常的突出。你必须了解windows帮你完成了
什么,你自己需要完成什么。这样才能完善整个功能。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-7-11 18:04:34 | 显示全部楼层
宋桓公 发表于 2016-7-11 16:43
在学这课的时候,明显体会到,一个程序或者是功能的完善是windows和程序员
协同完成的。滚动条的编程这一 ...

总结得很好,其实耐心学完 SDK,再来看大多数的应用,也就是那么回事~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-7-12 08:08:16 | 显示全部楼层
小甲鱼 发表于 2016-7-11 18:04
总结得很好,其实耐心学完 SDK,再来看大多数的应用,也就是那么回事~


好的~~~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-8-3 17:34:07 | 显示全部楼层
各位大虾谁能告诉我为什么不在   WM_VSCROLL:  消息后面的  UpdateWindow(hwnd);加上  InvalidateRect(hwnd, NULL, TRUE);
就不能实时更新?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-10-24 12:31:37 | 显示全部楼层
问下代码里有一段这样写 x=xChar*(1-xPos);还是x=xChar*(i-xPos);
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-1-14 22:42:40 | 显示全部楼层
HRESULT 这个是啥?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-11-5 23:11:34 | 显示全部楼层
编译不通过
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-17 21:47:33 | 显示全部楼层
这是啥
错误(活动)        E0144        "const wchar_t *" 类型的值不能用于初始化 "TCHAR *" 类型的实体        one        C:\Users\zc970\source\repos\one\one\源.cpp        93       
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-20 15:06

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表