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

えムナウ の とどけもの

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

目次

利用状況

イメージ ギャラリー

カテゴリ

Links
 

inetaj

MSMVPロゴ
MSMVP Visual C# 2005/01-2007/12

目次

スプレッドシート

サンプル3 そろそろ使えそうなスプレッドシート

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
}