えムナウのプログラミングのページ

えムナウ の とどけもの

 Logo えムナウBlog@AILight
えムナウBlog@Wankuma

目次

利用状況

イメージ ギャラリー

カテゴリ

Links
 

inetaj

MSMVPロゴ
MSMVP Visual C# 2005/01-2007/12
SpreadControl.cs スプレッドシートコントロール本体です。

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
        }
}