プログラムです。
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 に対応する
/// 2004/07/15
/// BlockRange プロパティ作成
/// 描画・入力・HitTest メソッド・セル移動をブロック対応
/// 2004/07/20 バグ修正
/// デザインモードでCulumns/Rowsを変更したときにグリッドが対応しない。
/// デザインモードでCulumns/Rowsを変更後グリッドにエラーが表示される。
/// フォント変更時にPreferredRowHeightが追従しない。
/// </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 Cell[] inititem ;
private CellRangeCollection rangecollection ;
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 ;
inititem = null ;
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);
}
rangecollection = new CellRangeCollection() ;
rangecollection.PropertyChange += new System.EventHandler(this.CellRange_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.AutoSize = false;
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() ;
}
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] ;
}
}
for ( int i=0 ; i<rows * columns ; i++ )
{
newitem[i].PropertyChange += new System.EventHandler(this.Cell_PropertyChange);
}
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 ) ;
CellRange blockrange = SearchBlock( currentColumnIndex, currentRowIndex ) ;
textBox1.Multiline = false ;
if ( blockrange == null )
{
textBox1.Size = new Size(preferredColumnWidth - 1, preferredRowHeight - 1) ;
}
else
{
textBox1.Size = new Size(preferredColumnWidth * (blockrange.Right - blockrange.Left + 1) - 1,
preferredRowHeight * (blockrange.Bottom - blockrange.Top + 1) - 1) ;
if ( blockrange.Bottom - blockrange.Top != 0)
{
textBox1.Multiline = true ;
}
}
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 CellRange SearchBlock( int column, int row )
{
CellRange blockrange = null ;
foreach ( CellRange range in rangecollection )
{
if ( range.Contains( column, row ) )
{
blockrange = range ;
}
}
return blockrange ;
}
private void MoveIndex( int column, int row )
{
CellRange blockrange = SearchBlock( column, row ) ;
if ( blockrange != null )
{
column = blockrange.Left ;
row = blockrange.Top ;
}
currentColumnIndex = column ;
currentRowIndex = row ;
}
private void MoveTo( int column, int row )
{
LeaveTextBox() ;
MoveIndex( column, row ) ;
EnterTextBox() ;
}
private void MoveTo( SpreadCell cell )
{
MoveTo( cell.ColumnNumber, cell.RowNumber ) ;
}
private void MoveUp()
{
LeaveTextBox() ;
int row, column ;
row = currentRowIndex ;
column = currentColumnIndex ;
row -- ;
if ( row < 0 )
{
row = 0 ;
}
MoveIndex( column, row ) ;
EnterTextBox() ;
}
private void MoveDown()
{
LeaveTextBox() ;
int row, column ;
row = currentRowIndex ;
column = currentColumnIndex ;
do
{
row ++ ;
if ( row >= rows )
{
row = rows - 1 ;
MoveIndex( column, row ) ;
break ;
}
MoveIndex( column, row ) ;
} while ( currentRowIndex != row ) ;
EnterTextBox() ;
}
private void MoveLeft()
{
LeaveTextBox() ;
int row, column ;
row = currentRowIndex ;
column = currentColumnIndex ;
do
{
column -- ;
if ( column < 0 )
{
column = columns - 1 ;
row -- ;
}
if ( row < 0 )
{
column = 0 ;
row = 0 ;
MoveIndex( column, row ) ;
break ;
}
MoveIndex( column, row ) ;
} while ( currentRowIndex != row && currentColumnIndex != column ) ;
EnterTextBox() ;
}
private void MoveRight()
{
LeaveTextBox() ;
int row, column ;
int oldrow, oldcolumn ;
row = currentRowIndex ;
column = currentColumnIndex ;
oldrow = currentRowIndex ;
oldcolumn = currentColumnIndex ;
do
{
column ++ ;
if ( column >= columns )
{
column = 0 ;
row ++ ;
}
if ( row >= rows )
{
column = columns - 1 ;
row = rows - 1 ;
MoveIndex( column, row ) ;
break ;
}
MoveIndex( column, row ) ;
} while ( currentRowIndex == oldrow && currentColumnIndex == oldcolumn ) ;
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() ;
}
else
{
oldrows = rows ;
}
}
}
[Description("列数を示します。"),Category("配置")]
[RefreshProperties(RefreshProperties.All)]
public int Columns
{
get
{
return columns ;
}
set
{
columns = value ;
if ( DesignMode == true || init == false )
{
ResizeData() ;
}
else
{
oldcolumns = columns ;
}
}
}
[Description("行の適切な高さを示します。"),Category("配置")]
[RefreshProperties(RefreshProperties.Repaint)]
public int PreferredRowHeight
{
get
{
return preferredRowHeight ;
}
set
{
preferredRowHeight = value ;
if ( init == false )
{
ResizeDisplay() ;
}
}
}
[Description("列の適切な幅を示します。"),Category("配置")]
[RefreshProperties(RefreshProperties.Repaint)]
public int PreferredColumnWidth
{
get
{
return preferredColumnWidth ;
}
set
{
preferredColumnWidth = value ;
if ( 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
{
if ( init == false )
{
item = value ;
}
else
{
inititem = value ;
}
}
}
[Description("セルブロックのコレクションです。"),Category("設定")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public CellRangeCollection BlockRange
{
get
{
return rangecollection ;
}
set
{
rangecollection = 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 ;
}
CellRange blockrange = SearchBlock( px, py ) ;
if ( blockrange != null )
{
px = blockrange.Left ;
py = blockrange.Top ;
}
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()
{
oldcolumns = columns ;
oldrows = rows ;
init = false ;
if ( inititem != null )
{
item = inititem ;
inititem = null ;
}
ResizeData() ;
}
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 PaintOneBlock( Graphics g, Rectangle rect, Cell cell )
{
Pen pen = new Pen(cell.ForeColor,1) ;
Brush brush = new SolidBrush(cell.ForeColor) ;
Brush brushback = new SolidBrush(cell.BackColor) ;
g.FillRectangle( brushback, rect ) ;
Rectangle rectcell = new Rectangle( rect.X - 1, rect.Y - 1, rect.Width + 1, rect.Height + 1 ) ;
Rectangle recttext = new Rectangle( rect.X - 2, rect.Y, rect.Width + 1, rect.Height + 1 ) ;
g.DrawString( cell.Text, cell.Font, brush, recttext ) ;
g.DrawRectangle( pen, rectcell ) ;
}
private void SpreadControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
int px, sx, py, sy ;
Rectangle rect ;
if ( DesignMode == true || init == false )
{
for ( int i=0 ; i<rows ; i++ )
{
for ( int j=0 ; j<columns ; j++ )
{
CellRange blockrange = SearchBlock( j, i ) ;
if ( blockrange == null )
{
py = AutoScrollPosition.Y + i * preferredRowHeight + 1 ;
sy = preferredRowHeight - 1 ;
px = AutoScrollPosition.X + j * preferredColumnWidth + 1 ;
sx = preferredColumnWidth - 1 ;
rect = new Rectangle( px, py, sx, sy ) ;
PaintOneBlock( e.Graphics, rect, this[i,j] ) ;
}
else if ( blockrange.Top == i && blockrange.Left == j )
{
if ( blockrange.Right >= columns )
{
blockrange.Right = columns - 1 ;
}
if ( blockrange.Bottom >= rows )
{
blockrange.Bottom = rows - 1 ;
}
py = AutoScrollPosition.Y + i * preferredRowHeight + 1 ;
sy = preferredRowHeight * (blockrange.Bottom - i + 1) - 1 ;
px = AutoScrollPosition.X + j * preferredColumnWidth + 1 ;
sx = preferredColumnWidth * (blockrange.Right - j + 1) - 1 ;
rect = new Rectangle( px, py, sx, sy ) ;
PaintOneBlock( e.Graphics, rect, this[i,j] ) ;
}
}
}
}
}
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)
{
textBox1.AutoSize = false ;
textBox1.Font = Font ;
preferredRowHeight = textBox1.PreferredHeight ;
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() ;
}
private void CellRange_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
#region セル範囲クラス
[Serializable]
[TypeConverter(typeof(CellRangeConverter))]
public class CellRange
{
private int _left ;
private int _top ;
private int _right ;
private int _bottom ;
public CellRange()
{
_left = 0 ;
_top = 0 ;
_right = 0 ;
_bottom = 0 ;
}
public CellRange(int left, int top, int right, int bottom)
{
_left = left ;
_top = top ;
_right = right ;
_bottom = bottom ;
RaisePropertyChange() ;
}
[Description("セル範囲の左端のカラム位置です。"),Category("表示")]
[RefreshProperties(RefreshProperties.Repaint)]
public int Left
{
get
{
return _left ;
}
set
{
if ( value >= 0 )
{
_left = value ;
RaisePropertyChange() ;
}
}
}
[Description("セル範囲の上端の行位置です。"),Category("表示")]
[RefreshProperties(RefreshProperties.Repaint)]
public int Top
{
get
{
return _top ;
}
set
{
if ( value >= 0 )
{
_top = value ;
if ( _top > _bottom )
{
_top = _bottom ;
_bottom = value ;
}
RaisePropertyChange() ;
}
}
}
[Description("セル範囲の右端のカラム位置です。"),Category("表示")]
[RefreshProperties(RefreshProperties.Repaint)]
public int Right
{
get
{
return _right ;
}
set
{
_right = value ;
if ( _left > _right )
{
_right = _left ;
_left = value ;
}
RaisePropertyChange() ;
}
}
[Description("セル範囲の下端の行位置です。"),Category("表示")]
[RefreshProperties(RefreshProperties.Repaint)]
public int Bottom
{
get
{
return _bottom ;
}
set
{
_bottom = value ;
if ( _top > _bottom )
{
_bottom = _top ;
_top = value ;
}
RaisePropertyChange() ;
}
}
public bool Contains( int x, int y )
{
if ( x >= _left && x <= _right && y >= _top && y <= _bottom )
{
return true ;
}
return false ;
}
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 CellRangeConverter : 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 CellRange)
{
CellRange ic = (CellRange)value;
return ic.Left.ToString() + "," + ic.Top.ToString() + "-" +
ic.Right.ToString() + "," + ic.Bottom.ToString() ;
}
if (destType == typeof(InstanceDescriptor) && value is CellRange)
{
CellRange ic = (CellRange)value;
System.Reflection.ConstructorInfo ctor = typeof(CellRange).GetConstructor(new Type[] {
typeof(int), typeof(int), typeof(int), typeof(int) } ) ;
if (ctor != null)
{
return new InstanceDescriptor(ctor, new object[] {ic.Left, ic.Top, ic.Right, ic.Bottom}) ;
}
}
return base.ConvertTo(context, culture, value, destType);
}
}
[Serializable()]
public class CellRangeCollection : CollectionBase
{
private void Adjust( ref CellRange range )
{
int swap ;
if ( range.Left > range.Right )
{
swap = range.Left ;
range.Left = range.Right ;
range.Right = swap ;
}
if ( range.Top > range.Bottom )
{
swap = range.Top ;
range.Top = range.Bottom ;
range.Bottom = swap ;
}
}
public CellRange this[ int index ]
{
get
{
return( (CellRange) List[index] );
}
set
{
CellRange range = value ;
Adjust( ref value ) ;
List[index] = value;
range.PropertyChange += new System.EventHandler(this.CellRange_PropertyChange);
RaisePropertyChange() ;
}
}
public int Add( CellRange value )
{
CellRange range = value ;
Adjust( ref value ) ;
int pos = List.Add( value ) ;
range.PropertyChange += new System.EventHandler(this.CellRange_PropertyChange);
RaisePropertyChange() ;
return pos ;
}
public int IndexOf( CellRange value )
{
Adjust( ref value ) ;
return( List.IndexOf( value ) );
}
public void Insert( int index, CellRange value )
{
Adjust( ref value ) ;
CellRange range = value ;
List.Insert( index, value );
range.PropertyChange += new System.EventHandler(this.CellRange_PropertyChange);
RaisePropertyChange() ;
}
public void Remove( CellRange value )
{
Adjust( ref value ) ;
List.Remove( value );
RaisePropertyChange() ;
}
public bool Contains( CellRange value )
{
Adjust( ref value ) ;
return( List.Contains( value ) );
}
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 ) ;
}
private void CellRange_PropertyChange(object sender, System.EventArgs e)
{
RaisePropertyChange() ;
}
}
#endregion
}



