模仿outlook快捷方式栏的一个控件(C#)

这是一个用c#写的控件,它的原型是outlook 2000里面左侧的快捷方式栏,类似的控件也会在QQ,Visio等常用软件中找到,我为这个控件写了一个dll,并且做了一个demo演示它。

如下图所示:
模仿outlook快捷方式栏的一个控件(C#)_第1张图片

我把一些主要的控件属性在demo里可以随时更改。它代码量不是很多,dll文件只有36kb。
我没有为这个控件提供额外的面板,但是控件中的每个元素都具有Tag属性。
提供了VisibleGroupChanged, ItemClick等主要事件。在它内部我封装了滚动处理,(按住滚动按钮超过0.5秒后由定时器自动滚动),封装了单选状态时的item互斥性切换。在控件中显示的内容全部是绘制而成,也就是说,它们都是逻辑元素,而非实际的子控件对象。为此,我定义了一个SbComponent类作为所有元素的父类,它主要描述了元素的布局信息,同时也提供了通用的HitTest测试方法以响应鼠标,Items对鼠标提供了悬停反馈,但是GroupHeader没有,因为我觉得它并不是最重要的功能,如果想加还是很简单的。在绘制元素时主要使用了ControlPaint类来实现。

控件的内部组织结构如下图所示:
模仿outlook快捷方式栏的一个控件(C#)_第2张图片


控件的使用非常简单:我借鉴了treeview,listview控件的封装用法,
 1 SideBar.SideBar sbar = new  SideBar.SideBar();
 2 // 赋予imagelist
 3 sbar.ImageList = this .imageList1;
 4 sbar.AddGroup( " 第一组 " );
 5 sbar.AddGroup( " 第二组 " );
 6 // 添加items,参数列表为:itemtext,imageindex
 7 sbar.Groups[ 0 ].Items.Add( " item0 " , 0 );
 8 sbar.Groups[ 1 ].Items.Add( " item1 " , 1 );
 9 sbar.VisibleGroupChanged += new  SbGroupEventHandler(sbar_VisibleGroupChanged);
10 sbar.ItemClick += new  SbItemEventHandler(sbar_ItemClick);

可以通过鼠标点击自动完成当前显示组的切换,也可以使用代码来完成:
 
1 // 设置当前显示的组
2 sbar.VisibleGroupIndex = 1 ;

晚上的时候,我为这个控件加入了对拖放item的功能支持。不过这个功能确实具有一定挑战性,因为涉及到的鼠标处理比较复杂。我们可以看到,鼠标操作的主要特点是:
1.当按下某个控件(例如按钮)时,保持鼠标按下状态,并移开控件,则该控件会弹起,如果此时抬起鼠标,则该控件不会被点击。如果保持鼠标按下并移回控件,控件继续显示成按下状态。即,必须按下和抬起时都捕捉到该控件,点击才有效。估计这是windows设计者考虑到了用户的误操作,允许用户可以此种方法取消点击控件。
2. 当鼠标按下一个item并拖动它到临界区(靠近itemsbox边缘)时,如果item很多,则自动开始滚动。
3. 当鼠标移动到其他GroupHeader时,会切换当前显示的Group。即允许用户将item从一个Group拖动到其他Group中。

上面的挑战性和难点在于,需要根据鼠标的位置计算出需要插入的索引位置,以及要绘制标记插入位置的反馈,并且再位置改变时更新它。具体的细节比较复杂,为此我为sidebar引入了很多成员变量来记录一些必要的信息。也使得mousedown,mouseup,mousemove里面的代码量增加了几乎一倍。。。

不过上面的烦琐细节都被我封装在内部,在外部的使用还是非常简单的。我提供了一个AllowDragItem属性,只需要简单的设置它即可选择是否支持拖放item。同时我考虑为控件增加一个新的事件把它通知给外部。

1 // 使控件支持鼠标拖放条目
2 Sbar.AllowDragItem = true ;


你可以在这里下载到这个控件和例子的最新源代码:
http://www.cnblogs.com/Files/hoodlum1980/SideBar20070707.rar

在这个网站上面还有我的其他几个比较小但是有趣的例子源码,也许会在以后详细介绍它们。
——————————————————————————————
小Bug记录:
1.修改了调整字体后布局错误的bug。
2.修改了在demo中的一个疏忽:在显示字体对话框时,错误的将字体初始化为了form1的字体。
3.我把影响外观的一些属性修改后的刷新显示封装在了控件内部。这个并不算什么严重的bug
但会使外部使用时更为简便。例如,对enabled,view(大图标,小图标...),flatstyle等属性的修改,都会在控件内部调用刷新。在外部只要简单的设置它们的值即可。  

---------------------

这是我在我的博客园博客开张时的第一篇文章,现在我把博客园博客的一些比较重要的文章转载到这里,算是一个重大的决定,由于网络速度,发布日志以及代码插入窗口,图片插入窗口的性能和相应速度,这些因素决定了我有向csdn搬家的倾向。今晚在博客园上想发表日志,可是乌龟爬一样的相应速度,以及屡次三番的server unavailable让我十分恼火!这是不可忍受的。。。

你可能感兴趣的:(c#,imagelist,listview,visio,dll,windows)