一.設計時效果:



二.運行時效果:


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

}

}

}

}

}

}