代码:
/Files/sherlockhua/filetransferbox.rar
/Files/sherlockhua/TransferBoxEx.rar(改进版)
实现效果图:
最近在做一个可在局域网中聊天的聊天工具,因为要支持多文件传输功能,所以显示多文件传输状态便成了一个问题。我们都用过qq,当进行多文件传输时,它可以以列表的形式把正在传输的文件信息显示出来。显示的内容有文件图标,文件名,发送或者接受文件,进度条,文件大小还有一些取消,保存之类的按钮。而且当正在传输的文件比较多,客户区显示不了时。就会出现一个滚动条,用来显示所有的发送或接收文件的信息。
好了,大概得轮廓都已经了解了。现在就可以开始着手写控件了。我们知道列表中的每一项都是一个文件信息,我们就可以把每一个文件信息作为一个类,然后在这个类之中绘制各种文件信息。自然而然,我们可以分辨出以下几个类:FileTransferItem类、FileLinkButton类、ProcessBar类。其中FileTransferItem类用来代表一个文件信息项。FileLinkButton提供类似LinkButton类的按钮功能,ProcessBar类提供进度条的功能。然而为了在正确位置进行绘制控件,就必须记下每一对象的位置。因此,我们可以用一个基类FileObject来替提供位置信息,其他的类都继承它。部分代码如下:
2 * 创建者:张华
3 * 创建日期:2008/7/8
4 * 更新日期:2008/7/8
5 * 描述:为类FileLinkButton、类FileTranferItem和类ProcessBar提供基础功能
6 * 联系方式:214140879
7 */
8using System;
9using System.Collections.Generic;
10using System.Text;
11using System.Drawing;
12using System.Drawing.Drawing2D;
13using System.Drawing.Imaging;
14using System.Xml.Serialization;
15using System.ComponentModel;
16
17namespace ZH.FileTranferBox
18{
19 [Serializable]
20 public class FileObject
21 {
22 字段
26
27 属性
148
149 构造函数
163 }
164}
165
为了更好的实现封装性和隐蔽性。在类FileTransferItem增加注册事件的函数。
2 /// 注册事件
3 /// </summary>
4 public void RegisterEvent()
5 {
6 _parent.MouseClick += (MouseEventHandler)_delegates[0];
7 _parent.MouseDown += (MouseEventHandler)_delegates[1];
8 _parent.MouseMove += (MouseEventHandler)_delegates[2];
9 _parent.Paint += (PaintEventHandler)_delegates[3];
10 }
11
当文件项移除时,取消注册函数:
2 {
3 _parent.MouseClick -= (MouseEventHandler)_delegates[0];
4 _parent.MouseDown -= (MouseEventHandler)_delegates[1];
5 _parent.MouseMove -= (MouseEventHandler)_delegates[2];
6 _parent.Paint -= (PaintEventHandler)_delegates[3];
7 }
8
文件信息项绘制函数:
2 /// 控件绘制函数
3 /// </summary>
4 /// <param name="sender"></param>
5 /// <param name="e"></param>
6 private void OnPaint(object sender, PaintEventArgs e)
7 {
8 if (visible == false) return;
9 Graphics g = e.Graphics;
10
11 Brush txtBrush = null;
12 StringFormat format = new StringFormat();
13 format.Alignment = StringAlignment.Near;
14 format.Trimming = StringTrimming.EllipsisWord;
15 format.FormatFlags = StringFormatFlags.NoWrap;
16
17 rectImage.X =Rectangle.X + LEFTSPACE;
18 rectImage.Y =Rectangle.Y+ TOPSPACE;
19
20 if (extImage == null)
21 {
22 System.Diagnostics.Debug.WriteLine("文件图像为空");
23 return;
24 }
25 //绘制左边的文件图像
26 g.DrawImage(extImage, rectImage, new Rectangle(0, 0, extImage.Width, extImage.Height), GraphicsUnit.Pixel);
27
28 //绘制标题(“发送文件”或“接受文件”)
29 int fontWidth = _parent.ClientRectangle.Width - rectImage.Width - LEFTSPACE - RIGHTSPACE - LEFTSPACE;
30 SizeF sizeF = g.MeasureString(caption, _parent.Font);
31 sizeF.Width = Math.Min(fontWidth, sizeF.Width);
32 RectangleF rectF = new RectangleF(new PointF(0, 0), sizeF);
33 rectF.X = Rectangle.X + LEFTSPACE + rectImage.Width + LEFTSPACE;
34 rectF.Y = Rectangle.Y + TOPSPACE;
35 if (mouseHover)
36 txtBrush = new SolidBrush(hoverFontColor.IsEmpty?_parent.HoverFontColor:hoverFontColor);
37 else
38 txtBrush = new SolidBrush(normalFontColor.IsEmpty?_parent.NormalFontColor:normalFontColor);
39 g.DrawString(caption, _parent.Font, txtBrush, rectF, format);
40
41 //绘制文件名
42 sizeF = g.MeasureString(fileName, _parent.Font);
43 sizeF.Width = Math.Min(fontWidth, sizeF.Width);
44 RectangleF rectF2 = new RectangleF(new PointF(0, 0), sizeF);
45 rectF2.X = Rectangle.X + LEFTSPACE + rectImage.Width + LEFTSPACE;
46 rectF2.Y = rectF.Y + rectF.Height + LEFTSPACE;
47
48 g.DrawString(fileName, _parent.Font, txtBrush, rectF2, format);
49
50 //绘制进度条
51 Rectangle rectProcess = Rectangle.Empty;
52 rectProcess.X = Rectangle.X + LEFTSPACE;
53 rectProcess.Y = Rectangle.Y + rectImage.Height + BOTTOMSPACE*2;
54 rectProcess.Width = Rectangle.Width - LEFTSPACE * 2;
55 rectProcess.Height = LEFTSPACE * 4;
56
57 processBar.Rectangle = rectProcess;
58 processBar.Paint(g);
59
60 //绘制文件大小
61 string fileSizeDisplay = Format.ToString(transferSize) + "/" + fileSize;
62 sizeF = g.MeasureString(fileSizeDisplay,_parent.Font);
63 RectangleF fileSizeRectF = new RectangleF(new Point(0, 0), sizeF);
64 fileSizeRectF.X = processBar.Right - sizeF.Width - LEFTSPACE;
65 fileSizeRectF.Y = processBar.Y + processBar.Height + LEFTSPACE;
66 g.DrawString(fileSizeDisplay, _parent.Font, txtBrush, fileSizeRectF, format);
67
68
69 //绘制按钮
70 Rectangle rectButton = Rectangle.Empty;
71 if (transferType == TransferType.SendFile)
72 {
73 rectButton.X = rectProcess.Right - 50 - RIGHTSPACE;
74 rectButton.Y = (int)fileSizeRectF.Y + (int)fileSizeRectF.Height + RIGHTSPACE;
75 rectButton.Width = 50;
76 rectButton.Height = 20;
77
78 lbCancel.Rectangle = rectButton;
79 lbCancel.Visible = true;
80 lbCancel.Paint(g);
81 }
82 else
83 {
84 int width = (Rectangle.Width-LEFTSPACE*4) / 3;
85 rectButton.X = rectProcess.Right - width - RIGHTSPACE;
86 rectButton.Y = (int)fileSizeRectF.Height + RIGHTSPACE + (int)fileSizeRectF.Y;
87 rectButton.Width = 50;
88 rectButton.Height = 20;
89
90 lbReject.Rectangle = rectButton;
91 lbReject.Visible = true;
92 lbReject.Paint(g);
93
94 rectButton.X = rectProcess.Right - width * 2 - RIGHTSPACE * 2;
95 rectButton.Y = (int)fileSizeRectF.Height + RIGHTSPACE + (int)fileSizeRectF.Y;
96 rectButton.Width = 50;
97 rectButton.Height = 20;
98
99 lbSave.Rectangle = rectButton;
100 lbSave.Visible = true;
101 lbSave.Paint(g);
102
103 rectButton.X = rectProcess.Right - width * 3 - RIGHTSPACE * 3;
104 rectButton.Y = (int)fileSizeRectF.Height + RIGHTSPACE + (int)fileSizeRectF.Y;
105 rectButton.Width = 50;
106 rectButton.Height = 20;
107
108 lbSaveAs.Rectangle = rectButton;
109 lbSaveAs.Visible = true;
110 lbSaveAs.Paint(g);
111 }
112 }
这里只是列出关键代码,具体代码参考源代码。
如何使用:
this.fileTranferBox1.AddItem(fileName, info.Length, ZH.FileTranferBox.TransferType.SendFile);
基本功能是实现了,但还有很多不足和改进的地方,有好的方法希望能够和我共享。谢谢!