ListView隐藏列 column隐藏标题栏不被拉出的处理方法

来源:互联网 发布:justin和selena知乎 编辑:程序博客网 时间:2024/04/30 12:29

想实现ListView在详细资料视图下列的隐藏,网上搜了一下实现方法,发现不外乎两种方法,一种是删除列,这是真正的隐藏,但是得记录删除的每一个单元格的内容,以备该列再次需要显示时把内容回填。相当于把ListView原来记录的东西自己保存了,隐藏的列越多,要记录的东西越多。而如果用户要修改已隐藏的单元格的内容,这就麻烦了。因为既然说“隐藏”,你就得允许修改已隐藏的内容,而实际上删除了,就得自己提供修改机制。不想这么麻烦。

于是看第二种方法:把列宽设为0,这样看上去是隐藏了,也没有修改单元格内容的麻烦,但是用户拖动列头,是可以把隐藏的列内容显示出来的,这就露馅了。可以子类化其Header控件,在鼠标消息中通过发送HDM_HITTEST消息查询鼠标位置,发现是在列的分隔线位置且该位置左右有隐藏的列就截取不处理,这样用户就无法改变隐藏列的宽度,把隐藏的列内容显示出来。但是这样又带来一个问题,由于无法改变隐藏列的宽度,因此也无法改变隐藏列右边列的宽度,表现为如果鼠标是按在隐藏列右边的分隔线,是无法拖动调整隐藏列右边列的宽度的。

两种方法都不完美,最完美的方法是完全自绘,自己画列头,自己处理列头的拖动,但是这又太麻烦了,有没有简单一点的处理方法呢?

下面介绍的就是RingSDK界面库采用的方法,是结合了上面提到的两种方法。隐藏采用把列宽设为0的方法,但是需要移一下位置,就是通过发送HDM_SETITEM消息把隐藏的列移动到最前面去,因为最前面的列分隔线是无法拖动的,也不会有人去拖,因此把隐藏列放在那里是最安全的,保险起见,截取鼠标消息处理一下,使无法拖动最左边的分隔线。这样唯一的破绽就是移到最左边的分隔线,鼠标形状会变,但是一样无法拖动,这应该是可以接受的。接下来就是处理隐藏列的再次显示,需要恢复宽度并且移动到原位置,因此需要记录列的宽度和原来的位置序号,可以使用两个WORD值,合成一个DWORD值就可以了,不需要分配内存,通过HDM_SETITEM消息把这个值跟相应列绑定就行了。

这样就是一个近乎完美的解决方法,不过可能还有一个缺陷就是:隐藏列后用户把没隐藏的列拖来拖去改变排列顺序,最后显示隐藏列时回到的位置可能不一定正确,但是我测试的时候拖来拖去把我自己都拖糊涂了,不知道最后隐藏列显示出来应该在什么位置是正确的,看起来好象都正确:-),就没管这个事情了。

真正实现代码的时候当然没有上面说的那么简单,有很多细节需要考虑、

原创粉丝点击