| SpreadControl | ユーザーコントロールに線と文字を表示してテキストボックス1つで入力し、 2次元インデクサでアクセスできるようにした例です。 CurrentCell プロパティ対応 HitTest メソッド対応 マウスクリックによるセル移動対応 上下キーよるセル移動対応 Tab・SHIFT+Tabキーよるセル移動対応 |
| SpreadTest | 変更なし |
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
{
#region ローカル変数
private int columns ;
private int rows ;
private int preferredColumnWidth ;
private int preferredRowHeight ;
private int currentColumnIndex ;
private int currentRowIndex ;
private string[,] text ;
#endregion
#region コンポーネント デザイナで生成された変数
private System.Windows.Forms.TextBox textBox1;
/// <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 ;
text = new string[rows,columns] ;
}
/// <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()
{
string[,] newtext = new string[rows,columns] ;
for ( int i=0 ; i<text.GetLength(0) ; i++ )
{
if ( i >= rows )
{
break ;
}
for ( int j=0 ; j<text.GetLength(1) ; j++ )
{
if ( j >= columns )
{
break ;
}
newtext[i,j] = text[i,j] ;
}
}
text = newtext ;
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 = text[currentRowIndex,currentColumnIndex] ;
textBox1.Focus() ;
}
private void LeaveTextBox()
{
text[currentRowIndex,currentColumnIndex] = textBox1.Text ;
textBox1.Visible = false ;
}
private void MoveTo( int column, int row )
{
LeaveTextBox() ;
currentColumnIndex = column ;
currentRowIndex = row ;
EnterTextBox() ;
}
private void MoveTo( Cell 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)]
public Cell CurrentCell
{
get
{
Cell cell = new Cell( 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 ;
ResizeData() ;
}
}
[Description("列数を示します。"),Category("配置")]
[RefreshProperties(RefreshProperties.All)]
public int Columns
{
get
{
return columns ;
}
set
{
columns = value ;
ResizeData() ;
}
}
[Description("行の適切な高さを示します。"),Category("配置")]
[RefreshProperties(RefreshProperties.All)]
public int PreferredRowHeight
{
get
{
return preferredRowHeight ;
}
set
{
preferredRowHeight = value ;
ResizeDisplay() ;
}
}
[Description("列の適切な幅を示します。"),Category("配置")]
[RefreshProperties(RefreshProperties.All)]
public int PreferredColumnWidth
{
get
{
return preferredColumnWidth ;
}
set
{
preferredColumnWidth = value ;
ResizeDisplay() ;
}
}
public string this [int rowindex,int columnindex]
{
get
{
if ( rowindex >= 0 && rowindex < rows &&
columnindex >= 0 && columnindex < columns )
{
return text[rowindex,columnindex] ;
}
return "" ;
}
set
{
if ( rowindex >= 0 && rowindex < rows &&
columnindex >= 0 && columnindex < columns )
{
text[rowindex,columnindex] = 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 ) ;
}
#endregion
#region イベント処理
private void SpreadControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
int px, sx, py, sy ;
Pen pen = new Pen(ForeColor,1) ;
Brush brush = new SolidBrush(ForeColor) ;
for ( int i=0 ; i<rows ; i++ )
{
py = AutoScrollPosition.Y + i * preferredRowHeight ;
sy = preferredRowHeight ;
for ( int j=0 ; j<columns ; j++ )
{
px = AutoScrollPosition.X + j * preferredColumnWidth ;
sx = preferredColumnWidth ;
Rectangle rect = new Rectangle( px, py, sx, sy ) ;
e.Graphics.DrawRectangle( pen, rect ) ;
e.Graphics.DrawString( text[i,j], Font, brush, 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)
{
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) ;
}
#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(CellConverter))]
public class Cell
{
private int _columnNumber ;
private int _rowNumber ;
public Cell()
{
_columnNumber = -1 ;
_rowNumber = -1 ;
}
public Cell(int column, int row)
{
_columnNumber = column ;
_rowNumber = row ;
}
public int ColumnNumber { get { return _columnNumber ; } }
public int RowNumber { get { return _rowNumber ; } }
}
internal class CellConverter : 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 Cell)
{
Cell ic = (Cell)value;
return ic.ColumnNumber.ToString() + "," + ic.RowNumber.ToString() ;
}
return base.ConvertTo(context, culture, value, destType);
}
}
#endregion
}