using System;
using System.Windows.Forms;
using nsExternalScrollbarListBox;
namespace ExternalScrollbarListBox_test
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private ExternalScrollbarListBox[] mLists = new ExternalScrollbarListBox[5];
private System.Windows.Forms.VScrollBar vScrollBar1;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
bool master = true;
for(int n = 0; n < mLists.Length; ++n)
{
mLists[n] = new ExternalScrollbarListBox();
for(int i = 0; i < 30; ++i)
{
mLists[n].Add(String.Format("{0,3} list{1}", i, n+1));
}
mLists[n].Name = "mList" + n;
mLists[n].TabIndex = n;
mLists[n].SetScrollBar(vScrollBar1, master);
master = false;
}
this.Controls.AddRange(mLists);
}
/// <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 Windows Form 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()
{
this.vScrollBar1 = new System.Windows.Forms.VScrollBar();
this.SuspendLayout();
//
// vScrollBar1
//
this.vScrollBar1.Location = new System.Drawing.Point(376, 184);
this.vScrollBar1.Name = "vScrollBar1";
this.vScrollBar1.Size = new System.Drawing.Size(16, 192);
this.vScrollBar1.TabIndex = 1;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(648, 525);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.vScrollBar1});
this.Name = "Form1";
this.Text = "Form1";
this.Layout += new System.Windows.Forms.LayoutEventHandler(this.Form1_HandleLayout);
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void Form1_HandleLayout(object sender, LayoutEventArgs e)
{
int x = 10;
int y = 10;
int width = 100;
int height = this.ClientSize.Height - 20;
for(int n = 0; n < mLists.Length; ++n)
{
mLists[n].SetBounds(x, y, width, height);
x += width;
}
vScrollBar1.SetBounds(x, y, vScrollBar1.Width, height);
}
}
}
|
using System;
using System.Collections;
using System.Windows.Forms;
using System.Drawing;
namespace nsExternalScrollbarListBox
{
/// <summary>
/// A ListBox-like control that has an external scrollbar
/// </summary>
public class ExternalScrollbarListBox : ListControl
{
private int cBorderWidth = SystemInformation.Border3DSize.Width;
private ScrollBarWrapper mScrollBar;
private int mSelectedIndex = -1;
private int mTopRow = 0;
private DrawMode mDrawMode = DrawMode.Normal;
private ArrayList mDrawItemDelegates = new ArrayList();
private ArrayList mList = new ArrayList();
private System.ComponentModel.Container components = null;
public ExternalScrollbarListBox()
{
Init();
mScrollBar = new NullScrollBar();
}
public event EventHandler SelectedIndexChanged;
public event DrawItemEventHandler DrawItem;
public delegate void DrawItemEventHandler(object sender, DrawItemEventArgs e);
public DrawMode DrawMode
{
set { mDrawMode = value; }
}
public object SelectedItem
{
set { mList[SelectedIndex] = value; }
get { return mList[SelectedIndex]; }
}
public void SetScrollBar(VScrollBar sb, bool master)
{
if (master)
mScrollBar = new MasterScrollBar(this, sb);
else
mScrollBar = new SlaveScrollBar(this, sb);
}
public void Add(object s)
{
mList.Add(s);
Invalidate();
}
public void AddRange(object[] r)
{
mList.AddRange(r);
Invalidate();
}
public void Clear()
{
mList.Clear();
Invalidate();
}
public ArrayList Items
{
get { return mList; }
}
public int IndexFromPoint(Point p)
{
int row = mTopRow + (p.Y - cBorderWidth) / RowHeight;
if (row >= mList.Count) return -1;
return row;
}
public int TopRow
{
set
{
if (mTopRow == value) return;
mTopRow = value;
Invalidate();
}
}
public override int SelectedIndex
{
set { mSelectedIndex = value; }
get { return mSelectedIndex; }
}
public new void SetBounds(int x, int y, int width, int height, BoundsSpecified specified)
{
base.SetBounds(x, y, width, height, specified);
Invalidate();
}
public new void SetBounds(int x, int y, int width, int height)
{
base.SetBounds(x, y, width, height);
Invalidate();
}
//--------- protected from here on
protected override void Dispose( bool disposing )
{
if( disposing )
{
if( components != null )
components.Dispose();
}
base.Dispose( disposing );
}
protected void HandleMouseDown(object sender, MouseEventArgs e)
{
int row = IndexFromPoint(new Point(e.X, e.Y));
if (row < 0) return;
Rectangle rct = new Rectangle(cBorderWidth, ((mSelectedIndex - mTopRow) * RowHeight) + cBorderWidth, this.Width - cBorderWidth, RowHeight);
if (mSelectedIndex >= mTopRow)
Invalidate(rct);
mSelectedIndex = row;
rct.Y = ((mSelectedIndex - mTopRow) * RowHeight) + cBorderWidth;
Invalidate(rct);
this.OnSelectedIndexChanged(EventArgs.Empty);
}
protected override void SetItemsCore(System.Collections.IList l)
{
}
protected override void RefreshItem(int i)
{
}
//--------- private from here on
private new void OnSelectedIndexChanged(EventArgs e)
{
if (SelectedIndexChanged == null) return;
SelectedIndexChanged(this, e);
}
//Removed the designer so that it didn't change this section
private void Init()
{
this.SuspendLayout();
this.BackColor = System.Drawing.Color.White;
this.CausesValidation = false;
this.Location = new System.Drawing.Point(8, 8);
this.Name = "mTextList";
this.SelectedIndex = 0;
this.Size = new System.Drawing.Size(88, 80);
this.TabIndex = 0;
this.Text = "mTextList";
this.TopRow = 0;
this.Name = "ExternalScrollbarListBox";
this.Size = new System.Drawing.Size(104, 96);
this.BackColor = Color.White;
this.Paint += new PaintEventHandler(HandlePaint);
this.MouseDown += new MouseEventHandler(HandleMouseDown);
this.ResumeLayout(false);
}
private int RowHeight
{
get { return this.Font.Height; }
}
//paint routines from here on
private void HandlePaint(object sender, PaintEventArgs e)
{
PaintBackground(e.Graphics);
PaintBorder(e.Graphics);
PaintList(e.Graphics);
mScrollBar.PaintScrollBar(this.mList.Count, VisibleRows);
}
private void PaintBackground(Graphics g)
{
g.FillRectangle(new SolidBrush(this.BackColor), 0, 0, this.Width, this.Height);
}
private void PaintBorder(Graphics g)
{
ControlPaint.DrawBorder3D(g, 0, 0, this.Width, this.Height);
}
private void PaintList(Graphics g)
{
MakeBottomRowVisible();
Rectangle rct = GetRowRectangle();
for(int row = this.mTopRow; row < this.mList.Count && CanPaintRow(rct); ++row, NextRow(ref rct))
PaintRow(g, row, rct);
}
private void MakeBottomRowVisible()
{
if (this.mTopRow < HiddenRows) return;
this.mTopRow = HiddenRows;
this.mScrollBar.Value = mTopRow;
}
private Rectangle GetRowRectangle()
{
return new Rectangle(cBorderWidth, cBorderWidth, this.Width - cBorderWidth, this.RowHeight);
}
private void PaintRow(Graphics g, int row, Rectangle rct)
{
if (row == this.mSelectedIndex)
PaintSelectedRow(g, row, rct);
else
PaintRow(g, row, rct, new SolidBrush(this.ForeColor), DrawItemState.Default);
}
private void PaintSelectedRow(Graphics g, int row, Rectangle rct)
{
g.FillRectangle(new SolidBrush(Color.Blue), rct);
PaintRow(g, row, rct, new SolidBrush(Color.White), DrawItemState.Selected);
}
private void PaintRow(Graphics g, int row, Rectangle rct, SolidBrush forecolor, DrawItemState state)
{
if (this.mDrawMode == System.Windows.Forms.DrawMode.Normal)
PaintRow(g, row, rct, forecolor);
else if (this.mDrawMode == System.Windows.Forms.DrawMode.OwnerDrawFixed)
PaintOwnerDrawRow(g, rct, row, state);
}
private void PaintOwnerDrawRow(Graphics g, Rectangle rct, int row, DrawItemState state)
{
this.OnDrawItem(new DrawItemEventArgs(g, this.Font, rct, row, state, this.ForeColor, this.BackColor));
}
private void OnDrawItem(DrawItemEventArgs e)
{
if (DrawItem == null) return;
DrawItem(this, e);
}
private void PaintRow(Graphics g, int row, Rectangle rct, SolidBrush forecolor)
{
g.DrawString(mList[row].ToString(), this.Font, forecolor, rct, StringFormat.GenericDefault);
}
private void NextRow(ref Rectangle rct)
{
rct.Y += RowHeight;
}
private bool CanPaintRow(RectangleF rct)
{
return (rct.Y + RowHeight) <= (this.Height - cBorderWidth);
}
private int HiddenRows
{
get { return Math.Max(mList.Count - VisibleRows, 0); }
}
private int VisibleRows
{
get { return VisibleHeight / RowHeight; }
}
private int VisibleHeight
{
get { return this.Height - (2 * cBorderWidth); }
}
}
}
|