代码:
/Files/sherlockhua/filetransferbox.rar
/Files/sherlockhua/TransferBoxEx.rar(改进版)
实现效果图:
最近在做一个可在局域网中聊天的聊天工具,因为要支持多文件传输功能,所以显示多文件传输状态便成了一个问题。我们都用过qq,当进行多文件传输时,它可以以列表的形式把正在传输的文件信息显示出来。显示的内容有文件图标,文件名,发送或者接受文件,进度条,文件大小还有一些取消,保存之类的按钮。而且当正在传输的文件比较多,客户区显示不了时。就会出现一个滚动条,用来显示所有的发送或接收文件的信息。
好了,大概得轮廓都已经了解了。现在就可以开始着手写控件了。我们知道列表中的每一项都是一个文件信息,我们就可以把每一个文件信息作为一个类,然后在这个类之中绘制各种文件信息。自然而然,我们可以分辨出以下几个类:FileTransferItem类、FileLinkButton类、ProcessBar类。其中FileTransferItem类用来代表一个文件信息项。FileLinkButton提供类似LinkButton类的按钮功能,ProcessBar类提供进度条的功能。然而为了在正确位置进行绘制控件,就必须记下每一对象的位置。因此,我们可以用一个基类FileObject来替提供位置信息,其他的类都继承它。部分代码如下:
/*2
* 创建者:张华3
* 创建日期:2008/7/84
* 更新日期:2008/7/85
* 描述:为类FileLinkButton、类FileTranferItem和类ProcessBar提供基础功能6
* 联系方式:2141408797
*/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.FileTranferBox18
{19
[Serializable]20
public class FileObject21
{22
字段26

27
属性148

149
构造函数163
}164
}165

为了更好的实现封装性和隐蔽性。在类FileTransferItem增加注册事件的函数。
/// <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

当文件项移除时,取消注册函数:
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

文件信息项绘制函数:
/// <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
else38
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
else83
{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);
基本功能是实现了,但还有很多不足和改进的地方,有好的方法希望能够和我共享。谢谢!


浙公网安备 33010602011771号