CListBox CEdit 自绘滚动条小试

如果直接需要代码,请直接移步http://www.codeproject.com/KB/dialog/skinscrollbar.aspx (注:本人非此代码作者)


用Spy++检查后可知,CListBox的滚动条根本不是独立的滚动条窗口,只是一个逻辑窗口,因此使用对Scrollbar进行SubClass的方法是不可行的,因此只能想办法屏蔽掉Scrollbar。


方案一:在CListBox上自行创建一个CScrollbar,然后改变Z order使之处于最上方,挡住原有Scrollbar。结果:失败!原来的滚动条依然会出现。


方案二:隐藏掉ListBox原有的Scrollbar,在ListBox外创建Scrollbar。

第一步:将CListBox设为Owner-draw,编写drawitem函数部分代码,发现滚动条存在。

第二步:自行响应WM_NCPAINT消息以屏蔽滚动条的绘制,可以暂时屏蔽滚动条,但在使用鼠标滚动进行LIST滚动时,滚动条会再次出现。

第三步:响应WM_NCCALCSIZE消息,在CListBox::OnNcCalcSize函数处理后,根据当前的STYLE对其中的参数进行改动,修改NCCALCSIZE_PARAMS* lpncsp中的lpncsp->rgrc[0]矩形框,去除滚动条位置(即将lpncsp->rgrc[0].right += GetSystemMetrics(SM_CXVSCROLL),如果是左滚动条,依法炮制),但结果即使只留2像素的边框位置,滚动条也会绘制到那2个像素宽度上面,而不会优先绘制边框,因此只能在创建时将边框也全部去除,即去除WS_BORDER与WS_EX_CLIENTEDGE。

第四步:编写自己的滚动条CImgScrollBar,重写各种鼠标响应消息响应,另外还需响应SBM_SETSCROLLINFO与SBM_GETSCROLLINFO消息进行滚动条数据设置与获取。在自行绘制的过程中需要注意的是SCROLLINFO结构体中的nPage与nMin与nMax对绘制滑块大小及拖动值的关系,即:可移动距离=nMax - nMin - nPage + 1。由于父窗口不是ListBox,因此可以为滚动条增加一个SetTarget的函数来指定所有的WM_VSCROLL和WS_HSCROLL的发送对象。

第五步:由于自行创建的滚动并不是嵌在窗口中的,因此需要不时地同步滚动条的数据以实现滚动条的滑块大小与效果随时保持正确的状态,因此,响应WM_ERAZEBKGND消息并在此消息响应中进行同步是个不错的方法。同时,响应LB_ADDSTRING和LB_DELETESTRING消息也是非常必要的。

第五步:由于将ListBox去除了边框,因此需要额外的窗口来绘制ListBox的边框,即新建一个CWnd的类CBorderWnd,将它的大小设为ListBox的大小,然后将ListBox的大小设为去除边框后的大小,并移动一个边框距离以让出边框效果。

第六步:重写CBorderWnd的OnPaint函数,对左下、右下两个角的正方形框位置进行绘制,因为当窗口同时拥有WS_VSCROLL和WS_HSCROLL时,会露出左下角或右下角,CBorderWnd必须对这两个角的绘制负责,但是,注意必须根据当前ListBox的状态对露出左下角或右下角时对其进行绘制,不能一股脑就把两个角都刷了。

在经历以上解释之后,现有三种具体可行方案可供考虑:一、自己编写CImgListBox进行大小控制,在OnSize中调整边框外的滚动条与CBorderWnd的位置,但是在OnSize中调用MoveWindow函数是一个很大的问题,而且在OnSize中的条件判断会很复杂(WS_HSCROLL、WS_VSCROLL、尚未腾出ScrollBar位置?已经腾出ScrollBar位置? Come on~~~)。 二、将CBorderWnd作为自己的父窗口,将大小及布局调整放到CBorderWnd来处理,不错的IDEA,啊哈。三、这也就是文章开始给出的链接中所使用的方式:不去除滚动条的位置,而是创建一个Wnd来作为自己的父窗口,自己的窗口Size比父窗口的Size要大,但父窗口对子窗口起到的裁剪效果便能将滚动条给屏蔽掉了,所以总的结构是CBorderWnd->Wnd->ListBox,两个ScrollBar属于CBorderWnd,由CBorderWnd实现WM_VSCROLL与WS_HSCROLL消息到ListBox的转发。麻烦的地方在于,当你使用GetDlgItem时,获取到的是一个CBorderWnd,而不是CListBox对象。


Edit的控制方法与ListBox的控制方法大致相同,因此不再赘述。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值