终于脱掉了5个小裤衩。。。。
前一段时间有人问过如何弄一个类似Iphone的list control,这两天写了一个,贴出来分享一下,不过功能还未完善。
- C# code
public partial class CustomListControl : Control { public CustomListControl() { InitializeComponent(); SetStyle(ControlStyles.Selectable, true); SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true ); } protected override void OnPaint(PaintEventArgs pe) { base.OnPaint(pe); // Draw background Rectangle clientRect = new Rectangle( kBorderWidth, kBorderWidth, this.ClientRectangle.Width - 2 * kBorderWidth, this.ClientRectangle.Height - 2 * kBorderWidth ); using (LinearGradientBrush b = new LinearGradientBrush( clientRect, Color.Black, Color.White, 90f) ) { Blend blend = new Blend(); blend.Positions = new float[] { 0.0f, 0.04f, 0.08f, 0.12f, 0.15f, 0.5f, 0.85f, 0.88f, 0.92f, 0.96f, 1f }; blend.Factors = new float[] { .2f, .4f, 0.6f, 0.8f, 0.85f, 0.95f, .85f, .8f, .6f, .4f, .2f }; b.Blend = blend; pe.Graphics.FillRectangle(b, clientRect); } // Draw border using (Pen p = new Pen(Color.FromArgb(127, 127, 127))) { p.Width = kBorderWidth; pe.Graphics.DrawRectangle( p, new Rectangle( kBorderWidth / 2, kBorderWidth / 2, this.Width - kBorderWidth, this.Height - kBorderWidth ) ); } // Draw selected focus Rectangle selectedBound = new Rectangle( this.ClientRectangle.X, this.ClientRectangle.Y + ((Int32)m_DisplayItemCount / 2) * this.ClientRectangle.Height / (Int32)m_DisplayItemCount, this.ClientRectangle.Width, this.ClientRectangle.Height / (Int32)m_DisplayItemCount ); using (Pen p = new Pen(Color.FromArgb(100, 100, 100, 100))) { pe.Graphics.DrawLine( p, new Point(selectedBound.X, selectedBound.Y), new Point(selectedBound.X + selectedBound.Width, selectedBound.Y) ); } using (Pen p = new Pen(Color.FromArgb(100, 250, 250, 250))) { pe.Graphics.DrawLine( p, new Point(selectedBound.X, selectedBound.Y + 1), new Point(selectedBound.X + selectedBound.Width, selectedBound.Y + 1) ); } using (Pen p = new Pen(Color.FromArgb(100, 100, 100, 100))) { pe.Graphics.DrawLine( p, new Point(selectedBound.X, selectedBound.Y + selectedBound.Height - 2), new Point(selectedBound.X + selectedBound.Width, selectedBound.Y + selectedBound.Height - 2) ); } using (Pen p = new Pen(Color.FromArgb(100, 250, 250, 250))) { pe.Graphics.DrawLine( p, new Point(selectedBound.X, selectedBound.Y + selectedBound.Height - 1), new Point(selectedBound.X + selectedBound.Width, selectedBound.Y + selectedBound.Height - 1) ); } using (Brush b = new SolidBrush(Color.FromArgb(100, 255, 255, 255))) { pe.Graphics.FillRectangle( b, new Rectangle( selectedBound.X, selectedBound.Y + 2, selectedBound.Width, selectedBound.Height / 2 - 2 ) ); } using (Brush b = new SolidBrush(Color.FromArgb(100, 180, 180, 180))) { pe.Graphics.FillRectangle( b, new Rectangle( selectedBound.X, selectedBound.Y + selectedBound.Height / 2 + 1, selectedBound.Width, selectedBound.Height / 2 - 2 ) ); } // Draw display items if (m_Items.Count == 0) return; using (Brush b = new SolidBrush(this.ForeColor)) { for (Int32 i = 0; i < (Int32)m_DisplayItemCount; i++) { Rectangle bound = new Rectangle( clientRect.X, clientRect.Y + i * clientRect.Height / (Int32)m_DisplayItemCount, clientRect.Width, clientRect.Height / (Int32)m_DisplayItemCount ); Int32 index = m_CurrentIndex + i - (Int32)m_DisplayItemCount / 2; if (index < 0) index += m_Items.Count; if (index >= m_Items.Count) index %= m_Items.Count; String item = m_Items[index]; using (StringFormat sf = new StringFormat()) { sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Center; pe.Graphics.DrawString(item, this.Font, b, bound, sf); } } } } protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e) { base.OnPreviewKeyDown(e); switch (e.KeyCode) { case Keys.Up: m_CurrentIndex--; if (m_CurrentIndex < 0) m_CurrentIndex += m_Items.Count; this.Invalidate(); break; case Keys.Down: m_CurrentIndex++; if (m_CurrentIndex >= m_Items.Count) m_CurrentIndex %= m_Items.Count; this.Invalidate(); break; default: break; } } protected override void OnMouseWheel(MouseEventArgs e) { base.OnMouseWheel(e); m_CurrentIndex -= e.Delta / 120; NormalizeCurrentIndex(); this.Invalidate(); } protected override void OnMouseClick(MouseEventArgs e) { base.OnMouseClick(e); Int32 delta = e.Y / (this.ClientRectangle.Height / (Int32)m_DisplayItemCount); m_CurrentIndex += delta - 2; NormalizeCurrentIndex(); this.Invalidate(); } [DefaultValue(0)] private Int32 CurrentIndex { get { return m_CurrentIndex; } set { m_CurrentIndex = value; } } public List<String> Items { get { return m_Items; } } [DefaultValue(DisplayItemCountEnum.Normal)] public DisplayItemCountEnum DisplayItemCount { get { return m_DisplayItemCount; } set { m_DisplayItemCount = value; } } private void NormalizeCurrentIndex() { if (m_CurrentIndex >= m_Items.Count) m_CurrentIndex %= m_Items.Count; if (m_CurrentIndex < 0) m_CurrentIndex += m_Items.Count; } private List<String> m_Items = new List<String>(); private Int32 m_CurrentIndex; private DisplayItemCountEnum m_DisplayItemCount = DisplayItemCountEnum.Normal; private const Int32 kBorderWidth = 3; public enum DisplayItemCountEnum { Less = 3, Normal = 5, More = 7 } }