プログラムです。
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.ComponentModel.Design.Serialization;
namespace SpreadControl
{
/// <summary>
/// SpreadControl の概要の説明です。
///
/// 2004/06/27
/// CurrentCell プロパティ対応
/// HitTest メソッド対応
/// マウスクリックによるセル移動対応
/// 上下キーよるセル移動対応
/// Tab・SHIFT+Tabキーよるセル移動対応
/// 2004/07/14
/// Cell プロパティにText/Font/ForeColor/BackColor追加
/// デフォルトインデクサによるCellプロパティの変更を可能にした
/// DataプロパティでCellプロパティの変更を可能にした
/// Dataプロパティは一次元配列で columns=3/rows=2 だと6要素できる
/// 0=0,0 / 1=0,1 / 2=0,2 / 3=1,0 / 4=1,1 / 5=1,2 に対応する
/// </summary>
public class SpreadControl : System.Windows.Forms.UserControl ,ISupportInitialize
{
#region ローカル変数
private bool init ;
private int columns ;
private int rows ;
private int preferredColumnWidth ;
private int preferredRowHeight ;
private int currentColumnIndex ;
private int currentRowIndex ;
private Cell[] item ;
private int oldcolumns ;
private int oldrows ;
#endregion
#region コンポーネント デザイナで生成された変数
private System.Windows.Forms.TextBox textBox1;
/// <summary>
/// 必要なデザイナ変数です。
/// </summary>
private System.ComponentModel.Container components = null;
#endregion
#region クラスの生成・消滅
public SpreadControl()
{
init = true ;
// この呼び出しは、Windows.Forms フォーム デザイナで必要です。
InitializeComponent();
// TODO: InitComponent 呼び出しの後に初期化処理を追加してください。
columns = 3 ;
rows = 2 ;
preferredColumnWidth = 75 ;
preferredRowHeight = 15 ;
currentColumnIndex = 0 ;
currentRowIndex = 0 ;
item = new Cell[rows * columns] ;
for ( int i=0 ; i<rows * columns ; i++ )
{
item[i] = new Cell() ;
item[i].PropertyChange += new System.EventHandler(this.Cell_PropertyChange);
}
oldcolumns = 3 ;
oldrows = 2 ;
}
/// <summary>
/// 使用されているリソースに後処理を実行します。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if( components != null )
components.Dispose();
}
base.Dispose( disposing );
}
private void SpreadControl_Load(object sender, System.EventArgs e)
{
textBox1.BorderStyle = BorderStyle.None ;
ResizeDisplay() ;
}
#endregion
#region コンポーネント デザイナで生成されたコード
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード]エディタで変更しないでください。
/// </summary>
private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(0, 24);
this.textBox1.Name = "textBox1";
this.textBox1.TabIndex = 0;
this.textBox1.Text = "textBox1";
//
// SpreadControl
//
this.AutoScroll = true;
this.Controls.Add(this.textBox1);
this.Name = "SpreadControl";
this.Load += new System.EventHandler(this.SpreadControl_Load);
this.Enter += new System.EventHandler(this.SpreadControl_Enter);
this.FontChanged += new System.EventHandler(this.SpreadControl_FontChanged);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SpreadControl_MouseUp);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.SpreadControl_Paint);
this.Leave += new System.EventHandler(this.SpreadControl_Leave);
this.ResumeLayout(false);
}
#endregion
#region ローカルメソッド
private bool IncludeClient(Rectangle rectcheck)
{
Rectangle rect = ClientRectangle ;
rect.Offset( -AutoScrollPosition.X, -AutoScrollPosition.Y ) ;
if ( rect.Left <= rectcheck.Left &&
rect.Top <= rectcheck.Top &&
rect.Right >= rectcheck.Right &&
rect.Bottom >= rectcheck.Bottom )
{
return true ;
}
return false ;
}
private void ResizeDisplay()
{
textBox1.Size = new Size(preferredColumnWidth - 1, preferredRowHeight - 1) ;
textBox1.Visible = false ;
if ( preferredColumnWidth < textBox1.Size.Width + 1 )
{
preferredColumnWidth = textBox1.Size.Width + 1 ;
}
if ( preferredRowHeight < textBox1.Size.Height + 1 )
{
preferredRowHeight = textBox1.Size.Height + 1 ;
}
AutoScrollMinSize = new Size( preferredColumnWidth * columns + 1, preferredRowHeight * rows + 1 ) ;
Refresh() ;
}
private void ResizeData()
{
Cell[] newitem = new Cell[rows * columns] ;
for ( int i=0 ; i<rows * columns ; i++ )
{
newitem[i] = new Cell() ;
newitem[i].PropertyChange += new System.EventHandler(this.Cell_PropertyChange);
}
for ( int i=0 ; i<oldrows && i<rows ; i++ )
{
for ( int j=0 ; j<oldcolumns && j<columns ; j++ )
{
newitem[i * columns + j] = item[i * oldcolumns + j] ;
}
}
item = newitem ;
oldcolumns = columns ;
oldrows = rows ;
ResizeDisplay() ;
}
private void EnterTextBox()
{
Rectangle rect = new Rectangle( currentColumnIndex * preferredColumnWidth,
currentRowIndex * preferredRowHeight,
preferredColumnWidth, preferredRowHeight ) ;
if ( !IncludeClient( rect ) )
{
AutoScrollPosition = new Point(rect.Right + 1 - ClientRectangle.Right,
rect.Bottom + 1 - ClientRectangle.Bottom ) ;
}
textBox1.Location = new Point( AutoScrollPosition.X + currentColumnIndex * preferredColumnWidth + 1,
AutoScrollPosition.Y + currentRowIndex * preferredRowHeight + 1 ) ;
textBox1.Size = new Size(preferredColumnWidth - 1, preferredRowHeight - 1) ;
textBox1.Visible = true ;
textBox1.Text = this[currentRowIndex,currentColumnIndex].Text ;
textBox1.BackColor = this[currentRowIndex,currentColumnIndex].BackColor ;
textBox1.ForeColor = this[currentRowIndex,currentColumnIndex].ForeColor ;
textBox1.Font = this[currentRowIndex,currentColumnIndex].Font ;
textBox1.Focus() ;
}
private void LeaveTextBox()
{
this[currentRowIndex,currentColumnIndex].Text = textBox1.Text ;
textBox1.Visible = false ;
}
private void MoveTo( int column, int row )
{
LeaveTextBox() ;
currentColumnIndex = column ;
currentRowIndex = row ;
EnterTextBox() ;
}
private void MoveTo( SpreadCell cell )
{
MoveTo( cell.ColumnNumber, cell.RowNumber ) ;
}
private void MoveUp()
{
LeaveTextBox() ;
currentRowIndex -- ;
if ( currentRowIndex < 0 )
{
currentRowIndex = 0 ;
}
EnterTextBox() ;
}
private void MoveDown()
{
LeaveTextBox() ;
currentRowIndex ++ ;
if ( currentRowIndex >= rows )
{
currentRowIndex = rows - 1 ;
}
EnterTextBox() ;
}
private void MoveLeft()
{
LeaveTextBox() ;
currentColumnIndex -- ;
if ( currentColumnIndex < 0 )
{
currentColumnIndex = columns - 1 ;
currentRowIndex -- ;
}
if ( currentRowIndex < 0 )
{
currentColumnIndex = 0 ;
currentRowIndex = 0 ;
}
EnterTextBox() ;
}
private void MoveRight()
{
LeaveTextBox() ;
currentColumnIndex ++ ;
if ( currentColumnIndex >= columns )
{
currentColumnIndex = 0 ;
currentRowIndex ++ ;
}
if ( currentRowIndex >= rows )
{
currentColumnIndex = columns - 1 ;
currentRowIndex = rows - 1 ;
}
EnterTextBox() ;
}
#endregion
#region 公開プロパティ
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public SpreadCell CurrentCell
{
get
{
SpreadCell cell = new SpreadCell( currentColumnIndex, currentRowIndex ) ;
return cell ;
}
set
{
if ( value.ColumnNumber >= 0 &&
value.ColumnNumber < columns &&
value.RowNumber >= 0 &&
value.RowNumber <= rows )
{
MoveTo( value ) ;
}
}
}
[Description("行数を示します。"),Category("配置")]
[RefreshProperties(RefreshProperties.All)]
public int Rows
{
get
{
return rows ;
}
set
{
rows = value ;
if ( DesignMode == true || init == false )
{
ResizeData() ;
}
}
}
[Description("列数を示します。"),Category("配置")]
[RefreshProperties(RefreshProperties.All)]
public int Columns
{
get
{
return columns ;
}
set
{
columns = value ;
if ( DesignMode == true || init == false )
{
ResizeData() ;
}
}
}
[Description("行の適切な高さを示します。"),Category("配置")]
[RefreshProperties(RefreshProperties.All)]
public int PreferredRowHeight
{
get
{
return preferredRowHeight ;
}
set
{
preferredRowHeight = value ;
if ( DesignMode == true || init == false )
{
ResizeDisplay() ;
}
}
}
[Description("列の適切な幅を示します。"),Category("配置")]
[RefreshProperties(RefreshProperties.All)]
public int PreferredColumnWidth
{
get
{
return preferredColumnWidth ;
}
set
{
preferredColumnWidth = value ;
if ( DesignMode == true || init == false )
{
ResizeDisplay() ;
}
}
}
public Cell this [int rowindex,int columnindex]
{
get
{
if ( rowindex >= 0 && rowindex < rows &&
columnindex >= 0 && columnindex < columns )
{
return item[rowindex * columns + columnindex] ;
}
return null ;
}
set
{
if ( rowindex >= 0 && rowindex < rows &&
columnindex >= 0 && columnindex < columns )
{
item[rowindex * columns + columnindex] = value ;
}
}
}
[Description("セルの表示を取得設定します。"),Category("配置")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Cell[] Data
{
get
{
return item ;
}
set
{
item = value ;
}
}
#endregion
#region 公開メソッド
public HitTestInfo HitTest( int x, int y )
{
HitTestInfo hittestinfo = new HitTestInfo() ;
x -= AutoScrollPosition.X ;
y -= AutoScrollPosition.Y ;
int px = x / preferredColumnWidth ;
int py = y / preferredRowHeight ;
if ( px >= columns || py >= rows )
{
return hittestinfo ;
}
hittestinfo = new HitTestInfo(px, py, HitTestType.Cell) ;
return hittestinfo ;
}
public HitTestInfo HitTest( Point position )
{
return HitTest( position.X, position.Y ) ;
}
public void BeginInit()
{
init = true ;
}
public void EndInit()
{
ResizeData() ;
init = false ;
}
public Cell GetCell( int rowindex,int columnindex )
{
if ( rowindex >= 0 && rowindex < rows &&
columnindex >= 0 && columnindex < columns )
{
return item[rowindex * columns + columnindex] ;
}
return null ;
}
public void SetCell( Cell cell, int rowindex,int columnindex )
{
if ( rowindex >= 0 && rowindex < rows &&
columnindex >= 0 && columnindex < columns )
{
item[rowindex * columns + columnindex] = cell ;
}
}
#endregion
#region イベント処理
private void SpreadControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
int px, sx, py, sy ;
Pen pen ;
Brush brush, brushback ;
Rectangle rect, recttext ;
if ( DesignMode == true || init == false )
{
for ( int i=0 ; i<rows ; i++ )
{
py = AutoScrollPosition.Y + i * preferredRowHeight + 1 ;
sy = preferredRowHeight - 1 ;
for ( int j=0 ; j<columns ; j++ )
{
px = AutoScrollPosition.X + j * preferredColumnWidth + 1 ;
sx = preferredColumnWidth - 1 ;
rect = new Rectangle( px, py, sx, sy ) ;
pen = new Pen(this[i,j].ForeColor,1) ;
brush = new SolidBrush(this[i,j].ForeColor) ;
brushback = new SolidBrush(this[i,j].BackColor) ;
e.Graphics.FillRectangle( brushback, rect ) ;
rect.Inflate( 1, 1 ) ;
recttext = new Rectangle( rect.X - 1, rect.Y + 1, rect.Width, rect.Height ) ;
e.Graphics.DrawString( this[i,j].Text, this[i,j].Font, brush, recttext ) ;
e.Graphics.DrawRectangle( pen, rect ) ;
}
}
}
}
private void SpreadControl_Enter(object sender, System.EventArgs e)
{
EnterTextBox() ;
}
private void SpreadControl_Leave(object sender, System.EventArgs e)
{
LeaveTextBox() ;
Refresh() ;
}
private void SpreadControl_FontChanged(object sender, System.EventArgs e)
{
if ( DesignMode == true || init == false )
{
ResizeDisplay() ;
}
}
private void SpreadControl_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
HitTestInfo hittestinfo = HitTest( e.X, e.Y ) ;
if ( hittestinfo.Type == HitTestType.Cell )
{
MoveTo( hittestinfo.Column, hittestinfo.Row ) ;
}
}
protected override bool ProcessCmdKey(ref Message m,Keys keyData)
{
const int WM_KEYDOWN = 0x0100;
if ( m.Msg == WM_KEYDOWN )
{
switch ( keyData )
{
case Keys.Tab :
{
MoveRight() ;
return true ;
}
case Keys.Shift | Keys.Tab:
{
MoveLeft() ;
return true ;
}
case Keys.Up:
{
MoveUp() ;
return true ;
}
case Keys.Down :
{
MoveDown() ;
return true ;
}
}
}
return base.ProcessCmdKey(ref m,keyData) ;
}
private void Cell_PropertyChange(object sender, System.EventArgs e)
{
Refresh() ;
}
#endregion
}
#region ヒットテストクラス
[Serializable]
[TypeConverter(typeof(HitTestTypeConverter))]
public enum HitTestType
{
None = 0 ,
Cell = 1
}
internal class HitTestTypeConverter : ExpandableObjectConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string)) return true;
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value, Type destType)
{
if (destType == typeof(string) && value is HitTestType)
{
HitTestType ic = (HitTestType)value;
switch ( ic )
{
case HitTestType.None: return "None" ;
case HitTestType.Cell: return "Cell" ;
}
return "" ;
}
return base.ConvertTo(context, culture, value, destType);
}
}
[Serializable]
[TypeConverter(typeof(HitTestInfoConverter))]
public class HitTestInfo
{
private int _column ;
private int _row ;
private HitTestType _type ;
public HitTestInfo()
{
_column = -1 ;
_row = -1 ;
_type = HitTestType.None ;
}
public HitTestInfo(int column, int row, HitTestType type)
{
_column = column ;
_row = row ;
_type = type ;
}
public int Column { get { return _column ; } }
public int Row { get { return _row ; } }
public HitTestType Type { get { return _type ; } }
}
internal class HitTestInfoConverter : ExpandableObjectConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string)) return true;
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value, Type destType)
{
if (destType == typeof(string) && value is HitTestInfo)
{
HitTestInfo ic = (HitTestInfo)value;
return ic.Column.ToString() + "," + ic.Row.ToString() + "," + ic.Type.ToString() ;
}
return base.ConvertTo(context, culture, value, destType);
}
}
#endregion
#region スプレッドシートセルクラス
[Serializable]
[TypeConverter(typeof(SpreadCellConverter))]
public class SpreadCell
{
private int _columnNumber ;
private int _rowNumber ;
public SpreadCell()
{
_columnNumber = -1 ;
_rowNumber = -1 ;
}
public SpreadCell(int column, int row)
{
_columnNumber = column ;
_rowNumber = row ;
}
public int ColumnNumber { get { return _columnNumber ; } }
public int RowNumber { get { return _rowNumber ; } }
}
internal class SpreadCellConverter : ExpandableObjectConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string)) return true;
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value, Type destType)
{
if (destType == typeof(string) && value is SpreadCell)
{
SpreadCell ic = (SpreadCell)value;
return ic.ColumnNumber.ToString() + "," + ic.RowNumber.ToString() ;
}
return base.ConvertTo(context, culture, value, destType);
}
}
#endregion
#region セルプロパティクラス
[Serializable]
[TypeConverter(typeof(CellConverter))]
public class Cell
{
private string _text ;
private Font _font ;
private Color _forecolor ;
private Color _backcolor ;
public Cell()
{
_text = "" ;
_font = TextBox.DefaultFont ;
_forecolor = TextBox.DefaultForeColor ;
_backcolor = TextBox.DefaultBackColor ;
}
public Cell(string text, Font font, Color forecolor, Color backcolor)
{
_text = text ;
_font = font ;
_forecolor = forecolor ;
_backcolor = backcolor ;
RaisePropertyChange() ;
}
[Description("セルのテキストです。"),Category("表示")]
public string Text
{
get
{
return _text ;
}
set
{
_text = value ;
RaisePropertyChange() ;
}
}
[Description("セルでテキストを表示するフォントです。"),Category("表示")]
public Font Font
{
get
{
return _font ;
}
set
{
_font = value ;
RaisePropertyChange() ;
}
}
[Description("セルでテキストを表示するために使用する前景色です。"),Category("表示")]
public Color ForeColor
{
get
{
return _forecolor ;
}
set
{
_forecolor = value ;
RaisePropertyChange() ;
}
}
[Description("セルでテキストを表示するために使用する背景色です。"),Category("表示")]
public Color BackColor
{
get
{
return _backcolor ;
}
set
{
_backcolor = value ;
RaisePropertyChange() ;
}
}
private EventHandler onPropertyChange ;
[Description("プロパティ変更されたときに発生します。"),Category("アクション")]
public event EventHandler PropertyChange
{ add { onPropertyChange += value; } remove { onPropertyChange -= value; } }
protected virtual void OnPropertyChange(EventArgs e)
{
if (onPropertyChange != null) onPropertyChange(this, e);
}
private void RaisePropertyChange()
{
EventArgs e = new EventArgs() ;
OnPropertyChange( e ) ;
}
}
internal class CellConverter : ExpandableObjectConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string)) return true;
if (destinationType == typeof(InstanceDescriptor)) return true;
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value, Type destType)
{
if (destType == typeof(string) && value is Cell)
{
Cell ic = (Cell)value;
return ic.Text + "," + ic.Font.ToString() + "," +
ic.ForeColor.ToString() + "," + ic.BackColor.ToString() ;
}
if (destType == typeof(InstanceDescriptor) && value is Cell)
{
Cell ic = (Cell)value;
System.Reflection.ConstructorInfo ctor = typeof(Cell).GetConstructor(new Type[] {
typeof(string), typeof(Font), typeof(Color), typeof(Color) } ) ;
if (ctor != null)
{
return new InstanceDescriptor(ctor, new object[] {ic.Text, ic.Font, ic.ForeColor, ic.BackColor}) ;
}
}
return base.ConvertTo(context, culture, value, destType);
}
}
#endregion
}



