内建滚动条的绘制

        内建滚动条的绘制网上流行的解决方案有两种:一种是使用另外自绘的滚动条控件覆盖系统提供的滚动条;另一种是使用HOOK 滚动条API的方式实现的。第一种方案的缺点是凭白多一个窗口让人心里不爽。第一种方案的缺点是HOOK API太麻烦,如果不HOOK API直接在原来的滚动条区域绘制我们自己的滚动条的话,会出现严重的闪烁问题。有没有更好的解决方案呢???假如我们能把系统滚动条的区域给隐藏起来,给出我们自己滚动条的区域,在我们自己滚动条区域绘制我们的滚动条,系统的滚动条就是绘制我们也看不到,因为我们已经把系统滚动条的区域给隐藏起来了。WM_NCCALCSIZE满足我们的需求。以ListBox的垂直滚动条为例,我完美隐藏了系统的垂直滚动条区域,并且绘制了自己的滚动条。如图:

        绘制内建的滚动条我们面临的最大问题就是如何隐藏系统的滚动条不让他绘制。可下人间的新浪博客《CListCtrl控件功能扩展总结(三)》一文中给出的解决方案是在每次重新计算窗口的客户区域的时候都调用ModifyStyle设置scroll风格才行,这样CListCtrl将没有机会自动为窗口加上滚动条代码如下:

    void CXXListCtrl::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)             
    {                                                                                               
        ModifyStyle( WS_HSCROLL | WS_VSCROLL, 0 ); // 去掉水平滚动条和竖直滚动条                   
        CListCtrl::OnNcCalcSize(bCalcValidRects, lpncsp);                                          
    }                                 

       这样能去掉系统的滚动条的原因是当没有出现滚动条时内建滚动条的控件是不具有WS_HSCROLL或WS_VSCROLL属性的,出现滚动条时系统会自动的给该控件加上WS_HSCROLL或WS_VSCROLL属性并且发送WM_NCCALCSIZE消息;反之去掉WS_HSCROLL或WS_VSCROLL属性并且发送WM_NCCALCSIZE消息并且发送WM_NCCALCSIZE消息。这也是我们一开始就去掉WS_HSCROLL或WS_VSCROLL属性不起作用的原因(刚开始控件都是没有内建滚动条的)。

       当有滚动条时使用ModifyStyle(WS_HSCROLL|WS_VSCROLL,0);能去掉滚动条的原理是系统也会发送WM_NCCALCSIZE消息重新计算了客户区域,系统滚动条是在非客户区域绘制的,系统滚动条的区域被划分成了客户区域,系统滚动条及还是在非客户区域绘制了,但用户看不到了。知道了这一点我们可以不调用ModifyStyle(WS_HSCROLL|WS_VSCROLL);我们自己直接手动调整客户区域就可以隐藏系统滚动条(有现成的不用,我有病啊???当然没病!!!直接调用的话我们就得不到系统滚动条的滚动数据了,我们并不是真的想去掉系统滚动条,只想把它藏起来!!!)。

void CListBoxEx::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)

{

     // TODO: Add your message handler code here and/or call default

    

     if (bCalcValidRects&&GetVScroll())//GetVScroll()检测是否要出现系统滚动条

     {

            lpncsp->rgrc[0].left-=19;//去掉默认滚动条的区域

            lpncsp->rgrc[0].right-=18;//腾出我们要绘制的滚动条区域

     }

     CListBox::OnNcCalcSize(bCalcValidRects, lpncsp);

    

}

       系统的滚动条是隐藏了,又有一个新的问题出现了,就是我们想在原来的系统滚动条的位置绘制我们自己的滚动条,而我们把原来的系统滚动条的区域划分成了客户区域。怎么绘制?有人会考虑直接在客户区域绘制不就得了,这样不行,窗口滚动的时候滚动条的区域也会滚动。细心的朋友有没有觉得我上面的代码有点问题?默认滚动条的区域应该是在右侧,我却把左侧的非客户区划分成了客户区。不知道大家有木有发现具有内建垂直滚动条的控件都会有WS_EX_RIGHTSCROLLBAR这么一个扩展属性?我们用代码把他改成WS_EX_LEFTSCROLLBAR默认滚动条的区域就会在左侧了。

long StyleEx=::GetWindowLong(m_hWnd,GWL_EXSTYLE);

            if ((StyleEx&WS_EX_RIGHTSCROLLBAR)==WS_EX_RIGHTSCROLLBAR)

            {

                   ModifyStyleEx(WS_EX_RIGHTSCROLLBAR,WS_EX_LEFTSCROLLBAR);

            }

        这样我们就完美隐藏了系统的滚动条又为我们自己的滚动条腾出了地方。我们的滚动条区域有了,滚动数据我们又能得到,至于绘制自己的滚动条嘛就很简单了,敬请参看其他的文章,网上有很多这方面的例子。

点击此处下载Demo源码 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值