代码:
/Files/sherlockhua/filetransferbox.rar
/Files/sherlockhua/TransferBoxEx.rar(改进版)
实现效果图:
最近在做一个可在局域网中聊天的聊天工具,因为要支持多文件传输功能,所以显示多文件传输状态便成了一个问题。我们都用过qq,当进行多文件传输时,它可以以列表的形式把正在传输的文件信息显示出来。显示的内容有文件图标,文件名,发送或者接受文件,进度条,文件大小还有一些取消,保存之类的按钮。而且当正在传输的文件比较多,客户区显示不了时。就会出现一个滚动条,用来显示所有的发送或接收文件的信息。
好了,大概得轮廓都已经了解了。现在就可以开始着手写控件了。我们知道列表中的每一项都是一个文件信息,我们就可以把每一个文件信息作为一个类,然后在这个类之中绘制各种文件信息。自然而然,我们可以分辨出以下几个类:FileTransferItem类、FileLinkButton类、ProcessBar类。其中FileTransferItem类用来代表一个文件信息项。FileLinkButton提供类似LinkButton类的按钮功能,ProcessBar类提供进度条的功能。然而为了在正确位置进行绘制控件,就必须记下每一对象的位置。因此,我们可以用一个基类FileObject来替提供位置信息,其他的类都继承它。部分代码如下:
1
/**//*
2
* 创建者:张华
3
* 创建日期:2008/7/8
4
* 更新日期:2008/7/8
5
* 描述:为类FileLinkButton、类FileTranferItem和类ProcessBar提供基础功能
6
* 联系方式:214140879
7
*/
8
using System;
9
using System.Collections.Generic;
10
using System.Text;
11
using System.Drawing;
12
using System.Drawing.Drawing2D;
13
using System.Drawing.Imaging;
14
using System.Xml.Serialization;
15
using System.ComponentModel;
16
17
namespace ZH.FileTranferBox
18

{
19
[Serializable]
20
public class FileObject
21
{
22
字段#region 字段
23
private Rectangle _rectangle;
24
private string toolTip;
25
#endregion
26
27
属性#region 属性
28
29
[Browsable(false)]
30
public Point Location
31
{
32
get
33
{
34
return _rectangle.Location;
35
}
36
37
38
set
39
{
40
_rectangle.Location = value;
41
}
42
}
43
[Browsable(false),XmlIgnore]
44
public Rectangle Rectangle
45
{
46
get
47
{
48
return _rectangle;
49
}
50
set
51
{
52
_rectangle = value;
53
}
54
}
55
[Browsable(false), XmlIgnore]
56
public int Width
57
{
58
get
59
{
60
return _rectangle.Width;
61
}
62
set
63
{
64
_rectangle.Width = value;
65
}
66
}
67
[Browsable(false), XmlIgnore]
68
public int Height
69
{
70
get
71
{
72
return _rectangle.Height;
73
}
74
set
75
{
76
_rectangle.Height = value;
77
}
78
}
79
[Browsable(false), XmlIgnore]
80
public int X
81
{
82
get
83
{
84
return _rectangle.X;
85
}
86
set
87
{
88
_rectangle.X = value;
89
}
90
}
91
[Browsable(false), XmlIgnore]
92
public int Y
93
{
94
get
95
{
96
return _rectangle.Y;
97
}
98
set
99
{
100
_rectangle.Y = value;
101
}
102
}
103
[Browsable(false), XmlIgnore]
104
public int Left
105
{
106
get
107
{
108
return _rectangle.Left;
109
}
110
}
111
[Browsable(false), XmlIgnore]
112
public int Top
113
{
114
get
115
{
116
return _rectangle.Top;
117
}
118
}
119
[Browsable(false), XmlIgnore]
120
public int Right
121
{
122
get
123
{
124
return _rectangle.Right;
125
}
126
}
127
[Browsable(false), XmlIgnore]
128
public int Bottom
129
{
130
get
131
{
132
return _rectangle.Bottom;
133
}
134
}
135
[Browsable(false), XmlIgnore]
136
public Size Size
137
{
138
get
139
{
140
return _rectangle.Size;
141
}
142
set
143
{
144
_rectangle.Size = value;
145
}
146
}
147
#endregion
148
149
构造函数#region 构造函数
150
151
public FileObject()
152
{
153
toolTip = "";
154
_rectangle = new Rectangle(0, 0, 0, 0);
155
}
156
public FileObject(Rectangle rect, string tip)
157
{
158
toolTip = tip;
159
_rectangle = new Rectangle(rect.Location, rect.Size);
160
}
161
162
#endregion
163
}
164
}
165
为了更好的实现封装性和隐蔽性。在类FileTransferItem增加注册事件的函数。
1
/**//// <summary>
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
当文件项移除时,取消注册函数:
1
public void UnRegisterEvent()
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
文件信息项绘制函数:
1
/**//// <summary>
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);
基本功能是实现了,但还有很多不足和改进的地方,有好的方法希望能够和我共享。谢谢!