一.设计时效果:
二.运行时效果:
三.简单谈谈实现思路:
由于昨天时间比较紧张,没有把全部的功能都做完善就发布出来了,今天把键盘操作给加上了,并修改了一些操作上的小BUG.将一些不必要显示在设计时的属性全部隐藏掉了.
这个控件实现起来比较简单,主要由3部分组成,1为一个元素类,主要实现了BOUNDS属性,以及实际的绘制每个元素的过程.2为一个集合类,这个类来管理储存的元素.在新增,删除元素时触发公共事件.3为JcsItemList控件本身.它的变量成员中含有一个集合类,并在属性中将之公开,这样我们可以在设计时界面来完成元素的添加.在主要的ONPAINT方法中,来实际完成绘制标题,使用遍历集合类元素的方法绘制各个元素.在滚动条的滚动事件中设置第一个绘制的元素的Bounds,并调整滚动条的最大值.
该控件当前实现的功能有:
1.绘制边框
2.绘制标题
3.单元素选中.
4.双击元素触发DoubleClickItem事件.
5.滚动条的点击操作.
6.鼠标滑轮的滚动条移动操作.
7.提供键盘上下键的操作(滚动条将随着移动).提供了在元素上的ENTER键的处理事件.
四.部分源代码:
using
System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace JcsCalendar
... {
public partial class JcsItemList : UserControl
...{
private const int c_headerheight = 4 ;//抬头高
private const int c_seheight = 2;//间隔高
private const int c_normalheight = 21;
private int firstitemindex = 0 ;
private int lastitemindex;
private ViewItemCollection itemcollection;
private VScrollBar vscrollbar;
private string m_caption = "JcsItemList";
private JcsViewItem selecteditem;
public delegate void ItemDoubleClick(JcsViewItem sender);
public event ItemDoubleClick DoubleClickItem;
//private OfficeRenderer render;
public JcsItemList()
...{
InitializeComponent();
//render = new OfficeRenderer();
this.BorderStyle = BorderStyle.FixedSingle ;
this.MinimumSize = new Size(100, c_normalheight * 2);
this.BackColor = Color.White;
vscrollbar = new VScrollBar();
vscrollbar.SmallChange = c_normalheight;
vscrollbar.LargeChange = c_normalheight * 2;
vscrollbar.Dock = DockStyle.Right;
this.Controls.Add(vscrollbar);
//vscrollbar.Value = 21;
vscrollbar.Scroll += new ScrollEventHandler(vscrollbar_Scroll);
vscrollbar.MouseWheel += new MouseEventHandler(vscrollbar_MouseWheel);
itemcollection = new ViewItemCollection();
itemcollection.CollectionChanged += new CollectionChangeEventHandler(itemcollection_CollectionChanged);
}
void vscrollbar_MouseWheel(object sender, MouseEventArgs e)
...{
}
/**//// <summary>
/// 标题
/// </summary>
[Category("JCS属性"),Description("容器标题")]
public string Caption
...{
get ...{ return this.m_caption ;}
set
...{
this.m_caption = value;
this.Invalidate();
}
}
void vscrollbar_Scroll(object sender, ScrollEventArgs e)
...{
int itemwidth = 0;
itemwidth = this.Width - 2 - this.vscrollbar.Width;
int firsttop = 22;
int firstindex = (int)(System.Math.Ceiling((double)e.NewValue / c_normalheight));
this.firstitemindex = firstindex;
//itemcollection[firstindex].Visible = true ;
int j = 0;
for (int i = 0; i < itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
if (i < firstindex)
...{
item.Bounds = new Rectangle(1, 0, 0, 0);
}
else
...{
item.Bounds = new Rectangle(1, firsttop * (j + 1), itemwidth, c_normalheight);
j++;
}
}
if(e.NewValue !=e.OldValue )
this.Invalidate();
//MessageBox.Show(this.vscrollbar.Maximum.ToString());
//MessageBox.Show(this.vscrollbar.Value.ToString());
}
private void adjustscroll()
...{
if (this.Height >= this.itemcollection.Count * c_normalheight + 21)
...{
this.vscrollbar.Visible = false;
for (int i = 0; i < itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
item.Width = this.Width - 2;
}
}
else
...{
this.vscrollbar.Visible = true;
for (int i = 0; i < itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
item.Width = this.Width - 2 - this.vscrollbar.Width ;
}
vscrollbar.Maximum = (this.itemcollection.Count + 1) * c_normalheight - this.Height + 2 * c_normalheight + c_normalheight;
vscrollbar.Minimum = 0;
}
}
void itemcollection_CollectionChanged(object sender, CollectionChangeEventArgs e)
...{
int itemwidth = 0;
if (this.vscrollbar.Visible)
...{
itemwidth = this.Width - 2 - this.vscrollbar.Width;
}
else
...{
itemwidth = this.Width - 2 ;
}
int firsttop = 22;
for (int i = 0; i < itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
item.Bounds = new Rectangle(1,firsttop * (i+1) ,itemwidth ,c_normalheight );
}
this.adjustscroll();
this.Invalidate();
}
/**//// <summary>
/// 元素集合
/// </summary>
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
Category("JCS属性"),Description("元素集合")]
public ViewItemCollection Items
...{
get ...{ return itemcollection; }
}
public JcsViewItem SelectedItem
...{
get ...{ return this.selecteditem; }
set
...{
if (value != null)
...{
if (this.selecteditem != null)
...{
this.selecteditem.IsMouseDown = false;
this.Invalidate(selecteditem.Bounds);
}
this.selecteditem = value;
this.selecteditem.IsMouseDown = true;
this.Invalidate(selecteditem.Bounds);
}
}
}
protected override void OnPaint(PaintEventArgs e)
...{
base.OnPaint(e);
Graphics g = e.Graphics;
drawheader(g);
drawitem(g);
}
protected override void OnResize(EventArgs e)
...{
base.OnResize(e);
//int t = this.Height%c_normalheight ;
//if (t != 0)
// this.Height -= t ;
adjustscroll();
}
private void drawheader(Graphics g)
...{
using(SolidBrush b = new SolidBrush(Color.Black))
...{
g.DrawString(this.m_caption , this.Font, b, 2, 4);
}
ControlPaint.DrawBorder3D(g, 0, 0, this.Width, c_normalheight, Border3DStyle.RaisedInner);
}
private void drawitem(Graphics g)
...{
ItemFont itemfont = new ItemFont(this.Font ,Color.LightYellow ,Color.Blue );
for (int i = firstitemindex; i < this.itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
item.DrawViewItem(g, itemfont);
}
}
protected override void OnMouseDown(MouseEventArgs e)
...{
this.Focus();
base.OnMouseDown(e);
if (e.Button == MouseButtons.Left)
...{
if (e.Clicks == 1)
...{
for (int i = 0; i < itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
if (item.Bounds.Contains(e.Location))
...{
this.SelectedItem = item;
//item.IsMouseDown = true;
//this.Invalidate(item.Bounds);
break;
}
}
}
else if (e.Clicks == 2)
...{
for (int i = 0; i < itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
if (item.Bounds.Contains(e.Location))
...{
this.DoubleClickItem(item);
}
}
}
}
}
protected override void OnMouseWheel(MouseEventArgs e)
...{
base.OnMouseWheel(e);
//MessageBox.Show(e.Y.ToString());
if (e.Delta > 0)
...{
if (this.vscrollbar.Visible)
...{
int currentvalue = this.vscrollbar.Value;
if (currentvalue >0)
...{
if (this.vscrollbar.Value - c_normalheight > 0)
...{
this.vscrollbar.Value -= c_normalheight;
}
else
...{
this.vscrollbar.Value = 0;
}
int itemwidth = 0;
itemwidth = this.Width - 2 - this.vscrollbar.Width;
int firsttop = 22;
int firstindex = (int)(System.Math.Ceiling((double)this.vscrollbar.Value / c_normalheight));
this.firstitemindex = firstindex;
//itemcollection[firstindex].Visible = true ;
int j = 0;
for (int i = 0; i < itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
if (i < firstindex)
...{
item.Bounds = new Rectangle(1, 0, 0, 0);
}
else
...{
item.Bounds = new Rectangle(1, firsttop * (j + 1), itemwidth, c_normalheight);
j++;
}
}
//if (e.NewValue != e.OldValue)
this.Invalidate();
}
}
}
else
...{
if (this.vscrollbar.Visible)
...{
int currentvalue = this.vscrollbar.Value;
if ((this.itemcollection.Count +1)* c_normalheight - currentvalue > this.Height - c_normalheight )
...{
this.vscrollbar.Value += c_normalheight;
int itemwidth = 0;
itemwidth = this.Width - 2 - this.vscrollbar.Width;
int firsttop = 22;
int firstindex = (int)(System.Math.Ceiling((double)this.vscrollbar.Value / c_normalheight));
this.firstitemindex = firstindex;
//itemcollection[firstindex].Visible = true ;
int j = 0;
for (int i = 0; i < itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
if (i < firstindex)
...{
item.Bounds = new Rectangle(1, 0, 0, 0);
}
else
...{
item.Bounds = new Rectangle(1, firsttop * (j + 1), itemwidth, c_normalheight);
j++;
}
}
//if (e.NewValue != e.OldValue)
this.Invalidate();
}
}
}
}
}
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace JcsCalendar
... {
public partial class JcsItemList : UserControl
...{
private const int c_headerheight = 4 ;//抬头高
private const int c_seheight = 2;//间隔高
private const int c_normalheight = 21;
private int firstitemindex = 0 ;
private int lastitemindex;
private ViewItemCollection itemcollection;
private VScrollBar vscrollbar;
private string m_caption = "JcsItemList";
private JcsViewItem selecteditem;
public delegate void ItemDoubleClick(JcsViewItem sender);
public event ItemDoubleClick DoubleClickItem;
//private OfficeRenderer render;
public JcsItemList()
...{
InitializeComponent();
//render = new OfficeRenderer();
this.BorderStyle = BorderStyle.FixedSingle ;
this.MinimumSize = new Size(100, c_normalheight * 2);
this.BackColor = Color.White;
vscrollbar = new VScrollBar();
vscrollbar.SmallChange = c_normalheight;
vscrollbar.LargeChange = c_normalheight * 2;
vscrollbar.Dock = DockStyle.Right;
this.Controls.Add(vscrollbar);
//vscrollbar.Value = 21;
vscrollbar.Scroll += new ScrollEventHandler(vscrollbar_Scroll);
vscrollbar.MouseWheel += new MouseEventHandler(vscrollbar_MouseWheel);
itemcollection = new ViewItemCollection();
itemcollection.CollectionChanged += new CollectionChangeEventHandler(itemcollection_CollectionChanged);
}
void vscrollbar_MouseWheel(object sender, MouseEventArgs e)
...{
}
/**//// <summary>
/// 标题
/// </summary>
[Category("JCS属性"),Description("容器标题")]
public string Caption
...{
get ...{ return this.m_caption ;}
set
...{
this.m_caption = value;
this.Invalidate();
}
}
void vscrollbar_Scroll(object sender, ScrollEventArgs e)
...{
int itemwidth = 0;
itemwidth = this.Width - 2 - this.vscrollbar.Width;
int firsttop = 22;
int firstindex = (int)(System.Math.Ceiling((double)e.NewValue / c_normalheight));
this.firstitemindex = firstindex;
//itemcollection[firstindex].Visible = true ;
int j = 0;
for (int i = 0; i < itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
if (i < firstindex)
...{
item.Bounds = new Rectangle(1, 0, 0, 0);
}
else
...{
item.Bounds = new Rectangle(1, firsttop * (j + 1), itemwidth, c_normalheight);
j++;
}
}
if(e.NewValue !=e.OldValue )
this.Invalidate();
//MessageBox.Show(this.vscrollbar.Maximum.ToString());
//MessageBox.Show(this.vscrollbar.Value.ToString());
}
private void adjustscroll()
...{
if (this.Height >= this.itemcollection.Count * c_normalheight + 21)
...{
this.vscrollbar.Visible = false;
for (int i = 0; i < itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
item.Width = this.Width - 2;
}
}
else
...{
this.vscrollbar.Visible = true;
for (int i = 0; i < itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
item.Width = this.Width - 2 - this.vscrollbar.Width ;
}
vscrollbar.Maximum = (this.itemcollection.Count + 1) * c_normalheight - this.Height + 2 * c_normalheight + c_normalheight;
vscrollbar.Minimum = 0;
}
}
void itemcollection_CollectionChanged(object sender, CollectionChangeEventArgs e)
...{
int itemwidth = 0;
if (this.vscrollbar.Visible)
...{
itemwidth = this.Width - 2 - this.vscrollbar.Width;
}
else
...{
itemwidth = this.Width - 2 ;
}
int firsttop = 22;
for (int i = 0; i < itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
item.Bounds = new Rectangle(1,firsttop * (i+1) ,itemwidth ,c_normalheight );
}
this.adjustscroll();
this.Invalidate();
}
/**//// <summary>
/// 元素集合
/// </summary>
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
Category("JCS属性"),Description("元素集合")]
public ViewItemCollection Items
...{
get ...{ return itemcollection; }
}
public JcsViewItem SelectedItem
...{
get ...{ return this.selecteditem; }
set
...{
if (value != null)
...{
if (this.selecteditem != null)
...{
this.selecteditem.IsMouseDown = false;
this.Invalidate(selecteditem.Bounds);
}
this.selecteditem = value;
this.selecteditem.IsMouseDown = true;
this.Invalidate(selecteditem.Bounds);
}
}
}
protected override void OnPaint(PaintEventArgs e)
...{
base.OnPaint(e);
Graphics g = e.Graphics;
drawheader(g);
drawitem(g);
}
protected override void OnResize(EventArgs e)
...{
base.OnResize(e);
//int t = this.Height%c_normalheight ;
//if (t != 0)
// this.Height -= t ;
adjustscroll();
}
private void drawheader(Graphics g)
...{
using(SolidBrush b = new SolidBrush(Color.Black))
...{
g.DrawString(this.m_caption , this.Font, b, 2, 4);
}
ControlPaint.DrawBorder3D(g, 0, 0, this.Width, c_normalheight, Border3DStyle.RaisedInner);
}
private void drawitem(Graphics g)
...{
ItemFont itemfont = new ItemFont(this.Font ,Color.LightYellow ,Color.Blue );
for (int i = firstitemindex; i < this.itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
item.DrawViewItem(g, itemfont);
}
}
protected override void OnMouseDown(MouseEventArgs e)
...{
this.Focus();
base.OnMouseDown(e);
if (e.Button == MouseButtons.Left)
...{
if (e.Clicks == 1)
...{
for (int i = 0; i < itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
if (item.Bounds.Contains(e.Location))
...{
this.SelectedItem = item;
//item.IsMouseDown = true;
//this.Invalidate(item.Bounds);
break;
}
}
}
else if (e.Clicks == 2)
...{
for (int i = 0; i < itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
if (item.Bounds.Contains(e.Location))
...{
this.DoubleClickItem(item);
}
}
}
}
}
protected override void OnMouseWheel(MouseEventArgs e)
...{
base.OnMouseWheel(e);
//MessageBox.Show(e.Y.ToString());
if (e.Delta > 0)
...{
if (this.vscrollbar.Visible)
...{
int currentvalue = this.vscrollbar.Value;
if (currentvalue >0)
...{
if (this.vscrollbar.Value - c_normalheight > 0)
...{
this.vscrollbar.Value -= c_normalheight;
}
else
...{
this.vscrollbar.Value = 0;
}
int itemwidth = 0;
itemwidth = this.Width - 2 - this.vscrollbar.Width;
int firsttop = 22;
int firstindex = (int)(System.Math.Ceiling((double)this.vscrollbar.Value / c_normalheight));
this.firstitemindex = firstindex;
//itemcollection[firstindex].Visible = true ;
int j = 0;
for (int i = 0; i < itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
if (i < firstindex)
...{
item.Bounds = new Rectangle(1, 0, 0, 0);
}
else
...{
item.Bounds = new Rectangle(1, firsttop * (j + 1), itemwidth, c_normalheight);
j++;
}
}
//if (e.NewValue != e.OldValue)
this.Invalidate();
}
}
}
else
...{
if (this.vscrollbar.Visible)
...{
int currentvalue = this.vscrollbar.Value;
if ((this.itemcollection.Count +1)* c_normalheight - currentvalue > this.Height - c_normalheight )
...{
this.vscrollbar.Value += c_normalheight;
int itemwidth = 0;
itemwidth = this.Width - 2 - this.vscrollbar.Width;
int firsttop = 22;
int firstindex = (int)(System.Math.Ceiling((double)this.vscrollbar.Value / c_normalheight));
this.firstitemindex = firstindex;
//itemcollection[firstindex].Visible = true ;
int j = 0;
for (int i = 0; i < itemcollection.Count; i++)
...{
JcsViewItem item = itemcollection[i] as JcsViewItem;
if (i < firstindex)
...{
item.Bounds = new Rectangle(1, 0, 0, 0);
}
else
...{
item.Bounds = new Rectangle(1, firsttop * (j + 1), itemwidth, c_normalheight);
j++;
}
}
//if (e.NewValue != e.OldValue)
this.Invalidate();
}
}
}
}
}
}