一.設計時效果:
二.運行時效果:
三.簡單談談實現思路:
由於昨天時間比較緊張,沒有把全部的功能都做完善就發布出來了,今天把鍵盤操作給加上了,並修改了一些操作上的小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;
&nb 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 )
&n ...{
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();
}
}
}
}
}
}