using System; using System.ComponentModel; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Windows.Forms; using System.Drawing; using System.Runtime.InteropServices; using Volian.Controls.Library; using C1.Win.C1FlexGrid; namespace Volian.Controls.Library { public partial class VlnFlexGrid : C1.Win.C1FlexGrid.C1FlexGrid { private TableCellEditor _tableCellEditor; private TableClipBoardFuncts _clpbrdCpyPste; #region Grid Initialize public VlnFlexGrid() { InitializeComponent(); SetupGrid(4, 3); // use a default row and column count } public VlnFlexGrid(int rows, int cols) { InitializeComponent(); SetupGrid(rows, cols); } public VlnFlexGrid(IContainer container) { container.Add(this); InitializeComponent(); _tableCellEditor = new TableCellEditor(this); } private void SetupGrid(int numrows, int numcols) //C1FlexGrid NewGrid() { // setup the default size of each cell in the table/grid this.Cols.DefaultSize = 40; this.Rows.DefaultSize = 20; // setup the number of rows and columns this.Rows.Count = numrows; this.Cols.Count = numcols; // make all the cell editable this.Rows.Fixed = 0; this.Cols.Fixed = 0; this.DrawMode = DrawModeEnum.OwnerDraw; this.ScrollBars = ScrollBars.None; // grid styles this.Styles.EmptyArea.BackColor = Color.Transparent; this.Styles.EmptyArea.Border.Style = BorderStyleEnum.None; this.Styles.Normal.Border.Color = Color.Black; this.Styles.Normal.TextAlign = C1.Win.C1FlexGrid.TextAlignEnum.LeftCenter; SetupCellStyles(); this.FocusRect = FocusRectEnum.Solid; this.Styles.Highlight.BackColor = Color.LightCyan; this.Styles.Highlight.ForeColor = Color.Black; this.Styles.Focus.BackColor = Color.LightCyan; this.HighLight = HighLightEnum.Always; this.AllowMerging = C1.Win.C1FlexGrid.AllowMergingEnum.Custom; this.AllowResizing = C1.Win.C1FlexGrid.AllowResizingEnum.Both; _tableCellEditor = new TableCellEditor(this); _clpbrdCpyPste = new TableClipBoardFuncts(); //this.Enter += new System.EventHandler(this.Grid_Enter); this.AfterResizeRow += new C1.Win.C1FlexGrid.RowColEventHandler(this.Grid_AfterResize); this.StartEdit += new C1.Win.C1FlexGrid.RowColEventHandler(this._StartEdit); this.AfterEdit += new C1.Win.C1FlexGrid.RowColEventHandler(this._AfterEdit); this.AfterScroll += new C1.Win.C1FlexGrid.RangeEventHandler(this._AfterScroll); this.AfterResizeColumn += new C1.Win.C1FlexGrid.RowColEventHandler(this.Grid_AfterResize); this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this._KeyPress); this.OwnerDrawCell += new OwnerDrawCellEventHandler(this.Grid_OwnerDrawCell); } private void Grid_OwnerDrawCell(object sender, C1.Win.C1FlexGrid.OwnerDrawCellEventArgs e) { RTF _rtf = new RTF(); // use nearest solid color // (the RTF control doesn't dither, and doesn't support transparent backgrounds) Color solid = e.Graphics.GetNearestColor(e.Style.BackColor); if (e.Style.BackColor != solid) e.Style.BackColor = solid; // check whether the cell contains RTF string rtfText = this.GetDataDisplay(e.Row, e.Col); if (rtfText.StartsWith(@"{\rtf")) { // it does, so draw background e.DrawCell(DrawCellFlags.Background); // draw the RTF text if (e.Bounds.Width > 0 && e.Bounds.Height > 0) { _rtf.Rtf = rtfText; _rtf.ForeColor = e.Style.ForeColor; _rtf.BackColor = e.Style.BackColor; _rtf.Render(e.Graphics, e.Bounds); } // and draw border last e.DrawCell(DrawCellFlags.Border); // we're done with this cell e.Handled = true; } } #endregion //Grid Initialize #region Grid and Cell Styles public void CellBackgroundYellow() { CellRange cr = this.Selection; cr.Style = this.Styles["Yellow"]; } public void ToggleCellTextAlignment() { CellRange cr = this.Selection; StepRTB srtb = new StepRTB(); srtb.Rtf = this.GetCellRTFString(cr.r1, cr.c1); srtb.SelectAll(); int align = (int)srtb.SelectionAlignment; align = (align + 1) % 3; srtb.SelectionAlignment = (HorizontalAlignment)align; this.PutCellRTFString(cr.r1, cr.c1, srtb.Rtf); } public void TableBorderNone() { this.BorderStyle = C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum.None; this.AdjustGridControlSize(); } public void TableBorderFixedSingle() { this.BorderStyle = C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum.FixedSingle; this.AdjustGridControlSize(); } public void TableBorderFixed3d() { this.BorderStyle = C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum.Fixed3D; this.AdjustGridControlSize(); } public void TableBorderLight3D() { this.BorderStyle = C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum.Light3D; this.AdjustGridControlSize(); } public void TableBorderXpThemes() { this.BorderStyle = C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum.XpThemes; this.AdjustGridControlSize(); } private CellRange GetSelectedCellRange() { return this.GetCellRange(this.Selection.TopRow, this.Selection.LeftCol, this.Selection.BottomRow, this.Selection.RightCol); } public void SelectedCellsBorderNone() { CellRange cr = GetSelectedCellRange(); cr.Style = this.Styles["None"]; } public void SelectedCellsBorderFlat() { CellRange cr = this.GetCellRange(this.Selection.TopRow, this.Selection.LeftCol, this.Selection.BottomRow, this.Selection.RightCol); cr.Style = this.Styles["Flat"]; } public void SelectedCellsBorderDouble() { CellRange cr = this.GetCellRange(this.Selection.TopRow, this.Selection.LeftCol, this.Selection.BottomRow, this.Selection.RightCol); cr.Style = this.Styles["Double"]; } public void SelectedCellsBorderRaised() { CellRange cr = this.GetCellRange(this.Selection.TopRow, this.Selection.LeftCol, this.Selection.BottomRow, this.Selection.RightCol); cr.Style = this.Styles["Raised"]; } public void SelectedCellsBorderInset() { CellRange cr = this.GetCellRange(this.Selection.TopRow, this.Selection.LeftCol, this.Selection.BottomRow, this.Selection.RightCol); cr.Style = this.Styles["Inset"]; } public void SelectedCellsBorderGroove() { CellRange cr = this.GetCellRange(this.Selection.TopRow, this.Selection.LeftCol, this.Selection.BottomRow, this.Selection.RightCol); cr.Style = this.Styles["Groove"]; } public void SelectedCellsBorderFillet() { CellRange cr = this.GetCellRange(this.Selection.TopRow, this.Selection.LeftCol, this.Selection.BottomRow, this.Selection.RightCol); cr.Style = this.Styles["Fillet"]; } public void SelectedCellsBorderDotted() { CellRange cr = this.GetCellRange(this.Selection.TopRow, this.Selection.LeftCol, this.Selection.BottomRow, this.Selection.RightCol); cr.Style = this.Styles["Dotted"]; } public void SetupCellStyles() { CellStyle cs; cs = this.Styles.Add("Dotted"); cs.Border.Style = BorderStyleEnum.Dotted; cs = this.Styles.Add("Double"); cs.Border.Style = BorderStyleEnum.Double; cs = this.Styles.Add("Fillet"); cs.Border.Style = BorderStyleEnum.Fillet; cs = this.Styles.Add("Flat"); cs.Border.Style = BorderStyleEnum.Flat; cs = this.Styles.Add("Groove"); cs.Border.Style = BorderStyleEnum.Groove; cs = this.Styles.Add("Inset"); cs.Border.Style = BorderStyleEnum.Inset; cs = this.Styles.Add("None"); cs.Border.Style = BorderStyleEnum.None; cs = this.Styles.Add("Raised"); cs.Border.Style = BorderStyleEnum.Raised; cs = this.Styles.Add("CenterRight"); cs.TextAlign = TextAlignEnum.RightCenter; //.LeftCenter; // this is being ignored - probably due to RTF conversion cs = this.Styles.Add("Yellow"); cs.BackColor = Color.Yellow; cs = this.Styles.Add("Margins"); cs.Margins.Bottom = 5; cs.Margins.Top = 10; cs.Margins.Left = 15; cs.Margins.Right = 20; } #endregion //Grid and Cell Styles #region Grid Size Adjustments /// /// Adjust the grid control size based on the cell sizes. /// public void AdjustGridControlSize() { int difW = this.Width - this.ClientSize.Width; int difH = this.Height - this.ClientSize.Height; int wid = 0; if (this != null) { foreach (C1.Win.C1FlexGrid.Column col in this.Cols) wid += (col.Width >= 0) ? col.Width : this.Cols.DefaultSize; int height = 0; foreach (C1.Win.C1FlexGrid.Row row in this.Rows) height += (row.Height >= 0) ? row.Height : this.Rows.DefaultSize; this.Size = new Size(wid + difW, height + difH); } this.Refresh(); } public void AdjustGridHeightWidth(int r, int c) { StepRTB trtb = new StepRTB(); string tstr = null; bool dummyCharWidth = false; bool AllowWidthShrink = false; trtb.Clear(); tstr = (string)this[r, c]; trtb.Font = this.Font; if (tstr != null && tstr.Length > 0) { if (tstr.StartsWith(@"{\rtf")) trtb.Rtf = tstr; // already RTF text else trtb.Text = tstr; // this will convert regular text to RTF text // regular text has special characters to toggle Bold, Underline, and Italics // we need to subtract the width of these characters (allow column/row to shrink) AllowWidthShrink = RemoveBoldUlineItalicChars(trtb.Rtf); // this will convert the special characters for Bold, Underline, and Italics // into RTF commands trtb.Rtf = ConvertTableText(trtb.Rtf); } else { trtb.Text = "X"; // this is to trick steprtf in giving a char width to fit one character // note that a space character was too small. dummyCharWidth = true; } // find the needed cell width trtb.AdjustWidthForContent(); if (dummyCharWidth) { trtb.Text = ""; // clear out the dummy character before saving dummyCharWidth = false; } this[r, c] = trtb.Rtf; // save the cleaned up and processed cell text as RTF this.Select(r, c, false); // Now see the the selected row,col is in the defined merge ranges bool mrgrows = false; bool mrgcols = false; foreach (CellRange cr in this.MergedRanges) { if (cr.Contains(r, c)) { if (cr.c1 != cr.c2) mrgcols = true; // in a range of merged columns if (cr.r1 != cr.r2) mrgrows = true; // in a range of merged rows continue; } } if (!mrgcols || !mrgrows) { // IF the row of the selected cell is NOT in merged range // then go ahead and adjust the row height (if needed) if (!mrgrows) { // add adjustment for grid and cell borders int newheight = trtb.Height + 2;// (int)numGridLineBorderAdj.Value; //Console.WriteLine("{0} {1} {2} '{3}'", r, c, newheight,trtb.Text); if (newheight > this.Rows[r].Height) this.Rows[r].Height = newheight; } // IF the column of the selected sell is NOT in merged range // then go ahead and adjust the column width (if needed) if (!mrgcols) { // add adjustment for grid and cell borders int newwidth = trtb.Width + 2;//(int)numGridLineBorderAdj.Value; if (newwidth > this.Cols[c].Width || AllowWidthShrink || r == 0) this.Cols[c].Width = newwidth; } } } private void Grid_AfterResize(object sender, C1.Win.C1FlexGrid.RowColEventArgs e) { this.AdjustGridControlSize(); } #endregion // Grid Size Adjustments #region Cell Text public void MakeRTFcells() { // This will spin through all the cells in the grid: // - convert the text to RTF if needed // - adjust the grid dimensions based on the cell info. for (int r = 0; r < this.Rows.Count; r++) { this.Rows[r].Height = 20;//10; for (int c = 0; c < this.Cols.Count; c++) this.AdjustGridHeightWidth(r, c); } this.AdjustGridControlSize(); } private bool RemoveBoldUlineItalicChars(string str) { int rtn = 0; // Underline next word rtn += str.IndexOf(@"\'17"); // Bold next word rtn += str.IndexOf(@"\'13"); // Italics On rtn += str.IndexOf(@"\'1B4"); // Italics Off rtn += str.IndexOf(@"\'1B5"); // underline On rtn += str.IndexOf(@"\'ab"); // underline Off rtn += str.IndexOf(@"\'bb"); return rtn > 0; } private string ConvertTableText(string str) { string rtn = ""; // Underline next word rtn = SomethingNextWord(str, @"\'17", @"\ul ", @"\ulnone "); // Bold next word rtn = SomethingNextWord(rtn, @"\'13", @"\b ", @"\b0 "); // Italics On rtn = rtn.Replace(@"\'1B4", @"\i "); // Italics Off rtn = rtn.Replace(@"\'1B5", @"\i0 "); // underline On rtn = rtn.Replace(@"\'ab", @"\ul "); // underline Off rtn = rtn.Replace(@"\'bb", @"\ulnone "); return rtn; } // This converts Underline or bold next word character to the corresponding on/off commands private static string SomethingNextWord(string str, string nxtwordcmd, string cmdOn, string cmdOff) { string rtn = ""; int bidx = 0; int fidx = str.IndexOf(nxtwordcmd, bidx); char[] term = " \r\n\x02".ToCharArray(); while (fidx > 0) { rtn += str.Substring(bidx, fidx - bidx) + cmdOn; bidx = fidx + 4; if (bidx < str.Length) { fidx = str.IndexOfAny(term, bidx); if (fidx > 0) { rtn += str.Substring(bidx, fidx - bidx) + cmdOff + str.Substring(fidx, 1); bidx = fidx + 1; } } if (bidx < str.Length) fidx = str.IndexOf(nxtwordcmd, bidx); else fidx = -1; } if (bidx < str.Length) rtn += str.Substring(bidx); return rtn; } private void _StartEdit(object sender, C1.Win.C1FlexGrid.RowColEventArgs e) { // start editing the cell with the custom editor _tableCellEditor.StartEditing(e.Row, e.Col); e.Cancel = true; } // after edit handler (built-in editors) private void _AfterEdit(object sender, C1.Win.C1FlexGrid.RowColEventArgs e) { this.AdjustGridControlSize(); } // if the custom editor is visible, make it follow the cell being edited private void _AfterScroll(object sender, C1.Win.C1FlexGrid.RangeEventArgs e) { this._tableCellEditor.UpdatePosition(); } // save last key pressed for the custom editor private void _KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) { this._tableCellEditor.SetPendingKey(e.KeyChar); } public string GetCellRTFString(int row, int col) { string rtnstr = ""; foreach (CellRange r in this.MergedRanges) { if (r.ContainsRow(row) && r.ContainsCol(col)) { rtnstr = (string)this[r.r1, r.c1]; return rtnstr; } } rtnstr = (string)this[row, col]; return rtnstr; } public void PutCellRTFString(int row, int col, string str) { foreach (CellRange r in this.MergedRanges) { if (r.ContainsRow(row) && r.ContainsCol(col)) { this[r.r1, r.c1] = str; return; } } this[row, col] = str; return; } #endregion //Cell Text #region Merged / Split Range public void MergeSelection() { //string tstr = ""; //C1.Win.C1FlexGrid.CellRange sel = this.Selection; //tstr = sel.Clip; // clip hold the data for the selected cells (used for un-merge) this.MergedRanges.Add(this.Selection); this.Invalidate(); } public void SplitSelection() { C1.Win.C1FlexGrid.CellRange sel = this.GetMergedRange(this.Selection.r1, this.Selection.c1); if (this.MergedRanges.Contains(sel)) this.MergedRanges.Remove(sel); this.Invalidate(); } private void AdjustMergedRows(int row, bool above, bool removing) { CellRangeCollection crc = new CellRangeCollection(this); if (removing) { foreach (CellRange r in this.MergedRanges) { CellRange cr = r; if (r.ContainsRow(row)) { if (r.TopRow != r.BottomRow) { cr.r2--; crc.Add(cr); } } else { if (row <= r.r1) { if (row < r.r1) cr.r1--; cr.r2--; } crc.Add(cr); } } } else // adding foreach (CellRange r in this.MergedRanges) { CellRange cr = r; int inspos = (above) ? row : row - 1; if (r.ContainsRow(inspos)) { if ((above && cr.r1 == inspos) || (!above && cr.r2 == inspos)) { string tstr = ""; int newrow = 0; if (above) { if (this[cr.r1 + 1, cr.c1] != null) tstr = this[cr.r1 + 1, cr.c1].ToString(); newrow = cr.r1; } else { if (this[cr.r2, cr.c1] != null) tstr = this[cr.r2, cr.c1].ToString(); newrow = cr.r2 + 1; } if (tstr != null && tstr.Length > 0) for (int x = cr.c1; x <= cr.c2; x++) this[newrow, x] = tstr; } cr.r2++; } else { if (inspos < cr.r1) { cr.r1++; cr.r2++; } } crc.Add(cr); } this.MergedRanges.Clear(); foreach (CellRange r in crc) this.MergedRanges.Add(r); } private void AdjustMergedColumns(int col, bool left, bool removing) { CellRangeCollection crc = new CellRangeCollection(this); if (removing) { foreach (CellRange r in this.MergedRanges) { CellRange cr = r; if (r.ContainsCol(col)) { if (r.LeftCol != r.RightCol) { cr.c2--; crc.Add(cr); } } else { if (col < cr.c1) { cr.c1--; cr.c2--; } crc.Add(cr); } } } else // adding foreach (CellRange r in this.MergedRanges) { CellRange cr = r; int inspos = (left) ? col : col - 1; if (r.ContainsCol(inspos)) { string tstr = ""; int newcol = 0; if (left) { if (inspos == cr.c1) tstr = this[cr.r1, cr.c1 + 1].ToString(); else tstr = this[cr.r1, cr.c1].ToString(); newcol = cr.c1; } else { if (this[cr.r1, cr.c2] != null) tstr = this[cr.r1, cr.c2].ToString(); newcol = cr.c2 + 1; } for (int x = cr.r1; x <= cr.r2; x++) this[x, newcol] = tstr; cr.c2++; } else if (col <= r.c1) { cr.c1++; cr.c2++; } crc.Add(cr); } this.MergedRanges.Clear(); foreach (CellRange r in crc) this.MergedRanges.Add(r); } private bool RowIsInMergeRange(int row) { bool rtn = false; if (row >= 0) { CellRange cr = this.Selection; rtn = true; int c = cr.c1; while (rtn && (c <= cr.c2)) { int idx = this.MergedRanges.IndexOf(row, c); rtn = (idx > -1); c++; } } return rtn; } private bool ColIsInMergeRange(int col) { bool rtn = false; if (col >= 0) { CellRange cr = this.Selection; rtn = true; int r = cr.r1; while (rtn && (r <= cr.r2)) { int idx = this.MergedRanges.IndexOf(col, r); rtn = (idx > -1); r++; } } return rtn; } #endregion //Merged / Split Range #region Grid Add and Remove Row / Column private int GetRowInsertPosition(Boolean before) { int rtnrow; CellRange cr = this.Selection; int idx = this.MergedRanges.IndexOf(cr.r1, cr.c2); if (idx > -1) cr = this.MergedRanges[idx]; // we want first or last row in merge range rtnrow = (before) ? cr.r1 : cr.r2; return rtnrow; } private int GetColInsertPosition(Boolean before) { int rtncol; CellRange cr = this.Selection; int idx = this.MergedRanges.IndexOf(cr.r1, cr.c2); if (idx > -1) cr = this.MergedRanges[idx]; // we want the first of last col in merge range rtncol = (before) ? cr.c1 : cr.c2; return rtncol; } public void InsertColumnBefore() { int newcol = this.GetColInsertPosition(true); this.Cols.Insert(newcol); this.AdjustMergedColumns(newcol, true, false); this.AdjustGridControlSize(); } public void InsertColumnAfter() { int colidx = this.GetColInsertPosition(false); if (colidx == this.Cols.Count - 1) // last column this.Cols.Add(1); else this.Cols.Insert(colidx + 1); this.AdjustMergedColumns(colidx + 1, false, false); this.AdjustGridControlSize(); } public void InsertRowBefore() { int newrow = this.GetRowInsertPosition(true); this.Rows.Insert(newrow); this.AdjustMergedRows(newrow, true, false); this.AdjustGridControlSize(); } public void InsertRowAfter() { int rowidx = this.GetRowInsertPosition(false); if (rowidx == this.Rows.Count - 1) // last row this.Rows.Add(1); else this.Rows.Insert(rowidx + 1); this.AdjustMergedRows(rowidx + 1, false, false); this.AdjustGridControlSize(); } public void RemoveSelectedColumn() { this.SelectionMode = SelectionModeEnum.Column; this.Select(this.Selection.r1, this.Selection.c1); DialogResult dr = MessageBox.Show("Remove this column?", "Remove Column", MessageBoxButtons.YesNo); if (dr == DialogResult.Yes) RemoveColumns(this.Selection.r1, this.Selection.c1, 1); this.SelectionMode = SelectionModeEnum.Default; } public void RemoveSelectedRow() { this.SelectionMode = SelectionModeEnum.Row; this.Select(this.Selection.r1, this.Selection.c1); DialogResult dr = MessageBox.Show("Remove this Row?", "Remove Row", MessageBoxButtons.YesNo); if (dr == DialogResult.Yes) this.RemoveRows(this.Selection.r1, this.Selection.c1, 1); this.SelectionMode = SelectionModeEnum.Default; } private void RemoveRows(int strow, int stcol, int cnt) { for (int i = 0; i < cnt; i++) { if (this.RowIsInMergeRange(strow)) { for (int cl = 0; cl < this.Cols.Count; cl++) { int idx = this.MergedRanges.IndexOf(strow, cl); if (idx > -1) { CellRange cr = this.MergedRanges[idx]; if (cr.r1 < cr.r2) this[cr.r1 + 1, cr.c1] = this[cr.r1, cr.c1]; } cl++; } } this.Rows.Remove(strow); this.AdjustMergedRows(strow, false, true); } this.AdjustGridControlSize(); } private void RemoveColumns(int strow, int stcol, int cnt) { for (int i = 0; i < cnt; i++) { if (this.ColIsInMergeRange(stcol)) { for (int rw = 0; rw < this.Rows.Count; rw++) { int idx = this.MergedRanges.IndexOf(rw, stcol); if (idx > -1) { CellRange cr = this.MergedRanges[idx]; if (cr.c1 < cr.c2) this[cr.r1, cr.c1 + 1] = this[cr.r1, cr.c1]; } } } this.Cols.Remove(stcol); this.AdjustMergedColumns(stcol, false, true); } this.AdjustGridControlSize(); } public void RemoveSelectedCells() { bool didremove = false; int lastRow = this.Rows.Count - 1; int lastCol = this.Cols.Count - 1; CellRange cr = this.Selection; // r2 is last row (or in merge range containing last row) // r1 is first row or r1-m (m is in merge range) is first row // we can remove columns c1 through c2 int idx = this.MergedRanges.IndexOf(cr.r2, cr.c2); CellRange mr = new CellRange(); if (idx > -1) mr = this.MergedRanges[idx]; if (cr.r2 == lastRow || idx > -1 && mr.r2 == lastRow)//RowIsInMergeRange(grd,cr.r2)) { if (cr.r1 == 0 || this.RowIsInMergeRange(cr.r1 - 1)) { this.RemoveColumns(cr.r1, cr.c1, cr.RightCol - cr.LeftCol + 1);// remove selected columns didremove = true; } } // c2 is last column (or in merge range containing last column) // c1 is first column or c1-m (m is merge range) is first column // we can remove rows r1 through r2 if (cr.c2 == lastCol || idx > -1 && mr.c2 == lastCol)//ColIsInMergeRange(grd,cr.c1-1)) { if (cr.c1 == 0 || this.ColIsInMergeRange(cr.c1 - 1)) { // remove selected rows this.RemoveRows(cr.r1, cr.c1, cr.BottomRow - cr.TopRow + 1); didremove = true; } } if (!didremove) MessageBox.Show("Cannot Removed Part of a Row or Column.", "Invalid Selection"); return; } #endregion //Grid Add and Remove Row / Column #region Clipboard public void ClipBoardCopyRow() { this.SelectionMode = SelectionModeEnum.Row; this.Select(this.Selection.r1, 0, this.Selection.r2, this.Cols.Count - 1, true); DialogResult dr = MessageBox.Show("Copy these Rows?", "Copy Rows", MessageBoxButtons.YesNo); if (dr == DialogResult.Yes) _clpbrdCpyPste.Put(this.Selection); this.SelectionMode = SelectionModeEnum.Default; } public void ClipBoardCopyColumn() { this.SelectionMode = SelectionModeEnum.Column; this.Select(0, this.Selection.c1, this.Rows.Count - 1, this.Selection.c2, true); DialogResult dr = MessageBox.Show("Copy these columns?", "Copy Columns", MessageBoxButtons.YesNo); if (dr == DialogResult.Yes) _clpbrdCpyPste.Put(this.Selection); this.SelectionMode = SelectionModeEnum.Default; } public void ClipBoardCopySelection() { this.Select(this.Selection.r1, this.Selection.c1, this.Selection.r2, this.Selection.c2); DialogResult dr = MessageBox.Show("Copy Selected Cells?", "Copy Selection", MessageBoxButtons.YesNo); if (dr == DialogResult.Yes) _clpbrdCpyPste.Put(this.Selection); } private void CopyTextFromCellRange(ArrayList arylst, int srow, int scol, int erow, int ecol) { StepRTB trtb = new StepRTB(); int aryidx = 0; for (int r = srow; r <= erow; r++) { for (int c = scol; c <= ecol; c++) { if (aryidx >= arylst.Count) trtb.Text = ""; else { trtb.Rtf = (string)(arylst[aryidx++]); trtb.AdjustWidthForContent(); } this[r, c] = trtb.Rtf; this.AdjustGridHeightWidth(r, c); } } } public enum enmPastePos : int { Before = 1, Replace = 0, After = -1 } public void ClipBoardPasteRows(enmPastePos pp) { // Get a list of strings representing the text (rtf text) in each cell // that was saved to the clipboard (row/column order) ArrayList aryCellList = _clpbrdCpyPste.Get(); if (aryCellList != null && aryCellList.Count > 0) { // get row/column starting position in which new rows will be added int startrow = this.Selection.r1 + ((pp == enmPastePos.After) ? 1 : 0); int startcol = this.Selection.c1; // get the number of rows needed based on what was save to the clipboard int numrows = Math.Max(1, (aryCellList.Count / this.Cols.Count)); // insert that number of new rows. if (pp != enmPastePos.Replace) // insert new rows before or after for (int r = 0; r < numrows; r++) if (pp == enmPastePos.After) // create new rows after this.InsertRowAfter(); else this.InsertRowBefore(); // copy each grid cell text (aryCellList) into the newly inserted rows CopyTextFromCellRange(aryCellList, startrow, startcol, startrow + numrows - 1, startcol + this.Cols.Count - 1); this.AdjustGridControlSize(); } } public void ClipBoardPasteColumns(enmPastePos pp) { // Get a list of strings representing the text (rtf text) in each cell // that was saved to the clipboard (row/column order) ArrayList aryCellList = _clpbrdCpyPste.Get(); if (aryCellList != null && aryCellList.Count > 0) { // get row/column starting position in which new rows will be added int startrow = 0;//grd.Selection.r1+((pp == enmPastePos.After) ? 1 : 0); int startcol = this.Selection.c1 + ((pp == enmPastePos.After) ? 1 : 0); // get the number of rows needed based on what was save to the clipboard int numcols = Math.Max(1, (aryCellList.Count / this.Rows.Count)); // insert that number of new rows. if (pp != enmPastePos.Replace) // insert new rows before or after for (int c = 0; c < numcols; c++) if (pp == enmPastePos.After) // create new rows after this.InsertColumnAfter(); else this.InsertColumnBefore(); // copy each grid cell text (aryCellList) into the newly inserted rows this.CopyTextFromCellRange(aryCellList, startrow, startcol, startrow + this.Rows.Count - 1, startcol + numcols - 1); this.AdjustGridControlSize(); } } public void ClipBoardPasteIntoSelection() { // Get a list of strings representing the text (rtf text) in each cell // that was saved to the clipboard (row/column order) ArrayList aryCellList = _clpbrdCpyPste.Get(); if (aryCellList != null && aryCellList.Count > 0) { // copy each grid cell text (aryCellList) into the selected cells this.CopyTextFromCellRange(aryCellList, this.Selection.r1, this.Selection.c1, this.Selection.r2, this.Selection.c2); this.AdjustGridControlSize(); } } #endregion //Clipboard #region Import / Export Grid /// /// Prompts user with Save File dialog. /// Grid will be saved to an XML file. /// /// public void ExportToXML(string initDir) { SaveFileDialog sfd = new SaveFileDialog(); sfd.DefaultExt = ".xml"; sfd.Filter = "XML files (*.xml)|*.xml|All files (*.*)|*.* "; //sfd.InitialDirectory = @"C:\Development\SampleTableData"; sfd.InitialDirectory = initDir; sfd.Title = "Save XML File"; sfd.ShowDialog(); this.WriteXml(sfd.FileName); } /// /// Prompts user with Save File dialog. /// Grid will be saved to an Excel file. /// /// public void ExportToExcel(string initDir) { SaveFileDialog sfd = new SaveFileDialog(); sfd.DefaultExt = ".xls"; sfd.Filter = "Excel files (*.xls)|*.xls|All files (*.*)|*.* "; //sfd.InitialDirectory = @"C:\Development\SampleTableData"; sfd.InitialDirectory = initDir; sfd.Title = "Save Excel File"; sfd.ShowDialog(); this.SaveExcel(sfd.FileName); } /// /// Prompts user with Open File dialog. /// XML file will be imported to a table grid. /// /// /// public string ImportXML(string initDir) { string rtn = ""; OpenFileDialog ofd = new OpenFileDialog(); ofd.DefaultExt = ".xml"; ofd.Filter = "XML files (*.xml)|*.xml|All files (*.*)|*.* "; //ofd.InitialDirectory = @"C:\Development\SampleTableData"; ofd.InitialDirectory = initDir; ofd.Multiselect = false; ofd.Title = "Select XML File"; ofd.ShowDialog(); this.Clear(); this.MergedRanges.Clear(); this.ReadXml(ofd.FileName); this.AdjustGridControlSize(); rtn = ofd.SafeFileName; return rtn; } /// /// Prompts user with Open File dialog. /// Excel file will be imported to a table grid. /// /// /// public string ImportExcel(string initDir) { string rtn = ""; //VlnFlexGrid grd = rbtDefaultTable.Checked ? vlnFlexGrid2 : vlnFlexGrid3; //GetActiveGrid(); OpenFileDialog ofd = new OpenFileDialog(); ofd.DefaultExt = ".xls"; ofd.Filter = "Excel files (*.xls)|*.xls|All files (*.*)|*.*"; //ofd.InitialDirectory = @"C:\Development\SampleTableData"; ofd.InitialDirectory = initDir; ofd.Multiselect = false; ofd.Title = "Select Excel File"; ofd.ShowDialog(); this.Clear(); this.MergedRanges.Clear(); this.LoadExcel(ofd.FileName); this.AdjustGridControlSize(); rtn = ofd.SafeFileName; return rtn; } /// /// This will parse a string containing the ascii text of the old style VE-PROMS (16-bit) tables. /// It will find the number of rows and columns base on newlines, vertical bars, and dashes. /// Then it will parse the the text, place them in celll, and attempt to merge cells were needed. /// /// public void ParseTableFromText(string txtbuff) { int curRow = 0; int curCol = 0; int maxRow = 0; int maxCol = 0; // Get Max Rows and Max Cols char[] test = "|\n\x02".ToCharArray(); int idx = 0; int idxst = 0; int colPos = 0; int strow = 0; Dictionary dicCols = new Dictionary(); do { idx = txtbuff.IndexOfAny(test, idxst); if (idx > -1) { switch (txtbuff[idx]) { case '|': // end of a column colPos = idxst - strow; if (!dicCols.ContainsKey(colPos)) dicCols.Add(colPos, curCol); else if (curCol > dicCols[colPos]) { dicCols.Remove(colPos); dicCols.Add(colPos, curCol); } curCol++; break; case '\x02': case '\n': // end of a row colPos = idxst - strow; if (!dicCols.ContainsKey(colPos)) dicCols.Add(colPos, curCol); else if (curCol > dicCols[colPos]) { dicCols.Remove(colPos); dicCols.Add(colPos, curCol); } curRow++; strow = idx + 1; if (curCol > maxCol) maxCol = curCol; curCol = 0; break; } idxst = idx + 1; if (idxst >= txtbuff.Length) idx = -1; } } while (idx != -1); maxRow = curRow + 1; curRow = 0; curCol = 0; // The resulting Table Grid size in rows and columns this.Cols.Count = maxCol + 1; this.Rows.Count = maxRow + 1; // make all rows and columns editable this.Rows.Fixed = 0; this.Cols.Fixed = 0; // TableCellInfo is used to assign merge ranges // Make a two dimensional array of TableCellinfo the same size as the table grid TableCellInfo[,] tci = new TableCellInfo[maxRow + 1, maxCol + 1]; for (int r = 0; r <= maxRow; r++) for (int c = 0; c <= maxCol; c++) tci[r, c] = new TableCellInfo(); // Read in each cell of the grid idx = 0; idxst = 0; colPos = 0; strow = 0; int prevCol = 0; int tstidx = 0; string tstr = ""; bool incRow = false; do { idx = txtbuff.IndexOfAny(test, idxst); if (idx > -1) { switch (txtbuff[idx]) { case '|': // end of column colPos = idxst - strow; // based on the position of the | char, find what column we are in. // note that this will tell us if any columns to the left were merged // the while loop will flag cell that need to be merged curCol = dicCols[colPos]; while (curCol > prevCol + 1) { tci[curRow, prevCol].MergeColRight = true; prevCol++; } prevCol = curCol; // parse out the text to be placed in the table cell tstr = txtbuff.Substring(idxst, idx - idxst); if (tstr.Length == 0) tstr += " "; // test for a string of '-' characters for (tstidx = 0; (tstidx < tstr.Length) && (tstr[tstidx] == '-'); tstidx++) ; if (tstidx < tstr.Length) // not a full line (row) of '-' chars { // if this column is in a merged grouping of rows, // get the cell text in the first cell of the merged grouping of cells // we will append the newly parsed text to this cell's text. int rw = curRow; while (rw - 1 > 0 && tci[rw - 1, curCol].MergeRowBellow) rw--; string jstr = (string)this[rw, curCol]; if (jstr == null) jstr = tstr; else jstr += "\n" + tstr; // multi line cell this[rw, curCol] = jstr; // take a peek at the start of the next piece of table text to parse // if it starts with a '-' char, then flag to merge the columns up to // this point with the same columns in the next row if (idx < txtbuff.Length - 1 && txtbuff[idx + 1] == '-') { for (int c = curCol; c >= -0; c--) if (!tci[curRow, c].ColEnd) tci[curRow, c].MergeRowBellow = true; } } else // parsed text contains all dashes { tci[curRow, curCol].ColEnd = true; incRow = true; } break; case '\x02': // end of file case '\n': // new line of 16-bit table text colPos = idxst - strow; // see what column we are in - new line might occure before last grid column curCol = dicCols[colPos]; strow = idx + 1; // parse out the cell text tstr = txtbuff.Substring(idxst, idx - idxst); if (tstr.EndsWith("\r")) // strip off carrage return tstr = tstr.Substring(0, tstr.Length - 1); if (tstr.Length == 0) tstr += " "; // test for a string of '-' characters for (tstidx = 0; (tstidx < tstr.Length) && (tstr[tstidx] == '-'); tstidx++) ; if (tstidx < tstr.Length) // not a full line (row) of '-' chars { // if this column is in a merged grouping of rows, // get the cell text in the first cell of the merged grouping of cells // we will append the newly parsed text to this cell's text. int rw = curRow; while (rw - 1 > 0 && tci[rw - 1, curCol].MergeRowBellow) rw--; string jstr = (string)this[rw, curCol]; if (jstr == null) jstr = tstr; else jstr += "\n" + tstr; // multi line cell this[rw, curCol] = jstr; } else if (tstr.Length > 0) // parsed text is all dash characters { incRow = true; if (curRow > 0) // merge the column in the previous row with this one tci[curRow - 1, curCol].MergeRowBellow = false; } // if were are that the end of the 16-bit text line, but not in the last column, // merge the remaining columns to the right if ((curCol < maxCol) && (tstidx < tstr.Length)) { for (int i = curCol; i < maxCol; i++) tci[curRow, i].MergeColRight = true; } if (incRow) curRow++; curCol = 0; incRow = false; break; } idxst = idx + 1; if (idxst >= txtbuff.Length) idx = -1; } else if (idxst < txtbuff.Length - 1) // handle any remaining text not yet parsed { // find the curent column and merge remaining columns to the right colPos = idxst - strow; curCol = dicCols[colPos]; while (curCol > prevCol + 1) { tci[curRow, prevCol].MergeColRight = true; prevCol++; } // parse out the remaining text tstr = txtbuff.Substring(idxst); if (tstr.Length == 0) tstr += " "; // test for a string of '-' characters for (tstidx = 0; (tstidx < tstr.Length) && (tstr[tstidx] == '-'); tstidx++) ; if (tstidx < tstr.Length) { // if this column is in a merged grouping of rows, // get the cell text in the first cell of the merged grouping of cells // we will append the newly parsed text to this cell's text. int rw = curRow; while (rw - 1 > 0 && tci[rw - 1, curCol].MergeRowBellow) rw--; string jstr = (string)this[rw, curCol]; if (jstr == null) jstr = tstr; else jstr += "\n" + tstr; // multi line cell this[rw, curCol] = jstr; } } } while (idx != -1); // we are done parsing the 16-bit text. // now set the merge ranges in the table grid, based on the // information saved in that two dimensional array of TableCellinfo this.Rows.Count = curRow + 1; this.AllowMerging = C1.Win.C1FlexGrid.AllowMergingEnum.Custom; maxRow = curRow; int rR = 0; int rC = 0; for (int r = 0; r <= maxRow; r++) for (int c = 0; c <= maxCol; c++) { if (tci[r, c].MergeColRight) { rC = c; while ((rC < maxCol) && (tci[r, rC].MergeColRight)) rC++; if (rC > c) { this.MergedRanges.Add(this.GetCellRange(r, c, r, rC)); string cellstr = this[r, c].ToString(); for (int x = c + 1; x <= rC; x++) this[r, x] = cellstr; c = rC; } } } for (int c = 0; c <= maxCol; c++) for (int r = 0; r <= maxRow; r++) { if (tci[r, c].MergeRowBellow) { rR = r; while ((rR < maxRow) && (tci[rR, c].MergeRowBellow)) rR++; if (rR > r) { this.MergedRanges.Add(this.GetCellRange(r, c, rR, c)); string cellstr = this[r, c].ToString(); for (int x = r + 1; x <= rR; x++) this[x, c] = cellstr; r = rR; } } } } #endregion //Import / Export Grid #region Bug Work Around protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { // Note: this fixes a bug that happens when the grid has more rows than columns // notified ComponentOne of the problem 6/25/09 via Email try { base.OnMouseDown(e); } catch (Exception ex) { while (ex != null) { Console.WriteLine("{0} {1} {2}", ex.GetType().Name, ex.Message, ex.StackTrace); ex = ex.InnerException; } } } #endregion //Bug Work Around } #region RTF Class for Cell rendering class RTF : StepRTB //RichTextBox { // messages used by RichEd20.dll internal const int WM_USER = 0x0400, EM_FORMATRANGE = WM_USER + 57; // FORMATRANGE is used by RichEd20.dll to render RTF internal struct FORMATRANGE { internal IntPtr hdc, hdcTarget; internal Rectangle rc, rcPage; internal int cpMin, cpMax; } // render the control directly into a given Graphics object // (this does not honor clipping set in the target Graphics object; it that is // a problem, use the RenderClipped method instead). public void Render(Graphics g, Rectangle rc) { // convert rect from pixels to twips rc.X = (int)(rc.X * 1440 / g.DpiX); rc.Y = (int)(rc.Y * 1440 / g.DpiY); rc.Width = rc.X + (int)((rc.Width) * 1440 / g.DpiX); rc.Height = rc.Y + (int)((rc.Height) * 1440 / g.DpiY); // get dc IntPtr hdc = g.GetHdc(); // set up FORMATRANGE struct FORMATRANGE fmt = new FORMATRANGE(); fmt.hdc = fmt.hdcTarget = hdc; fmt.rc = fmt.rcPage = rc; fmt.cpMin = 0; fmt.cpMax = -1; // render RTF int render = 1; SendMessageFormatRange(Handle, EM_FORMATRANGE, render, ref fmt); // clean up SendMessage(Handle, EM_FORMATRANGE, render, 0); // done with dc g.ReleaseHdc(hdc); } // render RTF into a Graphics object using a temporary bitmap to ensure // clipping works correctly. public void RenderClipped(Graphics g, Rectangle rc) { // create temp bitmap Rectangle rcSrc = new Rectangle(0, 0, rc.Width, rc.Height); using (Bitmap bmp = new Bitmap(rc.Width, rc.Height)) { // render RTF into bitmap using (Graphics gBmp = Graphics.FromImage(bmp)) { Render(gBmp, rcSrc); // transfer bitmap to original Graphics object // (this honors clipping set in the target Graphics object) g.DrawImage(bmp, rc, rcSrc, GraphicsUnit.Pixel); } } } // SendMessage [DllImport("USER32.DLL", CharSet = CharSet.Auto)] static private extern int SendMessage( IntPtr hWnd, uint wMsg, int wParam, int lParam); [DllImport("USER32.DLL", CharSet = CharSet.Auto, EntryPoint = "SendMessage")] static private extern int SendMessageFormatRange( IntPtr hWnd, uint wMsg, int wParam, ref FORMATRANGE lParam); } #endregion //RTF Class for Cell rendering # region TableCellInfo for text parse class TableCellInfo { private bool _MergeRowBellow; public bool MergeRowBellow { get { return _MergeRowBellow; } set { _MergeRowBellow = value; } } private bool _MergeColRight; public bool MergeColRight { get { return _MergeColRight; } set { _MergeColRight = value; } } private bool _ColEnd; public bool ColEnd { get { return _ColEnd; } set { _ColEnd = value; } } private string _Text; public string Text { get { return _Text; } set { _Text = value; } } } #endregion //TableCellInfo for text parse #region TableCellEditor /// /// TableCellEditor inherits from a StepRTB and is used as a custom cell editor /// for the C1FlexGrid control. /// public class TableCellEditor : StepRTB //System.Windows.Forms.RichTextBox //System.Windows.Forms.TextBox // System.Windows.Forms.ComboBox { private VlnFlexGrid _owner; private int _row, _col; private char _pendingKey; private bool _cancel; // constructor: attach to owner grid public TableCellEditor(VlnFlexGrid owner) { Visible = false; AutoSize = false; BackColor = Color.Beige; BorderStyle = BorderStyle.None; _pendingKey = (char)0; _cancel = false; _owner = owner; _owner.Controls.Add(this); this.CursorMovement += new StepRTBCursorMovementEvent(TableCellEditor_CursorMovement); this.CursorKeyPress += new StepRTBCursorKeysEvent(TableCellEditor_CursorKeyPress); this.Leave += new EventHandler(_editor_Leave); this.HeightChanged += new StepRTBEvent(_HeightChanged); } // start editing: move to cell and activate public void StartEditing(int row, int col) { // save coordinates of cell being edited _row = row; _col = col; this.Clear(); // assume we'll save the edits _cancel = false; // move editor over the current cell Rectangle rc = _owner.GetCellRect(row, col, true); rc.Width--; rc.Height--; Bounds = rc; // initialize control content Text = ""; if (_pendingKey > ' ') Text = _pendingKey.ToString(); else if (_owner[row, col] != null) { string tmp = _owner[row, col].ToString(); if (tmp.StartsWith(@"{\rtf")) Rtf = tmp; else Text = tmp; } Select(Text.Length, 0); Size sz = new Size(rc.Width, rc.Height); this.Size = sz; // make editor visible Visible = true; // and get the focus Select(); } void TableCellEditor_CursorKeyPress(object sender, KeyEventArgs args) { //throw new Exception("The method or operation is not implemented."); } void TableCellEditor_CursorMovement(object sender, StepRTBCursorMovementEventArgs args) { int row = _owner.Selection.r1; int col = _owner.Selection.c1; CellRange cr = _owner.Selection; //Console.WriteLine("keystroke {0} selection {1},{2}", args.Key, row, col); //vlnStackTrace.ShowStack("keystroke {0} selection {1},{2}", args.Key, row, col); _owner.Select(); // See if we are in a merged range of cells. // if so, use the merged range instead of the selected range // so that we can jump to the top/bottom/left/right of the range // before attempting the move to the next grid cell. int idx = _owner.MergedRanges.IndexOf(row, col); if (idx > -1) cr = _owner.MergedRanges[idx]; switch (args.Key) { case VEPROMS.CSLA.Library.E_ArrowKeys.CtrlDown: case VEPROMS.CSLA.Library.E_ArrowKeys.Down: row = cr.r2; if (row < _owner.Rows.Count - 1) _owner.Select(row + 1, col); break; case VEPROMS.CSLA.Library.E_ArrowKeys.CtrlLeft: case VEPROMS.CSLA.Library.E_ArrowKeys.Left: col = cr.c1; if (col > 0) _owner.Select(row, col - 1); break; case VEPROMS.CSLA.Library.E_ArrowKeys.CtrlRight: case VEPROMS.CSLA.Library.E_ArrowKeys.Right: col = cr.c2; if (col < _owner.Cols.Count - 1) _owner.Select(row, col + 1); break; case VEPROMS.CSLA.Library.E_ArrowKeys.CtrlUp: case VEPROMS.CSLA.Library.E_ArrowKeys.Up: row = cr.r1; if (row > 0) _owner.Select(row - 1, col); break; default: break; } //Console.WriteLine("selection {0}", _owner.Selection); _owner.Focus(); // focus was jumping out of the grid this keeps it in. } // after edit handler (custom editor) void _editor_Leave(object sender, EventArgs e) { _owner.Invalidate(); _owner.AdjustGridControlSize(); } void _HeightChanged(object sender, EventArgs args) { _owner.Invalidate(); } // save key that started the editing mode public void SetPendingKey(char chr) { _pendingKey = chr; } // expose internal variables public bool Cancel { get { return _cancel; } } public int Row { get { return _row; } } public int Col { get { return _col; } } // move editor after the grid has scrolled public void UpdatePosition() { // get cell rect now Rectangle rcCell = _owner.GetCellRect(_row, _col, false); // intersect with scrollable part of the grid Rectangle rcScroll = _owner.ClientRectangle; rcScroll.X = _owner.Cols[_owner.Cols.Fixed].Left; rcScroll.Y = _owner.Rows[_owner.Rows.Fixed].Top; rcScroll.Width -= rcScroll.X; rcScroll.Height -= rcScroll.Y; rcCell = Rectangle.Intersect(rcCell, rcScroll); // and move the control if (rcCell.Width > 0) rcCell.Width--; if (rcCell.Height > 0) rcCell.Height--; Bounds = rcCell; Size sz = new Size(_owner.GetCellRect(_row, _col).Width, _owner.GetCellRect(_row, _col).Height); this.Size = sz; } // lost focus: hide the editor override protected void OnLeave(System.EventArgs e) { // base processing base.OnLeave(e); // copy text to owner grid if (!_cancel) { _owner[_row, _col] = Rtf; //Text; } // no more pending keys _pendingKey = (char)0; // done for now, hide editor Visible = false; } // we will handle the Tab key ourselves override protected bool IsInputKey(Keys keyData) { if (keyData == Keys.Tab) return true; return base.IsInputKey(keyData); } //// some keys end the editing //override protected void OnKeyDown(System.Windows.Forms.KeyEventArgs e) //{ // switch (e.KeyCode) // { // case Keys.Escape: // cancel edits // _cancel = true; // _owner.Select(); // e.Handled = true; // return; // case Keys.Enter: // finish editing // case Keys.Tab: // case Keys.Up: // case Keys.Down: // case Keys.PageUp: // case Keys.PageDown: // _owner.Select(); // e.Handled = true; // MoveCursor(e.KeyCode); // return; // default: // default processing // base.OnKeyDown(e); // return; // } //} //// move cursor after done editing //protected void MoveCursor(Keys key) //{ // int row = _owner.Row; // int col = _owner.Col; // switch (key) // { // case Keys.Tab: col++; break; // case Keys.Up: row--; break; // //case Keys.Return: row++; break; // case Keys.Down: row++; break; // //case Keys.PageUp: row -= 10; break; // //case Keys.PageDown: row += 10; break; // } // // validate new selection // if (row < _owner.Rows.Fixed) row = _owner.Rows.Fixed; // if (col < _owner.Cols.Fixed) col = _owner.Cols.Fixed; // if (row > _owner.Rows.Count - 1) row = _owner.Rows.Count - 1; // if (col > _owner.Cols.Count - 1) col = _owner.Cols.Count - 1; // // apply new selection // _owner.Select(row, col); //} //// suppress some keys to avoid annoying beep //override protected void OnKeyPress(System.Windows.Forms.KeyPressEventArgs e) //{ // switch (e.KeyChar) // { // case (char)27: // Keys.Escape: // case (char)13: // Keys.Enter: // case (char)9: // Keys.Tab: // e.Handled = true; // return; // } // base.OnKeyPress(e); //} } #endregion // TableCellEditor #region TableClipBoardFuncts Class class TableClipBoardFuncts { DataFormats.Format dfmtTableCellRange = DataFormats.GetFormat("TableCellRange"); public TableClipBoardFuncts() { //mySeldTableCellsObject = new DataObject(dfmtTableCellRange.Name, seldTableCells); } public void Put(CellRange cr) { // Copies myObject into the clipboard. // Clip get the value (text) of all the cells in the selected range // This is saved as one RTF string. Clipboard.SetDataObject(cr.Clip, true); // the "true" make the copy persistent } public ArrayList Get() { // Retrieves the data from the clipboard. IDataObject myRetrievedObject = Clipboard.GetDataObject(); string jj = (string)myRetrievedObject.GetData(DataFormats.Text); return GetCellStrings(jj); } private ArrayList GetCellStrings(string instr) { // The table cells placed on the clipboard is saved as one long RTF string. // "\r\n\t" defines a cell border // "\r\n\r" defines beginning of next line (row) // This function will separate each cell text and place them in an array. // This allow the clipboard information to be pasted independently from // how it was selected. string tstr = ""; // this will contain the parsed out cell text ArrayList arylstCellStrings = new ArrayList(); int sidx = 0; // start index int tidx = 0; if (instr != null) { int idx = instr.IndexOf("\r\n\t"); // cell boarder if (idx < 0) idx = instr.IndexOf("\r\n\r"); // new line (needed for multiple lines in one cell) while (idx > 0) { tstr = instr.Substring(sidx, idx - sidx); tidx = tstr.IndexOf("\r\n\r"); if (tidx > 0) { idx = instr.IndexOf("\r\n\r", sidx); tstr = instr.Substring(sidx, idx - sidx); } arylstCellStrings.Add(tstr.Substring(tstr.IndexOf("{\\rtf"))); sidx = idx + 3; if (sidx < instr.Length) { idx = instr.IndexOf("\r\n\t", sidx); if (idx < 0) idx = instr.IndexOf("\r\n\r", sidx); } } if (sidx < instr.Length) { tstr = instr.Substring(sidx); arylstCellStrings.Add(tstr.Substring(tstr.IndexOf("{\\rtf"))); } } return arylstCellStrings; } } [Serializable] public class SelectedTableCells : Object { private CellRange _cpbrdCellRange; public CellRange CpbrdCellRange { get { return _cpbrdCellRange; } set { _cpbrdCellRange = value; } } public SelectedTableCells() { } } #endregion // TableClipBoardFuncts Class }