作者:刘树伟
滚动条自绘是整个win32自绘中,相对比较复杂的,因为滚动条很多信息,是绘制在临时DC上,这将导致在某些情况下,原始滚动条外观会显示出来。并且,滚动条的宽度也不好修改。
在LibUIDK界面库开发过程中,曾采用SetWindowRgn,把滚动条隐藏掉,然后创建一个自已实现的滚动条与List控件连动。这种方式,对于一般的应用场景,完全可以应对。但对于追求极致用户体验的用户,还差点意思。比如鼠标点击滚动条后,应该使List控件得到焦点。而采用“外挂”滚动条的方式,滚动条将得到焦点。外挂方式,为了保证滚动条看起来像List内置滚动条一样,需要处理的事情也更多,容易出问题的机率,也更大。
下面,我们将讨论一种全新的方式:
通过把垂直滚动条放到左侧,并且通过OnNcCalcSize来把左侧滚动条区域隐藏,再把右侧非客户区变宽,可以为右侧滚动条开出一个区域来进行绘制。同理,如果要把滚动条显示到左侧的话,就把右侧滚动条隐藏,并开出左侧区域。
这种方法解决了垂直滚动条的绘制,如果要绘制水平滚动条,因为不能把水平滚动条放到上面,所以此方法不通。
我们可以通过在OnNcCalcSize中调用ModifyStyle(WS_HSCROLL, 0);来禁止水平滚动条,然后在OnNcCalcSize中开出水平滚动条区域来绘制水平滚动条。
之所以不使用ModifyStyle(WS_HSCROLL | WS_VSCROLL, 0); 把水平和垂直滚动条都禁止掉,是因为一旦全部禁止掉后,就拿不到滚动条数据了(待验证),并且用鼠标滚轮也无法滚动List了。鼠标框选List Item时,鼠标移到List之外,List也不能自动滚动了。
至于ModifyStyle(WS_HSCROLL, 0)放的位置,可以研究一下放到其它地方是否更合适。
在新开辟出来的滚动条区域单击鼠标,会发现WM_NCLBUTTONDOWN无法响应,通过SPY++分析,发现是由于WM_NCHITTEST在新开辟出来的区域返回的是HTNOWHERE,而真正滚动条区域,返回的是HTVSCROLL等。所以,我们只需要处理WM_NCHITTEST消息,返回HTVSCROLL或HTHSCROLL即可。