using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
namespace SpreadControl
{
/// <summary>
/// SpreadControl の概要の説明です。
///
/// 2004/06/27
/// CurrentCell プロパティ対応
/// HitTest メソッド対応
/// マウスクリックによるセル移動対応
/// 上下キーよるセル移動対応
/// Tab・SHIFT+Tabキーよるセル移動対応
/// </summary>
public class SpreadControl : System.Windows.Forms.UserControl ,ISupportInitialize
{
#region ローカル変数
private bool _init ;
private int _columns ;
private int _initcolumns ;
private int _rows ;
private int _initrows ;
private int _preferredColumnWidth ;
private int _preferredRowHeight ;
private int _currentColumnIndex ;
private int _currentRowIndex ;
private bool _rowHeadersVisible ;
private bool _columnHeadersVisible ;
private int _rowHeaderWidth ;
private int _columnHeaderHeight ;
private Size _controlSize ;
private object[,] _data ;
private object[,] _initdata ;
private SpreadColumn[] _column ;
private SpreadColumn[] _initcolumn ;
private SpreadRow[] _row ;
private SpreadRow[] _initrow ;
#endregion
#region コンポーネント デザイナで生成された変数
/// <summary>
/// 必要なデザイナ変数です。
/// </summary>
private System.ComponentModel.Container components = null;
#endregion
#region クラスの生成・消滅
public SpreadControl()
{
// この呼び出しは、Windows.Forms フォーム デザイナで必要です。
InitializeComponent();
// TODO: InitComponent 呼び出しの後に初期化処理を追加してください。
_columns = 3 ;
_rows = 2 ;
_preferredColumnWidth = 75 ;
_preferredRowHeight = 15 ;
_currentColumnIndex = 0 ;
_currentRowIndex = 0 ;
_rowHeadersVisible = true ;
_columnHeadersVisible = true ;
_rowHeaderWidth = 75 ;
_columnHeaderHeight = 15 ;
_column = new SpreadColumn[_columns] ;
for ( int j=0 ; j<_columns ; j++ )
{
_column[j] = new SpreadColumn() ;
_column[j].PropertyChange +=new EventHandler(SpreadControl_PropertyChange);
bool notincontrols = true ;
foreach ( Control control in Controls )
{
if ( control.Name == _column[j].Control.Name )
{
notincontrols = false ;
break ;
}
}
if ( notincontrols )
{
Controls.Add( _column[j].Control ) ;
}
}
_row = new SpreadRow[_rows] ;
for ( int i=0 ; i<_rows ; i++ )
{
_row[i] = new SpreadRow() ;
_row[i].PropertyChange +=new EventHandler(SpreadControl_PropertyChange);
}
_data = new object[_rows,_columns] ;
for( int i=0 ; i<_rows ; i++ )
{
for ( int j=0 ; j<_columns ; j++ )
{
_data[i,j] = _column[j].SpreadControlParts.InitialValue() ;
}
}
_initcolumns = _columns ;
_initrows = _rows ;
_controlSize = new Size(
_rowHeaderWidth + _preferredColumnWidth * _columns + 1,
_columnHeaderHeight + _preferredRowHeight * _rows + 1 ) ;
}
/// <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)
{
ResizeDisplay() ;
}
#endregion
#region コンポーネント デザイナで生成されたコード
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード]エディタで変更しないでください。
/// </summary>
private void InitializeComponent()
{
//
// SpreadControl
//
this.Name = "SpreadControl";
this.Load += new System.EventHandler(this.SpreadControl_Load);
this.Enter += new System.EventHandler(this.SpreadControl_Enter);
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);
}
#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()
{
_controlSize = new Size( _preferredColumnWidth * _columns + 1,
_preferredRowHeight * _rows + 1 ) ;
if ( _rowHeadersVisible ) _controlSize.Width += _rowHeaderWidth ;
if ( _columnHeadersVisible ) _controlSize.Height += _columnHeaderHeight ;
if ( this.Width < _controlSize.Width || this.Height < _controlSize.Height )
{
AutoScrollMinSize = _controlSize ;
}
Refresh() ;
}
private void ResizeData()
{
//MessageBox.Show(string.Format("ResizeData from data[{0},{1}]",_data.GetLength(0),_data.GetLength(1))) ;
SpreadColumn[] newcolumn = new SpreadColumn[_columns] ;
for ( int j=0 ; j<_columns ; j++ )
{
if ( j >= _column.GetLength(0) )
{
newcolumn[j] = new SpreadColumn() ;
newcolumn[j].PropertyChange +=new EventHandler(SpreadControl_PropertyChange);
}
else
{
newcolumn[j] = _column[j] ;
}
bool notincontrols = true ;
foreach ( Control control in Controls )
{
if ( control.Name == newcolumn[j].Control.Name )
{
notincontrols = false ;
break ;
}
}
if ( notincontrols )
{
Controls.Add( newcolumn[j].Control ) ;
}
}
_column = newcolumn ;
SpreadRow[] newrow = new SpreadRow[_rows] ;
for ( int j=0 ; j<_rows ; j++ )
{
if ( j >= _row.GetLength(0) )
{
newrow[j] = new SpreadRow() ;
newrow[j].PropertyChange +=new EventHandler(SpreadControl_PropertyChange);
}
else
{
newrow[j] = _row[j] ;
}
}
_row = newrow ;
object[,] newdata = new object[_rows,_columns] ;
for( int i=0 ; i<_rows ; i++ )
{
for ( int j=0 ; j<_columns ; j++ )
{
if ( i >= _data.GetLength(0) || j >= _data.GetLength(1) )
{
newdata[i,j] = _column[j].SpreadControlParts.InitialValue() ;
}
else
{
newdata[i,j] = _data[i,j] ;
}
}
}
_data = newdata ;
//MessageBox.Show(string.Format("ResizeData to data[{0},{1}]",newdata.GetLength(0),newdata.GetLength(1))) ;
}
private void EnterControl()
{
int px, sx, py, sy ;
py = AutoScrollPosition.Y + _currentRowIndex * _preferredRowHeight ;
if ( _columnHeadersVisible ) py += _columnHeaderHeight ;
sy = _preferredRowHeight ;
px = AutoScrollPosition.X + _currentColumnIndex * _preferredColumnWidth ;
if ( _rowHeadersVisible ) px += _rowHeaderWidth ;
sx = _preferredColumnWidth ;
Rectangle rect = new Rectangle( px - AutoScrollPosition.X, py - AutoScrollPosition.Y, sx, sy ) ;
if ( !IncludeClient( rect ) )
{
AutoScrollPosition = new Point(rect.Right + 1 - ClientRectangle.Right,
rect.Bottom + 1 - ClientRectangle.Bottom ) ;
}
_column[_currentColumnIndex].EnterControl(
new Point( px + 1, py + 1 ),
new Size( sx - 1, sy - 1),
_data[_currentRowIndex,_currentColumnIndex]) ;
}
private void LeaveControl()
{
_data[_currentRowIndex,_currentColumnIndex] = _column[_currentColumnIndex].LeaveControl() ;
}
private void MoveTo( int column, int row )
{
LeaveControl() ;
_currentColumnIndex = column ;
_currentRowIndex = row ;
EnterControl() ;
}
private void MoveTo( SpreadCell cell )
{
MoveTo( cell.ColumnNumber, cell.RowNumber ) ;
}
private void MoveUp()
{
LeaveControl() ;
_currentRowIndex -- ;
if ( _currentRowIndex < 0 )
{
_currentRowIndex = 0 ;
}
EnterControl() ;
}
private void MoveDown()
{
LeaveControl() ;
_currentRowIndex ++ ;
if ( _currentRowIndex >= _rows )
{
_currentRowIndex = _rows - 1 ;
}
EnterControl() ;
}
private void MoveLeft()
{
LeaveControl() ;
_currentColumnIndex -- ;
if ( _currentColumnIndex < 0 )
{
_currentColumnIndex = _columns - 1 ;
_currentRowIndex -- ;
}
if ( _currentRowIndex < 0 )
{
_currentColumnIndex = 0 ;
_currentRowIndex = 0 ;
Control control = Parent.GetNextControl(this,false) ;
if ( control != null )
{
control.Focus() ;
}
else
{
control = Parent.GetNextControl(control,false) ;
control.Focus() ;
}
}
else
{
EnterControl() ;
}
}
private void MoveRight()
{
LeaveControl() ;
_currentColumnIndex ++ ;
if ( _currentColumnIndex >= _columns )
{
_currentColumnIndex = 0 ;
_currentRowIndex ++ ;
}
if ( _currentRowIndex >= _rows )
{
_currentColumnIndex = _columns - 1 ;
_currentRowIndex = _rows - 1 ;
Control control = Parent.GetNextControl(this,true) ;
if ( control != null )
{
control.Focus() ;
}
else
{
control = Parent.GetNextControl(control,true) ;
control.Focus() ;
}
}
else
{
EnterControl() ;
}
}
#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)]
[DefaultValue(2)]
public int Rows
{
get
{
return _rows ;
}
set
{
if ( _init == false )
{
_rows = value ;
try
{
_init = true ;
ResizeData() ;
}
finally
{
_init = false ;
}
ResizeDisplay() ;
}
else
{
_initrows = value ;
}
}
}
[Description("列数を示します。"),Category("配置")]
[RefreshProperties(RefreshProperties.All)]
[DefaultValue(3)]
public int Columns
{
get
{
return _columns ;
}
set
{
//MessageBox.Show(string.Format("Columns DesignMode={0},init={1}",DesignMode,_init)) ;
if ( _init == false )
{
_columns = value ;
try
{
_init = true ;
ResizeData() ;
}
finally
{
_init = false ;
}
ResizeDisplay() ;
}
else
{
_initcolumns = value ;
}
}
}
[Description("列属性の配列を示します。"),Category("配置")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public SpreadColumn[] Column
{
get
{
return _column ;
}
set
{
if ( _init == false )
{
_column = value ;
ResizeDisplay() ;
}
else
{
_initcolumn = value ;
}
}
}
[Description("行属性の配列を示します。"),Category("配置")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public SpreadRow[] Row
{
get
{
return _row ;
}
set
{
if ( _init == false )
{
_row = value ;
ResizeDisplay() ;
}
else
{
_initrow = value ;
}
}
}
[Description("行の適切な高さを示します。"),Category("配置")]
[RefreshProperties(RefreshProperties.Repaint)]
[DefaultValue(15)]
public int PreferredRowHeight
{
get
{
return _preferredRowHeight ;
}
set
{
_preferredRowHeight = value ;
if ( _init == false )
{
ResizeDisplay() ;
}
}
}
[Description("列の適切な幅を示します。"),Category("配置")]
[RefreshProperties(RefreshProperties.Repaint)]
[DefaultValue(75)]
public int PreferredColumnWidth
{
get
{
return _preferredColumnWidth ;
}
set
{
_preferredColumnWidth = value ;
if ( _init == false )
{
ResizeDisplay() ;
}
}
}
[Description("列ヘッダーの幅を示します。"),Category("配置")]
[DefaultValue(15)]
public int ColumnHeaderHeight
{
get
{
return _columnHeaderHeight ;
}
set
{
_columnHeaderHeight = value ;
if ( _init == false )
{
ResizeDisplay() ;
}
}
}
[Description("行ヘッダーの幅を示します。"),Category("配置")]
[DefaultValue(75)]
public int RowHeaderWidth
{
get
{
return _rowHeaderWidth ;
}
set
{
_rowHeaderWidth = value ;
if ( _init == false )
{
ResizeDisplay() ;
}
}
}
[Description("列ヘッダーが表示されているかを示します。"),Category("表示")]
[DefaultValue(true)]
public bool RowHeadersVisible
{
get
{
return _rowHeadersVisible ;
}
set
{
_rowHeadersVisible = value ;
if ( _init == false )
{
ResizeDisplay() ;
}
}
}
[Description("行ヘッダーが表示されているかを示します。"),Category("表示")]
[DefaultValue(true)]
public bool ColumnHeadersVisible
{
get
{
return _columnHeadersVisible ;
}
set
{
_columnHeadersVisible = value ;
if ( _init == false )
{
ResizeDisplay() ;
}
}
}
public object this [int rowindex,int columnindex]
{
get
{
if ( rowindex >= 0 && rowindex < _rows &&
columnindex >= 0 && columnindex < _columns )
{
return _data[rowindex,columnindex] ;
}
return null ;
}
set
{
if ( rowindex >= 0 && rowindex < _rows &&
columnindex >= 0 && columnindex < _columns )
{
_data[rowindex,columnindex] = value ;
}
}
}
#endregion
#region 公開メソッド
public HitTestInfo HitTest( int x, int y )
{
HitTestInfo hittestinfo = new HitTestInfo() ;
x -= AutoScrollPosition.X ;
if ( _rowHeadersVisible ) x -= _rowHeaderWidth ;
y -= AutoScrollPosition.Y ;
if ( _columnHeadersVisible ) y -= _columnHeaderHeight ;
if ( x < 0 || y < 0 )
{
return hittestinfo ;
}
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 ;
//MessageBox.Show(string.Format("BeginInit DesignMode={0},init={1}",DesignMode,init)) ;
}
public void EndInit()
{
try
{
if ( _initdata != null )
{
_data = _initdata ;
_initdata = null ;
}
if ( _initcolumn != null )
{
_column = _initcolumn ;
_initcolumn = null ;
}
if ( _initrow != null )
{
_row = _initrow ;
_initrow = null ;
}
_columns = _initcolumns ;
_rows = _initrows ;
//MessageBox.Show(string.Format("EndInit DesignMode={0},init={1}",DesignMode,_init)) ;
ResizeData() ;
//MessageBox.Show(string.Format("EndInit2 DesignMode={0},init={1}",DesignMode,_init)) ;
}
finally
{
_init = false ;
}
ResizeDisplay() ;
}
#endregion
#region イベント処理
private void SpreadControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
int px, sx, py, sy ;
if ( _init == false )
{
//MessageBox.Show(string.Format("Paint to data[{0},{1}]",rows,columns)) ;
if ( _columnHeadersVisible )
{
py = AutoScrollPosition.Y ;
sy = _columnHeaderHeight ;
for ( int j=0 ; j<_columns ; j++ )
{
Pen penHeader = new Pen(_column[j].HeaderForeColor,1) ;
Brush brushHeader = new SolidBrush(_column[j].HeaderForeColor) ;
Brush brushBackHeader = new SolidBrush(_column[j].HeaderBackColor) ;
px = AutoScrollPosition.X + j * _preferredColumnWidth ;
if ( _rowHeadersVisible ) px += _rowHeaderWidth ;
sx = _preferredColumnWidth ;
Rectangle rect = new Rectangle( px, py, sx, sy ) ;
e.Graphics.FillRectangle( brushBackHeader, rect ) ;
e.Graphics.DrawRectangle( penHeader, rect ) ;
e.Graphics.DrawString( _column[j].HeaderText, _column[j].HeaderFont, brushHeader, rect ) ;
}
}
if ( _rowHeadersVisible )
{
px = AutoScrollPosition.X ;
sx = _rowHeaderWidth ;
for ( int i=0 ; i<_rows ; i++ )
{
Pen penHeader = new Pen(_row[i].HeaderForeColor,1) ;
Brush brushHeader = new SolidBrush(_row[i].HeaderForeColor) ;
Brush brushBackHeader = new SolidBrush(_row[i].HeaderBackColor) ;
py = AutoScrollPosition.Y + i * _preferredRowHeight ;
if ( _columnHeadersVisible ) py += _columnHeaderHeight ;
sy = _preferredRowHeight ;
Rectangle rect = new Rectangle( px, py, sx, sy ) ;
e.Graphics.FillRectangle( brushBackHeader, rect ) ;
e.Graphics.DrawRectangle( penHeader, rect ) ;
e.Graphics.DrawString( _row[i].HeaderText, _row[i].HeaderFont, brushHeader, rect ) ;
}
}
for ( int i=0 ; i<_rows ; i++ )
{
py = AutoScrollPosition.Y + i * _preferredRowHeight ;
if ( _columnHeadersVisible ) py += _columnHeaderHeight ;
sy = _preferredRowHeight ;
for ( int j=0 ; j<_columns ; j++ )
{
Pen pen = new Pen(_column[j].ForeColor,1) ;
Brush brush = new SolidBrush(_column[j].ForeColor) ;
Brush brushBack = new SolidBrush(_column[j].BackColor) ;
px = AutoScrollPosition.X + j * _preferredColumnWidth ;
if ( _rowHeadersVisible ) px += _rowHeaderWidth ;
sx = _preferredColumnWidth ;
Rectangle rect = new Rectangle( px, py, sx, sy ) ;
e.Graphics.FillRectangle( brushBack, rect ) ;
e.Graphics.DrawRectangle( pen, rect ) ;
e.Graphics.DrawString( _data[i,j].ToString(), Font, brush, rect ) ;
}
}
}
}
private void SpreadControl_Enter(object sender, System.EventArgs e)
{
EnterControl() ;
}
private void SpreadControl_Leave(object sender, System.EventArgs e)
{
LeaveControl() ;
Refresh() ;
}
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 SpreadControl_PropertyChange(object sender, EventArgs e)
{
ResizeDisplay() ;
}
#endregion
}
}



