实现了功能,还没有添加完整的事件和别的东西,核心代码如下:
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace UserControls
{
/// <summary>
/// Summary description for RowHeader.
/// </summary>
public class RowHeader : System.Windows.Forms.UserControl
{
#region Variable
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
/// <summary>
///
/// </summary>
protected BorderStyle borderStyle;
/// <summary>
///
/// </summary>
protected Color borderColor;
/// <summary>
///
/// </summary>
protected Color selectedFieldBackColorFocused;
/// <summary>
///
/// </summary>
protected Color selectedFieldBackColorNotFocused;
/// <summary>
///
/// </summary>
protected int _nDraggingLineHeight = 2;
/// <summary>
///
/// </summary>
protected RowHeaderFieldCollection _fields = RowHeaderFieldCollection.CreateInstance();
/// <summary>光标是否显示为垂直拖动状态。</summary>
/// <remarks>
/// 当鼠标在<see cref="RowHeaderField"/>的
/// 下边框附近的某个范围内,或者在选中某
/// 条线条之后,鼠标处于拖动状态即为true;
/// 否则为false。
/// </remarks>
private bool _bShowHSplit = false;
/// <summary> 被选中的线条是否显示为虚线。</summary>
/// <remarks></remarks>
private bool _bShowDashed = false;
/// <summary></summary>
private bool _bMouseDrag = false;
/// <summary>鼠标是否按下。</summary>
private bool _bMouseButtonLeftDown = false;
/// <summary>鼠标一直处于按住状态。</summary>
private bool _bMouseButtonLeftPress = false;
/// <summary>鼠标是否松开。</summary>
private bool _bMouseButtonLeftUp = false;
/// <summary>鼠标当前位置的X坐标。</summary>
private int _nMouseX = 0;
/// <summary>鼠标当前位置的Y坐标。</summary>
private int _nMouseY = 0;
#endregion Variable
#region Property
/// <summary>
/// 在<see cref="RowHeader"/>获得焦点时,
/// 绘制选中<see cref="RowHeaderField"/>的背景色
/// </summary>
public Color SelectedFieldBackColorFocused
{
get { return selectedFieldBackColorFocused; }
set
{
if ( selectedFieldBackColorFocused != value )
{
selectedFieldBackColorFocused = value;
this.Invalidate();
}
}
}
/// <summary>
/// 在<see cref="RowHeader"/>未获得焦点时,
/// 绘制选中<see cref="RowHeaderField"/>的背景色
/// </summary>
public Color SelectedFieldBackColorNotFocused
{
get { return selectedFieldBackColorNotFocused; }
set
{
if ( selectedFieldBackColorNotFocused != value )
{
selectedFieldBackColorNotFocused = value;
this.Invalidate();
}
}
}
/// <summary> 设置或获取边框式样的值. </summary>
/// <remarks>
/// 通过编程或者属性BordStyle可以改变控件<see cref='RowHeader'/>的边框式样的值.
/// </remarks>
public BorderStyle BorderStyle
{
get { return borderStyle; }
set
{
if ( borderStyle != value )
{
borderStyle = value;
this.Invalidate();
}
}
}
/// <summary> 设置或获取边框颜色的值.</summary>
/// <remarks>
/// 该值表示<see cref='RowHeader'/>控件的边框颜色。
/// </remarks>
/// <value>
/// 一个<see cref="Color"/>,表示行头控件的边框颜色。
/// </value>
public Color BorderColor
{
get { return borderColor; }
set
{
if ( borderColor != value )
{
borderColor = value;
this.Invalidate();
}
}
}
#endregion Property
#region Paint the RowHeader and RowHeaderField
/// <summary>
/// 绘制控件<see cref="RowHeader"/>
/// </summary>
/// <param name="sender"></param>
/// <param name="pe"></param>
protected void RowHeader_Paint(object sender,PaintEventArgs pe)
{
Graphics g = pe.Graphics;
PaintBackColor(g);
PaintBorders(g);
PaintSelectedRowHeaderField(g);
PaintHeaderFieldBackColorAndBorder(g);
PaintRowHeaderField(g);
RowHeader_DrawDraggingLine(g);
}
/// <summary>
/// 绘制控件<see cref="RowHeader"/>的背景色
/// </summary>
/// <param name="g"></param>
protected void PaintBackColor(Graphics g)
{
Rectangle rect ;
rect= new Rectangle();
rect.X = 0;
rect.Y = 0;
rect.Width = this.Bounds.Width;
rect.Height = this.Bounds.Height;
g.FillRectangle(new SolidBrush(Color.White), rect);
}
/// <summary>
/// 绘制控件<see cref="RowHeader"/>的边框
/// </summary>
/// <param name="g"></param>
protected void PaintBorders(Graphics g)
{
Rectangle recBounds = new Rectangle();
//取得边框位置
recBounds.X = 0;
recBounds.Y = 0;
recBounds.Width = this.Bounds.Width;
recBounds.Height = this.Bounds.Height;
switch (borderStyle)
{
case BorderStyle.Fixed3D:
ControlPaint.DrawBorder3D(g,recBounds,Border3DStyle.Raised);
break;
case BorderStyle.FixedSingle:
ControlPaint.DrawBorder(g,recBounds,BorderColor,ButtonBorderStyle.Solid);
break;
}
}
/// <summary>
/// 绘制控件<see cref="RowHeader"/>的组成部分<see cref="RowHeaderField"/>的背景和边框
/// </summary>
/// <param name="g"></param>
protected void PaintHeaderFieldBackColorAndBorder(Graphics g)
{
for ( int i = 0; i < _fields.Count; i++ )
{
if ( _fields[i].Selected )
continue;
RectangleF recField = new RectangleF();
recField.X = _fields[i].X;
recField.Y = _fields[i].Y;
recField.Height = _fields[i].Height;
recField.Width = _fields[i].Width - 1;
g.FillRectangle(new SolidBrush(Color.FromKnownColor(KnownColor.Control)), recField);
g.DrawRectangle(new Pen(borderColor, 1), recField.X,recField.Y,recField.Width,recField.Height);
}
}
/// <summary>
/// 绘制控件<see cref="RowHeader"/>的组成部分<see cref="RowHeaderField"/>
/// </summary>
/// <param name="g"></param>
protected void PaintRowHeaderField(Graphics g)
{
for (int i = 0; i < _fields.Count; i++)
{
RectangleF recField = new RectangleF();
recField.X = _fields[i].X;
recField.Y = _fields[i].Y;
recField.Height = _fields[i].Height;
recField.Width = this.Width;
string caption = (i + 1).ToString();
DrawString(recField, g, caption, StringAlignment.Center, StringAlignment.Center, this.Font, this.ForeColor);
}
}
/// <summary>
/// 画被拖拽的线条
/// </summary>
/// <param name="g"></param>
protected void RowHeader_DrawDraggingLine(Graphics g)
{
if ( _bShowDashed == true )
{
RectangleF rec = new RectangleF();
rec.X = 0;
rec.Y = _nMouseY - _nDraggingLineHeight / 2.0f;
rec.Width = this.Width;
rec.Height = _nDraggingLineHeight;
g.FillRectangle(new HatchBrush(HatchStyle.Percent50,Color.FromKnownColor(KnownColor.Black),Color.FromKnownColor(KnownColor.Transparent)),rec);
}
}
#endregion Paint the RowHeader and RowHeaderField
# region Others
/// <summary>
/// 重设置<see cref="RowHeaderFieldCollection"/>中的元素<see cref="RowHeaderField"/>
/// 的位置<see cref="RowHeaderField.X"/>和<see cref="RowHeaderField.Y"/>
/// </summary>
/// <remarks>当拖拽<see cref="RowHeaderField"/>时,应该调用此函数</remarks>
protected void ResetRowHeaderFieldLocation()
{
for ( int i = 0;i < _fields.Count; i++ )
{
_fields[i].X = 0;
_fields[i].Y = _fields.GetTotalHaightBeforeIndex(i);
}
}
/// <summary>
/// 重设置<see cref="RowHeaderFieldCollection"/>中的元素<see cref="RowHeaderField"/>
/// 的位置<see cref="RowHeaderField.Height"/>和<see cref="RowHeaderField.Width"/>
/// </summary>
/// <remarks>当拖拽<see cref="RowHeaderField"/>时,应该调用此函数</remarks>
protected void ResetRowHeaderFieldSize()
{
for ( int i = 0; i < _fields.Count; i++ )
{
if ( _fields[i].InDraging == true )
{
if ( _nMouseY - _fields[i].Y <= RowHeaderField.MinHeight )
_fields[i].Height = RowHeaderField.MinHeight;
else
_fields[i].Height = _nMouseY - _fields[i].Y;
//以后扩展X方向的拖拽
break;
}
}
}
#endregion Others
#region About Draw String
/// <summary>
///
/// </summary>
/// <param name="rec"></param>
/// <param name="g"></param>
/// <param name="text"></param>
/// <param name="horizontalAlign"></param>
/// <param name="verticalAlign"></param>
/// <param name="font"></param>
/// <param name="fontColor"></param>
public static void DrawString(RectangleF rec, Graphics g, string text, StringAlignment horizontalAlign, StringAlignment verticalAlign, Font font, Color fontColor)
{
SolidBrush sbCellFontColor = new SolidBrush(fontColor);
RectangleF recF = new RectangleF(); //单元格内容字符串范围
SizeF sz = new SizeF(); //单元格内容字符串尺寸
StringFormat sf = new StringFormat(StringFormat.GenericDefault); //字符串格式
sf.Alignment = horizontalAlign; //对齐方式
sf.Trimming = StringTrimming.EllipsisWord;
int charsfitted = 0;
int linesfilled = 0;
//画字符串
if (text != "" && rec.Width > 0)
{
sz = g.MeasureString(text, font, new SizeF(rec.Width, rec.Height), sf, out charsfitted, out linesfilled);
switch(verticalAlign)
{
case StringAlignment.Far:
recF = new RectangleF(rec.Left, (float)(rec.Top + Math.Ceiling(rec.Height - sz.Height)) - 1, rec.Width, sz.Height);
break;
case StringAlignment.Center:
recF = new RectangleF(rec.Left, (float)(rec.Top + Math.Ceiling((rec.Height - sz.Height) / 2) + 1), rec.Width, sz.Height);
break;
default:
recF = new RectangleF(rec.Left, rec.Top + 2, rec.Width, rec.Height);
break;
}
g.DrawString(text, font, sbCellFontColor, recF, sf);
}
}
/// <summary>
/// 测量指定字符串的高度。
/// </summary>
/// <param name="text">一个<see cref="string"/>,表示要测量的字符串。</param>
/// <param name="g">一个<see cref="System.Drawing.Graphics"/>对象。</param>
/// <param name="f">一个<see cref="System.Drawing.Font"/>,表示绘制此字符串的<see cref="Font"/>对象。</param>
/// <returns>一个<see cref="float"/>型的值,表示指定字符串的高度。</returns>
public static float MeasureTextHeight(string text,System.Drawing.Graphics g,System.Drawing.Font f)
{
//测量字符串的高度
SizeF sz = new SizeF();
if (text == String.Empty) return 0;
if (g == null) return 0;
if (f == null) return 0;
sz = g.MeasureString(text,f);
return sz.Height;
}
#endregion About Draw String
#region Mouse event
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void RowHeader_MouseDown(object sender,MouseEventArgs e)
{
_nMouseX = e.X;
_nMouseY = e.Y;
if ( e.Button == MouseButtons.Left )
{
_bMouseButtonLeftDown = true;
_bMouseButtonLeftUp = false;
_bShowDashed = _bShowHSplit ? true : false;
}
if ( _bShowDashed == true )
{
int indexDraged = _fields.GetIndexDraggedRegionByPostion(_nMouseX,_nMouseY);
_fields.SetDraggedField(indexDraged);
}
else
{
int index = _fields.GetIndexRegionByPostion(_nMouseX,_nMouseY);
if ( index >= 0 && index <= _fields.Count )
_fields[index].Selected = true;
}
this.Invalidate();
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void RowHeader_MouseMove(object sender,MouseEventArgs e)
{
_nMouseX = e.X;
_nMouseY = e.Y;
if ( _bMouseButtonLeftDown == false )
{
if ( _fields.GetIndexDraggedRegionByPostion(_nMouseX,_nMouseY) >=0 )
_bShowHSplit = true;
else if ( _fields.GetIndexRegionByPostion(_nMouseX,_nMouseY) >=0 )
_bShowHSplit = false;
this.Cursor = _bShowHSplit ? Cursors.HSplit : Cursors.Default;
}
// 如果鼠标按下,同时光标为拖拽状态,选中线条为虚线时
else if ( _bMouseButtonLeftDown == true && _bShowHSplit == true && _bShowDashed == true )
{
_bMouseButtonLeftPress = true;
_bMouseDrag = true;
ResetRowHeaderFieldSize();
ResetRowHeaderFieldLocation();
}
this.Invalidate();
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void RowHeader_MouseUp(object sender,MouseEventArgs e)
{
_bMouseButtonLeftDown = false;
_bMouseButtonLeftUp = true;
_bMouseButtonLeftPress = false;
_bShowDashed = false;
_nMouseX = e.X;
_nMouseY = e.Y;
if ( _fields.IndexInDraging >= 0 )
{
_fields[_fields.IndexInDraging].InDraging = false;
}
this.Invalidate();
}
/// <summary>
///
/// </summary>
/// <param name="g"></param>
protected void PaintSelectedRowHeaderField(Graphics g)
{
for ( int i = 0; i < _fields.Count; i++ )
{
if ( _fields[i].Selected == true )
{
RectangleF recField = new RectangleF();
recField.X = _fields[i].X;
recField.Y = _fields[i].Y;
recField.Height = _fields[i].Height;
recField.Width = _fields[i].Width - 1;
if (this.Focused)
g.FillRectangle(new SolidBrush(selectedFieldBackColorFocused), recField);
else
g.FillRectangle(new SolidBrush(selectedFieldBackColorNotFocused), recField);
break;
}
}
}
#endregion Mouse event
#region Constructor and Dispose
/// <summary>
/// RowHeader的构造函数
/// </summary>
public RowHeader()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
int totalHaight = 0;
this.SetStyle(ControlStyles.UserPaint,true);
this.SetStyle(ControlStyles.DoubleBuffer,true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint,true);
this.SetStyle(ControlStyles.Selectable, false);
borderStyle = BorderStyle.FixedSingle;
borderColor = Color.FromKnownColor(KnownColor.ControlDark);
selectedFieldBackColorFocused = Color.FromArgb(254, 128, 62);
selectedFieldBackColorNotFocused = Color.FromArgb(255, 192, 111);
_fields = RowHeaderFieldCollection.CreateInstance();
for ( int i = 0; i < 20; i++ )
{
RowHeaderField rhf = new RowHeaderField();
rhf.ID = i;
rhf.Index = i;
rhf.Fields = _fields;
rhf.Parent = this;
rhf.Y = totalHaight;
rhf.Height = RowHeaderField.DelfaultHeight;
rhf.Width = this.Width;
totalHaight = totalHaight + rhf.Height;
_fields.Add(rhf);
}
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// RowHeader
//
this.Name = "RowHeader";
this.Size = new System.Drawing.Size(40, 401);
this.SizeChanged += new System.EventHandler(this.RowHeader_SizeChanged);
this.LostFocus += new EventHandler(RowHeader_LostFocus);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.RowHeader_MouseUp);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.RowHeader_Paint);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.RowHeader_MouseMove);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.RowHeader_MouseDown);
}
#endregion
private void RowHeader_SizeChanged(object sender, System.EventArgs e)
{
this.Invalidate();
}
#endregion Constructor and Dispose
private void RowHeader_LostFocus(object sender, EventArgs e)
{
this.Invalidate();
}
}
}