界面控件 - 滚动条ScrollBar

本文介绍如何扩展Windows滚动条,模仿VS2015代码编辑器的MinMap功能。通过自定义滚动条结构SCROLLINFO,计算滚动数量、滑块尺寸和位置,响应鼠标点击、拖拽及滚轮消息,实现高效的人机交互,提高代码定位效率。
摘要由CSDN通过智能技术生成

界面是人机交互的门户,对产品至关重要。在界面开发中只有想不到没有做不到的,有好的想法,当然要尝试着做出来。对滚动条的扩展,现在有很多类是的例子。

VS2015的代码编辑是非常强大的,其中有一个功能可以把滚动态变成MinMap,可以通过Options->Text Editor->C/C++->Scroll Bars中的Behavior选项分类进行打开。

sublime也有这个功能,但没有VS的好用。变成MinMap后整个代码文档变成一个完整的缩微图,在你对代码比较熟悉的情况下,可以非常容易判断并定位到大致的函数位置。同时对特殊状态,如:错误信息,更新信息等进行标识。只要看一眼滚动条就能知道当前文档的情况,可以快速定位到相关文档位置。

优点多多: 当一个文件内容比较长时,在上面标注相关重要内容是非常方便的。用于只要一看滚动条上的相关标示,就能知道相关信息。不用再开辟窗口告诉用户,他想得到的有关信息。

VS可作参考,做这个就比较容易。不知道微软有没有注册版权-_-!!。因此想到扩展Scroll Bar是个不错的主意,但windows系统并没有给这个机会,一般的窗口类都自带系统滚动条。系统自带的完全无法做出这种效果,只能自己做一个覆盖系统默认滚动条。

一、滚动条结构SCROLLINFO

typedef struct tagSCROLLINFO {
  UINT cbSize;    // 结构尺寸
  UINT fMask;     // 需要处理或返回的相关选项参数
  int  nMin;      // 滚动条的最小值
  int  nMax;      // 最大滚动范围
  UINT nPage;     // 一页有效行数
  int  nPos;      // 当前滚动条
  int  nTrackPos; // 拖拽滚筒条时的位置
} SCROLLINFO, *LPCSCROLLINFO;

正常我们用到的的滚动条有下面一些元素,画了张图更容易理解点。

可以看到如果我们默认最小值=0时,实际需要的只有三个滚动条参数,最大可以滚动的范围nMax,一页可显示的行数nPage 和 当前行的显示位置nPos 这三个参数。

1、滚动数量计算

如滚动条能正常滚动到最后一行的位置。有100行记录,滚动最下面界面显示最后一行。为方便计算没条记录的行高固定。

  • nPage = ClientHeight / rowHeight
  • nMax = rowCount - 1 + nPage - 1

正常情况计算是总行数-1, 就是 nMax的值,应为要允许滚动到记录最后一条,因此需要多加一页的滚动数量。就产生了上面的nMax的公式。

// 只要超过1行就能滚动,因此需要多加一页的行数。
si.nMax   = rowCount - 1 + yClient / rowHeight - 1;
si.nPage  = yClient / rowHeight;

2、滑块尺寸计算

滑块的尺寸的尺寸按照上图的定义,滚动条的高度除以滚动范围再乘上每页数量可以得到。

滑块尺寸 = 滚动条高度 / 有效范围 * 每页数量

上述计算公式存在另外一个问题,如果记录量很大时就杯具,滑块会非常小,用户很难用鼠标抓到滑块。眼神犀利和伸手敏捷的才能完成这种艰巨任务。因此为滑容易定位的最小值。

 s = max((float)((r.bottom - r.top) / (si.nMax - si.nMin) * si.nPage), 20.0f);

3、滑块位置计算

在图上看滑块有效的滑动位置是需要扣除滑块的大小的。

实际滑动位置 = (滚动条高度 - 滑块尺寸) / (有效范围 - 每页数量 + 1) * 当前行位置

有除法,就会存一些精度问题,所以算出位置后要检查一下位置是否超出客户区。

v = 0;
if (si.nPos > 0) 
    v = (int)((r.bottom - r.top - s) / (float)(si.nMax - si
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值