HOME  | DEMO  | BUY NOW

    SimpleGrid  (c) 2000- 2006 Octatec Ltd
   
SimpleGrid is a very easy-to-use Active/X Grid control suitable for use in Visual C++ or Visual Basic Applications. There are many methods and properties that allow a great deal of control over the grids appearance, but very few methods need to be used to get a working application. Cells can be edited as normal, via a drop-down list of choices, or via check-boxes.

Contents


Introduction

As already stated, SimpleGrid is so named because it is simple to use. A bold and unusual claim for a grid control. You will no doubt be aware that their are many Grid Controls available, so why would you choose this one? Well, firstly, if you're looking for spread-sheet functionality, this is not the grid for you - it does not support formulae or any sort of automatic calculations.. If, however, you just want a grid for data entry and/or data display this is the grid for you. Despite its ease of use, its appearance and functionality can be tailored to meet your individual needs. The following is a list of its main features.
  • The grid cells can be either editable or read-only, cell text editing is fully implemented by the grid.
  • Cells can be defined to contain lists and are then edited by means of a drop-down list box.
  • Cells  can be defined to contain checkboxes.
  • Cells can be defined to contain buttons.
  • Data entered into cells can be automatically validated for integral or floating point number, this can be set on a per-cell basis
  • An event is fired when an edit is complete so you can implement custom validation
  • An event is fired whenever an editable cell is clicked, you can then set a flag from the event that will prevent the edit if you wish
  • An event is fired whenever a column heading is clicked
  • Events are fire when buttons are clicked, allowing you to easily add pop-up context menus
  • The grid can be configured so that rows are automatically added when the user hits RETURN on the last row, when this happens, an event is fired, allowing you to set initial data in the newly created row.
  • You can enable or disabled visual markings of selected rows and/or columns and/or cells.
  • The background and text colours can be set for the whole grid or for selected cells.
  • Grid lines can be enabled or disabled for rows and/or columns.
  • As well as the standard ability to give columns headings, you can also easily give rows 'headings' if you wish, and make this 'row-heading column' read-only, even when the rest of the grid is editable..
  • All screen drawing is double buffered to eliminate flicker, so you could easily use the grid to display real-time data.
  • The grid can automatically resize when the control-container resizes, or its size can remain fixed
  • The grid can be automatically populated from an ADO recordset, CSV file or SAFEARRAY.
All the above functionality can be accessed by simple method calls on the object, you won't need to jump through any hoops to get this grid to behave exactly the way you want.


Getting Started

A full set of C++ and VB samples are supplied with the OCX, however, here is a brief guide to get you started.

Typically, you will have the following code to initialize your grid. This code is taken from the VB sample provided with the grid, however, it's equally as simple in C++  (NB, most of the samples are in C++)

   ' add columns

    SimpleGrid1.AddProportionateColumn "C1", 4, True
    SimpleGrid1.AddProportionateColumn "C2", 4, True
    SimpleGrid1.AddProportionateColumn "C3", 4, True
    SimpleGrid1.AddProportionateColumn "C4", 4, True
        ' the columns are proportionate, using one quater of the
        ' available space each

    ' now add rows

    SimpleGrid1.AddRows 5

    ' now add dummy data

    For r = 0 To 4
        For c = 0 To 3
            s = "rc:" & r & "," & c
            SimpleGrid1.SetCellText r, c, s
         Next c
    Next r

Its as simple as that. You can set properties before you start, and/or change them when the grid is active.


Property, Method and Event Summary

The following is an ODL-style summary of the methods. The same information is available from the type-library, supplied with the control. A full description of each property and method by cetegory follows this section.

properties
[id(01)] long DfltBkgdColor;
[id(02)] long DfltTextColor;
[id(03)] long EditBkgdColor;
[id(04)] long EditTextColor;
[id(05)] boolean RowLines;
[id(06)] boolean ColumnLines;
[id(07)] long GridLineColor;
[id(08)] boolean SelectOnEditMode;
[id(09)] boolean IntegerValidation;
[id(10)] boolean FloatingValidation;
[id(11)] boolean NavigationOnlyByClick;
[id(12)] boolean NoColumnZeroDrag;
[id(13)] boolean NoColumnZeroEdit;
[id(14)] boolean ColumnZero3DEffect;
[id(15)] boolean ColumnZeroClickFeedback;
[id(16)] boolean MultiLineHdr;
[id(17)] boolean BoldHdr;
[id(18)] boolean SortingOnColumnClick;
[id(19)] boolean ColumnDragEnabled;
[id(20)] boolean EnableColumnSelection;
[id(21)] boolean SelectionFromHdrOnly;
[id(22)] boolean ReadOnly;
[id(23)] boolean MaintainROCurrentCellMark;
[id(24)] boolean EnableRowSelection;
[id(25)] long SelectionColor;
[id(26)] long UnusedSpaceColor;
[id(27)] boolean SelectOnEdit;
[id(28)] boolean AutoAddRow;
[id(29)] boolean NoHdr;
[id(30)] boolean EditHScroll;
[id(31)] boolean NoResizeColumns;
[id(32)] boolean NoEscapeEdit;

methods
[id(33)] boolean AddRows(long numberOfRows);
[id(34)] boolean SetCellText(long row, long col, BSTR text);
[id(35)] BSTR GetCellText(long row, long col);
[id(36)] boolean EditCell(long row, long col);
[id(37)] long GetRowCount();
[id(38)] long GetColumnCount();
[id(39)] void Redraw();
[id(40)] void Resize(long cx, long cy);
[id(41)] void SetFocus();
[id(42)] boolean CopyGridToClipboard();
[id(43)] boolean CopyCurrentColumnToClipboard();
[id(44)] boolean CopyCurrentCellToClipboard();
[id(45)] boolean SetSelectedRow(long row);
[id(46)] boolean SetSelectedColumn(long col);
[id(47)] boolean SetCellColours(long row, long col, long crNormalBkgd, long crNormalText, long crEditBkgd, long crEditText)
[id(48)] boolean SetCellIntegerValidation(long row, long col);
[id(49)] boolean SetCellFloatValidation(long row, long col);
[id(50)] boolean SetCellNoValidation(long row, long col);
[id(51)] boolean AddColumn(BSTR columnName, long width, boolean leftJustify);
[id(52)] boolean AddProportionateColumn(BSTR columnName, long proportionateWidth, boolean leftJustify);
[id(53)] boolean CanUndo();
[id(54)] boolean Undo();
[id(55)] boolean CanRedo();
[id(56)] boolean Redo();
[id(57)] boolean CopyFromClipboard();
[id(58)] boolean InitFromAdo(IDispatch* lpAdoRecordSet, long colWidth, boolean leftJustify);
[id(59)] boolean InitFromAdoProportionateColumn(IDispatch* lpAdoRecordSet, long proportion, boolean leftJustify);
[id(60)] boolean SetCellUserData(long row, long col, long userData);
[id(61)] boolean InitFromCsv(BSTR file, long colWidth, boolean leftJustify);
[id(62)] boolean InitFromCsvProportionateColumn(BSTR file, long proportion, boolean leftJustify);
[id(63)] boolean SerializeIntoString(BSTR* prprties, BSTR* data);
[id(64)] boolean DeserializeFromString(BSTR prprties, BSTR data);
[id(65)] boolean InitFromArrayProportionateCol(VARIANT safeArray, long proportion, boolean leftJustify, boolean firstRowHasColumnNames
[id(66)] boolean InitFromArray(VARIANT safeArray, long colWidth, boolean leftJustify, boolean firstRowHasColumnNames);
[id(67)] boolean SetFromArray(VARIANT safeArray, long startRowOffset);
[id(68)] long GetSelectedRow();
[id(69)] long GetSelectedColumn();
[id(70)] boolean CopyColumnFromClipboard(long column);
[id(71)] boolean CopyColumnToClipboard(long column);
[id(72)] boolean DeleteRow(long row);
[id(73)] boolean InsertRow(long row);
[id(74)] boolean StaticDraw(OLE_HANDLE hdc, long top, long left, long bottom, long right);
[id(75)] void EnablePrintPreview(long mode);
[id(76)] void EnableMultiRowSelection(boolean mode);
[id(77)] void InitEnumSelectedRows();
[id(78)] long EnumNextSelectedRow();
[id(79)] boolean CopySelectedRowsToClipboard();
[id(80)] boolean CopyToSelectedRowsFromClipboard();
[id(81)] boolean EnableUndo(BOOL mode);
[id(82)] boolean SetCellList(long row, long col, BSTR listItems, boolean canEditList);
[id(83)] boolean SetCellCheckbox(long row, long col, boolean initialState, BSTR label);
[id(84)] long GetChecboxState(long row, long col);
[id(85)] void EnableDlgTabEntry(boolean mode);
[id(87)] boolean SetCellListSelection(long row, long col, BSTR textItem);
[id(88)] boolean Sort(long column);
[id(89)] boolean SetMultiSelectedRow(long row, boolean selectIt);
[id(90)] void GetCurrentCell(long* row, long* col);
[id(91)] boolean SetColumnWidth(long col, long width);
[id(92)] long GetColumnWidth(long col);
[id(93)] boolean CopyCurrentCellFromClipboard();
[id(94)] void EnableDefaultRBPopup(boolean mode);
[id(95)] BSTR GetHeading(long col);
[id(96)] void LockColumnWidth(long col, boolean locked);
[id(97)] boolean SetColumnName(long col, BSTR name);
[id(98)] boolean StaticDrawEx(OLE_HANDLE hdc, long top, long left, long bottom, long right, long start, long end);
[id(99)] boolean SetCellBoldFont(long row, long col, boolean mode);
[id(100)]long GetCellUserData(long row, long col);
[id(101)] boolean InsertColumn(long pos, BSTR columnName, long width, boolean leftJustify);
[id(102)] boolean DeleteColumn(long col);
[id(103)] void Hide(boolean hideGrid);
[id(104)] void EmphasizeColumnLine(long col, boolean emphasize);
[id(105)] void SetCaretAtEndOnEdit(boolean setAtEnd);
[id(106)] boolean SetCellItalicFont(long row, long col, boolean mode);
[id(107)] boolean SetCellCustomFont(long row, long col, boolean mode);
[id(108)] void SetCustomFontName(long pointSize, BSTR fontName);
[id(109)] void UseTabsOnClipboard(boolean useTabs);
[id(110)] void RedrawHeader();
[id(111)] boolean SetCellButton(long row, long col, BSTR caption);
[id(112)] boolean SetRowColours(long row, long crNormalText, long crEditText, long crNormalBkgd, long crEditBkgd);
[id(114)] void EnableEditPosCorrectionXP(long mode);
[id(113)] boolean SetRowText(long row, BSTR text, short delimiter);
[id(115)] boolean MoveColumn(long moveCol, long position);
[id(116)] BSTR SerializeLogicalColumns();
[id(117)] boolean DeSerializeLogicalColumns(BSTR columnData);
[id(118)] void EnableLogicalColumnMapping(boolean mode);
[id(119)] void EnsureRowIsVisible(long row);
[id(120)] boolean AddPercentageColumn(BSTR columnName, long percentageWidth, long leftJustify);
[id(121)] void AutoInitializeRowsOnCreate(boolean mode);
[id(122)] boolean EnableSpeedOptimizations();
[id(123)] void EnsureColumnIsVisible(long col);
[id(124)] boolean SetFromAdoRecordSet(IDispatch* lpAdoRecordSet);
[id(125)] void Uncreate();

events
[id(1)] void CellBeginEdit(long row, long col, BSTR text, long userData, long* outputIndicator);
[id(2)] void CellChanged(long row, long col, BSTR newText, long userData,long* outputIndicator);
[id(3)] void SelectionChanged(long row, long col);
[id(4)] void RButtonClick(long row, long col, BSTR text, long userData);
[id(5)] void RColumnClick(long col);
[id(6)] void NonEditingCellClick(long row, long col, BSTR text, long userData);
[id(7)] void AutoExpand(long row, long col);
[id(8)] void UserSort(long col, BSTR text1, BSTR text2, long *presult, BOOL *presultIsValid);
[id(9)] void RButtonDblClick(long row, long col, BSTR value, long userData);
[id(10)]void LButtonDblClick(long row, long col, BSTR value, long userData);
[id(11)]void ButtonClick(long row, long col, BSTR caption, long userData);
 


Property, Method  and Event Description

Properties

long GetDfltBkgdColor();
void SetDfltBkgdColor(long nNewValue);
long GetDfltTextColor();
void SetDfltTextColor(long nNewValue);
long GetEditBkgdColor();
void SetEditBkgdColor(long nNewValue);
long GetEditTextColor();
void SetEditTextColor(long nNewValue);
long GetGridLineColor();
void SetGridLineColor(long nNewValue);
long GetSelectionColor();
void SetSelectionColor(long nNewValue);
long GetUnusedSpaceColor();
void SetUnusedSpaceColor(long nNewValue);
These methods simpley get and set the named colour property. The parameter is an RGB value. NB when setting the selection colour, you cal pass in 0xffffffff and the Systems selection colour (and the systems selected-text colour) will be used.

BOOL GetRowLines();
void SetRowLines(BOOL bNewValue);
BOOL GetColumnLines();
void SetColumnLines(BOOL bNewValue);
Row dividing lines and column dividning lines can be switched on or off, these properties control that behaviour. NB: when on, the colour of the lines can be changed using the GridLineColor property.

BOOL GetIntegerValidation()
void SetIntegerValidation(BOOL bNewValue)
BOOL GetFloatingValidation();
void SetFloatingValidation(BOOL bNewValue);
These properties set or remove  integer or floating point validation for all cells in the grid. The default state is no validation. If you want more complex validation than just ineger or floating point for some or all cells, you can respond to the CellChanged event, and cause the change to be rejected if invalid by setting the input parameter to the event, *outputIndicator, to 0.

BOOL GetNoColumnZeroDrag();
void SetNoColumnZeroDrag(BOOL bNewValue);
This property enables you to lock column zero in place, other columns can be re-arranged (draged to a different location in the grid) but column zero can't. This is useful if column zero is acting as a row 'header'

BOOL GetNoColumnZeroEdit();
void SetNoColumnZeroEdit(BOOL bNewValue);
This property  can be used to prevent the editing of column zero, even when the rest of the grid is editable. You might want to prevent column zero from being edited if it is displaying 'row headings'.

BOOL GetColumnZero3DEffect();
void SetColumnZero3DEffect(BOOL bNewValue);
This property adds a 3D effect to column zero, making it look rather like the column headings.

BOOL GetColumnZeroClickFeedback();
void SetColumnZeroClickFeedback(BOOL bNewValue);
Setting click feedback on column zero only has any effect when its 3D effect property is set, then when the row is selected, column zero looks to be clicked in

BOOL GetMultiLineHdr();
void SetMultiLineHdr(BOOL bNewValue);
This property controls multiline header mode. A multi line header is fixed at 3 lines, with one word per line.

BOOL GetBoldHdr();
void SetBoldHdr(BOOL bNewValue);
This property enables the header to be displayed using a bold font.

BOOL GetSortingOnColumnClick();
void SetSortingOnColumnClick(BOOL bNewValue);
This property enables columns to be sorted by clicking them

BOOL GetColumnDragEnabled();
void SetColumnDragEnabled(BOOL bNewValue);
This property allows you to switch on or off the column-drag functionality. This functionality allows columns to be repositioned in the grid by the user. NB: column zero can be locked in place by the NoColumnZeroDrag property, even when the rest of the columns can be draged. See the MoveColumn method for moe information about column drag and drop

BOOL GetEnableColumnSelection();
void SetEnableColumnSelection(BOOL bNewValue);
This property enables column selection, a selected column is displayed using the SelectionColor property.

BOOL GetSelectionFromHdrOnly();
void SetSelectionFromHdrOnly(BOOL bNewValue);
If columns are selectable, this property determins if they can be selected only by clicking the header, or by clicking anywhere in the column

BOOL GetReadOnly();
void SetReadOnly(BOOL bNewValue);
This property controls whether or not the grid can be edited.

BOOL GetMaintainROCurrentCellMark();
void SetMaintainROCurrentCellMark(BOOL bNewValue);
If a grid is editable, the current cell is displayed in the edit colours. If the grid is not editable, the current cell is not displayed in different colours unless this property is TRUE.

BOOL GetEnableRowSelection();
void SetEnableRowSelection(BOOL bNewValue);
If this property is true, when a row is clicked it is 'selected' and displayed in using the SelectionColor property.

BOOL GetSelectTextOnEdit();
void SetSelectTextOnEdit(BOOL bNewValue);
If this property is set, when a cell is entered for editing, the entire text is 'selected' within the edit control.

BOOL GetEditHScroll();
void SetEditHScroll(BOOL bNewValue);
If this property is set, text being edited will automatcally scroll horizontally, when you try to type beyond the borders of the cell.  By default, this property is FALSE.

BOOL GetAutoAddRow();
void SetAutoAddRow(BOOL bNewValue);
If this property is set, and the grid is editable, hitting RETURN on the last row will automatically add a new row and fire the AutoExpand event, during which you should set initial values for the cells of the newly added row. By default, this property is FALSE.

BOOL GetNoHdr();
void SetNoHdr(BOOL bNewValue);
This property allows you to remove the header from the grid.

BOOL GetNoResizeColumns();
void SetNoResizeColumns(BOOL bNewValue);
This property allows you to prevent the user from resizing columns by clicking on the lines that divide them in the header.

BOOL GetNoEscapeEdit();
void SetNoEscapeEdit(BOOL bNewValue);
By default, if the user presses ESCAPE while editing, the edit is aborted, and the original text is restored. This property can switch that behaviour on or off.

BOOL GetSelectOnEditMode()
void SetSelectOnEditMode(BOOL bNewValue)
When SelectOnEdit is on, programmatic editing of a cell also selects the row and column that contain the cell.

void SetCaretAtEndOnEdit(BOOL setAtEnd)
This can be used as an alternative to setting selection on edit, the caret will be set to the end of the text, otherwise, the caret is at the start of the text. Both of these methods apply to the whole grid.

BOOL GetNavigationOnlyByClick();
void SetNavigationOnlyByClick(BOOL bNewValue);
These property disables the use of arrow/tab keys for navigation, requiring a Mouse click to navigate. The default is to allow tab/arrow-key navigation.
 

Methods

Grid Initialization

BOOL AddColumn(LPCTSTR columnName, long width, BOOL leftJustify);
Before you can use a SimpleGrid control, you must add all its columns. This method allows you to do that, specifying the width and justification of the column.(NB: the width is in pixels).

BOOL AddProportionateColumn(LPCTSTR columnName, long proportionateWidth, BOOL leftJustify);
This is an alternative way of adding columns. It adds a column who's width is a certain proportion of the available display width. The proportionateWidth parameter is an integer representing the proportion, e.g. 2 represents half the available width, 4 represents a quarter of the available width. You cam add as many columns as you want using this method, regardless of the value of proportionateWidth, i.e. if you add 8 columns with proportionateWidth=4, then the control will have a horizontal scroll bar, and 4 columns will be visible at any one time.The main purpose of this method is, however, to add equally spaced columns, in which case the proportionateWidth parameter should be the same as the number of columns you intend to add.

BOOL AddPercentageColumn(LPCTSTR columnName, long percentageWidth, BOOL leftJustify); 
You can use this method to add columns that take up a particular percentage of the grid width. I.e. you could add a column that is 75% and another that is 25%. You could even add a 3rd that is, say 33%, in which case, the grid would have a scroll bar. This gives you much more control than the AddProportionateColumn() method. The percentageWidth parameter is an integer value that represents the percentage of the grid that will be used by the column. This could be greater than 100 if you wanted a realy wide column with a scroll bar, but probably you don't want that.

BOOL AddRows(long numberOfRows);
After you have added columns, you can add rows. You can insert and delete rows at any time.

BOOL InitFromAdo(LPDISPATCH lpAdoRecordSet, long colWidth, BOOL leftJustify);
BOOL InitFromAdoProportionateColumn(LPDISPATCH lpAdoRecordSet, long proportion, BOOL leftJustify);
These 2 methods initialize a grid to display the data held in an ADO record set. These methods create the grid with equal width columns, either using a proportion or absolute value. The number of columns, the column names and the number of rows are all  taken from the Record Set.

BOOL InitFromCsv(LPCTSTR file, long colWidth, BOOL leftJustify);
BOOL InitFromCsvProportionateColumn(LPCTSTR file, long proportion, BOOL leftJustify);
These 2 methods initialize a grid to display the data held in an CSV file. These methods create the grid with equal width columns, either using a proportion or absolute value. The number of columns, the column names and the number of rows are all  taken from the CSV file.

BOOL InitFromArray(const VARIANT& safeArray, long colWidth, BOOL leftJustify, BOOL firstRowHasColNames);
BOOL InitFromArrayProportionateCol(const VARIANT& safeArray, long proportion, BOOL leftJustify, BOOL firstRowHasColNames);
These 2 methods initialize a grid to display the data held in an array. These methods create the grid with equal width columns, either using a proportion or absolute value. If  firstRowHasColNames=true, the number of columns and the column names as well as the number of rows are all  taken from the array. If firstRowHasColNames=false, either  AddColumn() or  AddProportionateColumn() must already have been called to define the columns - in such a case, any extra columns in the array are ignored.

void Uncreate()
You can call this method to put the grid into an ‘uncreated’ state, i.e. the same state as when the control has just been inserted. You can then run the AddColumn, AddPropotionateColumn or InitFrom…() methods, just as you do when you initialize the grid for the first time.

BOOL SetFromArray(const VARIANT FAR& safeArray, long startRowOffset);
This method enables an array to be copied into the grid, beginning at a particular row in the grid (the copy starts from row 0 in the array and continues until all rows have been copied, or the end of the grid is reached. The grid never gets extended by this method

BOOL SetFromAdoRecordSet(IDispatch* lpAdoRecordSet);
You can use this method to set rows of an existing grid from an ADO Recordset. If the Recordset is larger than the grid it will be truncated when applied to the grid, the grid never gets extended by this method

void EnableMultiRowSelection(boolean mode);
Call this method to allow multiple rows to be selected.
When Multi-Row sekectilon is enabled, the methods InitEnumSelectedRows() and EnumNextSelectedRow() allows all selected rows to be enumerated

void InitEnumSelectedRows();
Call this method to initialize the enumeration of the selected rows.

long EnumNextSelectedRow();
Call this method to get the index of the next selected row. Whan no more rows are available, -1 is returned.

void EnableDlgTabEntry(BOOL mode);
This method allows TABs to be processed by the grid when it is placed on a dialog box, without this, the TABs will move focus to the next control on the dialog. As an alternative to use this method, you could override your dialolg classes PreTranslateMessage(MSG* pMsg) method - the ColumnCal sample demonstrates  both of these techniques.

BOOL EnableSpeedOptimizations()
This method is intended for use with large grids. It must be called before any columns or rows have been added, otherwise it will return FALSE and have no effect. If you have a large number of cells, more than 10,000, say, initialization of the grid is noticeably slow, however other operations, such as re-painting are not badly affected by such a large size, as it is unlikely all the cells will be displaying at the same time. If you call this method, the speed of initialisation is much improved. Indeed there is an all-round speed improvement on all grid operations, however this is less noticeable in other situations. So, why not always use this method? Well, there is a price to pay for the speed improvement. If you call this method, column drag&drop is disabled and column sort operations are also disabled (although you could sort the data yourself and re-apply it to the grid). The default mode of the grid is to have speed optimizations switched off. Note: you will also notice a slight speed improvement if  you use the SetFromArray() method rather than call SetCellText() in a loop.

AutoInitializeRowsOnCreate(BOOL mode)
This is another way to improve the speed of grid initialisation, it can be used in conjuction with EnableSpeedOptimizations() or separately, in either case it will result in faster initialisation. If you create your grid then immediately fill all cells with data, this method will improved your initialisation speed. Normally, when the rid is created, each cell is initialized with ‘empty’ data automatically, but if you intended to set all cells yourself, you can call this method to prevent automatic initialisation, thus making initialisation twice as fast. NB: this is realy only noticeable when you have a large number of cells, over 10,000, say. The default mode of the grid is automatically initialize rows on creation. Any un-initialized cells are displayed in light grey until they are initilzed by a call to SetCellTex() or similar method.

void SetDropListHeight(long height);
This method can be used to set the height of the drop-down list when a cell contains a list. The list-height is set for the grid as a whole and not on a per-cell basis. If height is -1, the list height is calculated separately for each list so that the drop-down list is large enough for all the items. If height is 0, the default height is used.
If the height is any other -ve number, the absolute value of the height specifies a maximum allowable height, subject to this limit the optimum height is calculated and used. Note the height refers to the number of items displayed in the drop-down list.

Cell Operations

BOOL SetCellText(long row, long col, LPCTSTR text);
Set the text of the cell. Rows and columns are numbered from 0.

BOOL SetCellList(long row, long col, LPCTSTR listItems, boolean canEditList);
This method can be used as an alternative to SetCellText(). Using this method defines a list of possible values that the user can chose from when editing the cell. If  canEditList is TRUE, the user can type values that are not in the list into the cell. The listItems parameter is a sem-colon separated list of items. The first item in the list is the one that is currently selected, if you want to specify a different item to be selected, use the following pattern for listItems, "@CCC;AAA;BBB;CCC;DDD;", here CCC will be selected, the list will contain items "AAA;BBB;CCC;DDD;"

BOOL SetCellListSelection(long row, long col, LPCTSTR textItem)
This method can be used to change the current selection of a cell that contains a list. If the list is not editable, textItem must exist within the list, otherwise, it need not.

BOOL SetCellCheckbox(long row, long col, boolean initialState, BSTR label)
This method will set the contents of a cell to a checkbox and a label.

BOOL SetCellButton(long row, long col, LPCTSTR caption);
Define a cell to contain a button.

BOOL SetRowText(long row, LPCTSTR text, short delimiter);
This method uses the specified text to fill as many cells in the row as possible. The text should contain groups of characters delimited by delimiter. The delimiter parameter is the ASCII value of the delimiter character, 2 special values are accepted for convenience, 0 specifies a comma delimiter and –1 specifies a tab delimiter (you can, of course, still use the ASCII values of comma and tab). NB the ASCII value of a space is 32.

BSTR GetCellText(long row, long col);
Get the text of the cell, cells are always treated as containing strings data, even if they have integer or floating point validation set.
If GetCellText() is called for a cell containing a Checkbox, a flag-indicator is returned, followed by a colon and then the label of the Checkbox, e.g. "0:label text". If GetCellText() is called for a cell containing a List Box, the currently selected  text is returned, not the entire contents of the list.

long GetChecboxState(long row, long col)
If the cell at row, col contains a Checkbox, 1 or 0 is returned indicating its state. If the cell does not contain a Checkbox, -1 is returned

BOOL SetCellUserData(long row, long col, long userData);
This method allows you to associate a specific value (user data) to a cell.

long GetCellUserData(long row, long col);
Get the cell's user data, 0 is returned if no user data has been set.

BOOL EditCell(long row, long col);
This method starts  an edit operation on the specified cell.

BOOL SetCellBoldFont(long row, long col, boolean mode);
Set the font to bold for the cell.

BOOL SetCellItalicFont(long row, long col, boolean mode);
Set the font to italic for the cell.

BOOL SetCellCustomFont(long row, long col, boolean mode);
Set the font to 'custom'  for the cell.

void void SetCustomFontName(long fontSize, BSTR fontName);
Define the 'custom font' for the grid - this can be applied to individual  cells using SetCellCustomFont() method. E.G.SetCustomFontName(80, "Times New Roman"). NB: the fontSize parameter is the font height in tenths of a point (For instance, pass 120 to request a 12-point font.)

BOOL SetCellColours(long row, long col, long crNormalBkgd, long crNormalText, long crEditBkgd, long crEditText);
Set the background and foreground  for the cell in normal and editing display mode.

BOOL SetRowColours(long row, long crNormalText, long crEditText, long crNormalBkgd, long crEditBkgd);
This method  can be used for convenience if you want to set the colours of an entire row.

Row/Column Operations

long GetRowCount();
Get the number of rows

long GetColumnCount();
Get the number of rows

long GetSelectedRow();
Get the row index of the selected row, -1 is returned if no row is selected. If multi-row selection is enabled, this method returns the first selected row.

long GetSelectedColumn();
Get the row index of the selected column, -1 is returned if no column is selected.

BOOL SetSelectedRow(long row);
Select the row specified (row indexes start at 0).

BOOL SetSelectedColumn(long col);
Select the row specified (row indexes start at 0). The previously selected row will be deselected.

void GetCurrentCell(long* row, long* col);
Get the current cell position, regardless of selction states or editing states.

BOOL SetColumnWidth(long col, long width);
long GetColumnWidth(long col);
Set/Get the width of an individual column - only use this method after the grid has been created. (NB: the width is in pixels).

void LockColumnWidth(long col, boolean locked);
Lock the column width at the current value, the user will not be able to resize the column - use full if you want to hide a column - set it's wisth to zero then lock it. to lock all columns, use the single method SetNoResizeColumns(TRUE).

BOOL SetColumnName(long col, BSTR name);
This method can be used to change the name (heading) of a column after the grid has been created.

BOOL SetMultiSelectedRow(long row, boolean selectIt);
This method can be used (if the grid permits multiple selection) to select multiple rows, if selectIt is FALSE, the row is deselected.

BOOL DeleteRow(long row);
Delete the row specified .

BOOL InsertRow(long row);
Insert a row at the specified location.

BOOL InsertColumn(long pos, BSTR columnName, long width, boolean leftJustify);
Insert a column at position pos

BOOL DeleteColumn(long col);
Delete the specified column, NB column 0 cannot be deleted

BOOL Sort(long column);
Sort the grid on the column - this is just as if the user has clicked the column.

BSTR GetHeading(long col);
Get the title of the specified column.

void EmphasizeColumnLine(long col, boolean emphasize);
If you are using grid lines, this will ‘emphasize’ the line at a particular position using dark grey. If mode is FALSE, the line is set to the normal (default) colour. If col is –1 and mode is FALSE, all columns are set to un-emphasized mode.

BOOL MoveColumn(long moveCol, long position)
This method gives you programmatic control over column-drag-drop facility that the user can perform (if ColumnDragEnabled is TRUE). NB: this method will still work even if ColumnDragEnabled is FALSE. Once a column has been moved using this method, or by the user dragging and dropping, the column maintains its original logical position, so that methods like SetCellText don’t need to keep track of how the user drags and drops columns, if, say column1 is ‘bank account’, even after MoveColumn (1, 3) has been called, your program still sets the text in column1 to change the ‘bank account’ column.

If you want to save and restore the column ordering a user has applied by dragging and dropping, see SerializeLogicalColumns() and DeSerializeLogicalColumns()below.

void EnsureRowIsVisible(long row);
You can use this method to ensure that a particular row is visible, if it isn't the grid will scroll it into view.

void EnsureColumnIsVisible(long col);
You can use this method to ensure that a particular column is visible, if it isn't the grid will scroll it into view, placing it at the far left of the grid.

Clipboard Operations

void UseTabsOnClipboard(boolean useTabs);
Use this method to specify  that columns are separated with TABs on the clipboard, otherwise they are separated with commas. (The default is to use comma separators).

BOOL CopyGridToClipboard();
Copy the entire grid to the clipboard, including header.

BOOL CopyColumnToClipboard(long column);
Copy the named column to the clipboard, including header.

BOOL CopyCurrentCellToClipboard();
Copy the current cell to the clipboard.

BOOL CopyCurrentCellFromClipboard();  /* paste cell */
Copy the current cell from the clipboard, i.e. paste from the clipboard into the current cell.

BOOL CopyFromClipboard(); /* paste whole grid*/
Copy (i.e. paste) data from the clipboard into the grid. Column headers are not affected.

BOOL CopyColumnFromClipboard(long column); /* paste a column */
Copy (i.e. paste) data from the clipboard into the specified grid column. Column headers are not affected.

BOOL CopySelectedRowsToClipboard(); 
Copy the selected row(s) to the clipboard

BOOL CopyToSelectedRowsFromClipboard(); /* paste rows */
paste the contents of the clipboard into the selected rows.

NB: when editing Ctl-C(copy) Ctl-V(patse) Ctl-X(cut) are all available.

When copying more than a single cell, cells are separated with commas on the clipboard, and the comma is used as a delimiter when pasting  into more than a single cell. If  void UseTabsOnClipboard(boolean useTabs) is called with TRUE, the TAB character is used as a delimiter rather than a comma when copying to the clipboard.

Undo/Redo

BOOL CanUndo();
Returns TRUE if it possible to undo an operation. All edit operations can be undone and redone. Clipboard operations cannot be undone. Row inserts and deletes cannot be undone.

BOOL Undo();
Undo the last edit operations.

BOOL CanRedo();
Returns TRUE if it possible to redo an operation.

BOOL Redo();
Undo the last edit operations.

void EnableUndo(BOOL mode);
Call this method to enable or dissable the Undo/Redo functionality. Undo/Redo is, by default, enabled,

General Operations

void Redraw();
Repaint the grid.

void Resize(long cx, long cy);
Resize the grid

void SetFocus();
Set the focus to the grid.

BOOL SerializeIntoString(BSTR FAR* properties, BSTR FAR* data);
Serialize the grid's data into a string. This is just for interest and possible convenience - the grid serializes itself in the standard ways expected by ActiveX controls. you should not need to use this method, but rather rely on the serializing capabilities of the container, that sill call the grids standard interfaces to serialize it.

BOOL DeserializeFromString(LPCTSTR properties, LPCTSTR data);
Deserialize the grid's data from a string.

BSTR SerializeLogicalColumns()
Call this method to serialize the logical column order into a string. You do not need to understand the contents of the string, just save it and use it in DeSerializeLogicalColumns() when the application starts in the future. If the user has not performed any column drag/drop, this method will return an empty string, which can safely be passed into DeSerializeLogicalColumns().

BOOL DeSerializeLogicalColumns(LPCTSTR columnData)
You can call this method to restore the logical column mappings created by a users drag/drop action or by use of the MoveColumn() method Typically you will use the grids Serialize/DeSerialze methods to save the data, and then call this method to restore the logical column mappings. If you write your own code to save and restore the grid, make sure you call EnableLogicalColumnMapping(FALSE) before you wite-out your grid so that the columns are saved in absolute rather than logical postion order - this method needs the grid to be in absolute column order before logical column mappings can be applied.

void EnableLogicalColumnMapping(BOOL mode)
After a users column drag/drop or a call to MoveColumn() the moved columns are still addressed by their original position (their logical position). If you want to address the columns true (absolute) position  for any reason (e.g. saving the grid’s data), you can call this method to disable logical column mapping in all the Set/Get methods that take a column position. NB logical column mapping is always TRUE by default

void EnableDefaultRBPopup(BOOL mode);
If this method is not called, when a cell is being edited, a default Right-Hand button popup menu is displayed - note this is only the case when a cell is actually being edited - and the program will not get a Right-Hand button click notification event. If this method is called, no default popup is created and a Right-Hand button click notification event is fired. (Also note: if the edit control processes the Right Button click, it will only allow  copying if there is any text selected in the edit control, you can arrange for all the text to be selected when you click on a cell, see the SelectOnEditMode method)

void Hide(boolean hideGrid);
Hide and  re-show the grid - this improves the look and redraw-speed if you are doing multiple grid-column re-sizing in code.

void EnableEditPosCorrectionXP(long mode)
It has been noticed that under WindowsXP the edit control used for editing cells has slightly different presentation properties. The grid will automatically detect WindowsXP and correct for this by positioning the edit control slightly differently. You can switch this behaviour on or off by calling this method with the paaremetr 0 (off, regardless of operating system) 1(on, regardless of operating system) and –1(on if WindowsXP, off otherwise, this is the default)
 

Special Printing Operations

BOOL StaticDraw(OLE_HANDLE hdc, long top, long left, long bottom, long right);
Render the grid into the specified device context, with the specified size and position. This is implemented to enable (relatively) easy printing. (you could equally well get the control's IViewObject interface and call the IViewObject::Draw() method if you wish).

BOOL StaticDrawEx(OLE_HANDLE hdc, long top, long left, long bottom, long right, long start, long end);
This method allows starting and ending rows for the print to be specified.

void EnablePrintPreview(long mode);
You will find that if you contain a grid in a standard MFC container, print-preview doesn't work (the reason for this is deep within the implementation of MFC itself). Calling this method allows print-preview to work.
 

Events

void CellBeginEdit(long row, long col, BSTR text, long userData, long* outputIndicator);
This event  is fired just before editing begins. If *outputIndicator is set to 0, then editing will not be permitted. You can use this event to implement a grid that contains some editable cells and some read only cells. This event is also fired before a cell-button responds to a press, and is *outputIndicator is 0, the button will not respond to the click. 

void CellChanged(long row, long col, BSTR newText, long userData,long* outputIndicator);
This event  is fired just after editing completes. If *outputIndicator is set to 0, then the change will be discarded. You can use this event to implement custom cell validation. Note: if the cell contains a check-box, this event is fired when the check-box is clicked, you don’t have to leave the cell first.

void SelectionChanged(long row, long col);
This event is fired when either a row or column selection changes. It is only fired if selection is enabled.

void RButtonClick(long row, long col, BSTR text, long userData);
This event is fired when the right button is clicked on a cell. It can be used to implement custom behaviour, such as a pop-up context menu.
Note: No LButonClick even exists, this is because a Right Button Click starts editing, and so CellBeginEdit is fired when a cell is right clicked. However, if the grid is read-only NonEditingCellClick  is fired instead of CellBeginEdit..

void RColumnClick(long col);
This event is fired when the right button is clicked on a column heading. It can be used to implement custom behaviour, such as a pop-up context menu.

void NonEditingCellClick(long row, long col, BSTR text, long userData);
This even is fired when a read-only cell is clicked.

void AutoExpand(long row, long col);
This event is fired if AutoExpand is enabled. If you enable AutoExpand, the grid will automatically add a row when Carriage Return is pressed on the last row. When this event is fired, you must set valid data into the newly added row.

void UserSort(long col, BSTR text1, BSTR text2, long *presult, BOOL*pResultIsValid);
This event is fired when columns are being sorted. If it is not implemented or if *pResultIsValid is set to FALSE, default sorting takes place. If you implement this event, you must set *presult to a negative value if the first item should precede the second, a positive value if the first item should follow the second, or zero if the two items are equivalent

NOTE: unless you have very basic sorting requirements you will need to implement this event handler. By default all columns are treated as alphabetic when sorted, even if the grid contains only numbers, default sorting will sort alphabetically not numerically. (if you have set IntegerValudation or FloatValidation for the grid, or for the individual cell, then the grid uses this information and performs an appropriate numeric sort )

void RButtonDblClick(long row, long col, BSTR value, long userData);
This event is fired normally when it occurs in an inactive cell. If the cell is active, it will only be fired if EnableDefaultRBPopup(FALSE) has been called. If EnableDefaultRBPopup is TRUE, the edit controls default Right-Button popup is displayed when the right button is clicked and the double click is lost.

void LButtonDblClick(long row, long col, BSTR value, long userData);
This event is fired normally if the grid is read-only or if you catch OnCellBeginEdit() for a specific cell and set *outputIndicator = 1. If you don’t do this, the event will not be fired when it occurs in an inactive cell – this is because the first click cause the cell to become active and display an edit control, the 2nd click then goes to a different window than the first, and so the double click is lost. Once a cell is active, i.e. being edited, double click events will be fired normally.

You can arrange for double-click events to always be caught, and initiate editing of a cell is you wish, the technique for doing this is as follows…

void OnCellBeginEdit(long row, long col, LPCTSTR text, long userData, long FAR* outputIndicator) 
{
    if( m_editOK )
        *outputIndicator = 1;
    else
        *outputIndicator = 0;
}

void OnLButtonDblClick(long row, long col, LPCTSTR value, long userData) 
{
    m_editOK =  true;
    m_grid.EditCell(row, col);
    m_editOK = false;
}
void ButtonClick(long row, long col, BSTR caption, long userData);
This event is fired only when a cell-button is clicked.



 

The Property Page

 
The  property page sets the various properties of the 
control. Most properties are boolean values, except the colours, which are RGB values, and are set by Colour 
Dialogs when the buttons are pressed.



 

Samples

Several sample programs with full source code are included. The samples are mostly MFC applications created with Microsoft's Visual C++, and one sample is written in Microsoft's Visual Basic.

SimpleGridSample

This is an MFC Dialog Based sample. It demonstrates the major features of the grid, including initialization from ADO Record Sets, CSV files and arrays.
A separate dialog allows you to set various properties that are then applied when the grid is created. Most of the features of the grid can be changed, including making the second column be editable through list boxes.
 
How to add the grid to an MFC dialog
  1. Create an MFC project with the ActiveX control box checked in the Wizard dialogs
  2. Create a class for the Grid OCX

  3. take the   Project/Add To Project/Components and Controls  menu option and choose  Registered ActiveX Control, then select Simple Grid Control and click [INSERT] then close the dialog -A wrapper class will be generated, CSimpleGrid. 
  4. Add the Grid OCX to a dialog  - an OCX should automatically appear on your Controls tool bar, drag  this onto the dialog in the normal way
  5. Add a CSimpleGrid variable to your dialog - hold down SHIFT and double click in the SimpleGrid ocx, if you haven't already created a class for the Dialog box you will be asked to do so now - do that and then repeat the double click. You will be given the chance to add a CSimpleGrid object to your dialog, which in this samples called m_grid. 
  6. Initialize your grid in the OnInitDialog() member of the dialog that contains your grid 
  7. To add an event handler, select the grid-ocx in the dialog editor by single-clicking it. Then press CTL-W to get the class wizard. You should see IDC_SIMPLEGRIDCTRL1 hilighted in the left hand pane, with the events in the right-hand pane

SimpleGridSample2

This sample shows how to add a grid control to an MFC OLE-container Document/View application, and in particular, how to handle events.
 
  • How to add the Grid to an MFC OLE Container
    1. Add a SimpleGrid Control wrapper class

    2. Press CTL-W to get the class wizard, press the [Add a Class] button and take the 'from a type lib' option, find the SimpleGrid type lib, and select all classes in it. NB: this differs from the way we add the control when dealing with a Dialog container. 
    3. Creating a SimpleGrid Control on the screen

    4. This is quite easy and is done in   CSimpleGridSample2View::OnEditInsertGrid() 
    5. Add Event Handlers

    6. This is slightly more complex, and uses 3 custom methods in CSimpleGridSample2CntrItem.cpp, EnableEventNotification(),  AdviseEventSink();  UnadviseEventSink(); and a support class, GridEventSink  (see GridEventSink.h)

    This sample also includes support for printing
     

    ColumnCalc

    This sample demonstrates formatting (4 decimal places is enforced) and automatic validation. Rows and Columns are also added at runtime. This is also a C++ MFC application. This demo also includes a right button context menu that can delete and add rows, and copy and paste columns
     
    This is just a standard MFC Dialog-Based app with ActiveX support.

    A SimpleGrid is added to the dialog box in the same way as in
    the SimpleGridSample

    The GRID is initialized in OnInitDialog

    Four main methods have been added to manipulate the grid

     void CColumnCalcDlg::AddColumn(LPCTSTR name)
     void CColumnCalcDlg::AddRow()
     void CColumnCalcDlg::SumColumns(int cmax)
     void CColumnCalcDlg::FixTotalRowColour()

    And 2 event handlers have been added to ensure the text entered
    is formatted correctly and to prevent the editing of the Totals row

      void CColumnCalcDlg::OnCellBeginEditSimplegridctrl1(...) 
     void CColumnCalcDlg::OnCellChangedSimplegridctrl1(...) 

    Event handlers have also been added to display context menus when the Right Mouse Button is clicked
    void CColumnCalcDlg::OnRButtonClickSimplegridctrl1()
    void CColumnCalcDlg::OnRColumnClickSimplegridctrl1()
    NOTE: using a Carriage Return <CR> will move the grid position down one line. The trick to get this to work, was to make the Calculate button (rather than the Close button) the default.

    The SimpleGrid supports Automatic addition of a row if the user hits return and would go beyond the last row [ see the SetAutoRowAdd() property and the OnAutoExpand() event ]. However, this is not useful in this application as the last row is not editable, so hitting <CR> will never trigger this behaviour!

    This sample also shows how to arrange for the grid to receive TABs when contained by a dialog box.
     

    ColumnCalc2

    This final MFC sample demonstrates automatic integer validation. Its main point is, however, automatic row addition when <CR> is hit on the last row. The application comprises 2 grids, the 2nd has no header, and is used to display the total.
     
    The main difference between this and ColmnCalc is that the total-row is a separate headerless grid, and all  priorities are set using the  property page rather than using method calls in OnInitDialog().

    Because the total row is a separate grid, the main entry grid allows sorting - this is disabled in ColumnCalc since if it were allowed, the total-row would move!

    Because the bottom row of the main grid is  editable, Auto Expand is available, and has been set through the property page. For AutoExpand to work correctly, you must set the newly added row in the OnAutoExpandSimplegridctrl1(...) event handler.

    The problem with this approach is that the total grid, being independent of the main grid, will not scroll horizontally with the main grid, nor will it's columns move or resize with the main grid - for this reason, the columns cannot be resized or moved, nor can a horizontal scroll-bar be allowed.

    For simplicity, this sample is restricted to integers. ColumnCalc allows floating point entry. ColumnCalc2 does not have the ability to Cut/Paste Undo/Redo - this is just to keep the sample simple - to see how to use those functions, see ColumnCalc above.


     

    SimpleGridSampleVB

    This is the sole VB sample. and demonstrates the basic use of the grid, as well as automatic expansion when <CR> is pressed on the bottom row.

    NB: the copy and paste buttons in this sample apply to the whole grid and not just the current cell – this is just the way the sample was written, the buttons could have been made to apply to the current cell or current row.
     

    ActiveX Test Container Saved State

    This is not a sample as such, but rather a saved stated of the Visual C++ ActiveX test container. See the file Samples\SimpleGrid.tcs if you wish to try this out.


    Using List Boxes

    If, instead of calling SetCellText(), you call SetCellList(), the cell will contain a list of possibe choices, which are displayed to the user by a drop-down list box. If the canEditList parameter is TRUE, the list box allows the user to enter items that are not currently in the list by typing them in.

    There are currently 2 restrictions with the use of list boxes...

    1. The  user-defined colours are  not applied to the list box.
    2. If the canEditList parameter is TRUE, the TAB key will not allow navigation passed a list box.
    These restrictions will be lifted in future versions of the control.

    The size of the dropdown list-box can be set using the method SetDropListHeight().


    Using Checkboxes

    Using check boxes is very easy, just use the SetCellCheckbox() method instead of calling  SetCellText(), and use GetChecboxState() to determine  the state of the Checkbox. You may also use GetCellText()on a Checkbox cell, this will return the 'label' of the cell preceded by a colon separated indicator of the checkbox's state, 1=on(i.e. checked) and 0=off.


    Using Buttons

    If, instead of SetCellText(), SetCellButton() is called, the cell will contain a button. The  ButtonClick() event is fired when the button is clicked. The event  CellBeginEdit() is fired before the button responds to the click, and if *outputIndicator is set to 0, the button will not respond to a click, and the ButtonClick() event is not fired. If the users presses the space-bar on the button, the button is ‘clicked’.


    Copy and Paste

    When copying and pasting a grid without Checkboxes and Lists Boxes, copy and paste works just as you would expect. When copying a cell containing a List Box, the currently selected item from the list is copied, the list items are not copied. When copying a cell containing a Checkbox, a flag-indication, a colon and the Checkbox text are copied, e.g. "1:checkbox label".

    When pasting into a cell containing a List Box, the same format as used when setting the contents of the List Box Cell is used, i.e. a semi-colon separated list of items. But, this is NOT the format used when copying a cell containing a List Box - it follows that you can't copy a grid to the clipboard and then paste back into the grid without loss of information if the grid contains List Boxes.

    When pasting into a cell containing a Checkbox, the same format as used when copying the contents of the Checkbox Cell to the clipboard is used, i.e. a flag-indicator, a colon and a string. There is no loss of information if a grid containing a Checkbox is copied to the clipboard and then copied back.

    NB: if a row is added to a grid as a result of copying from the clipboard, the cells added will never contain List Boxes or Checkboxes, regardless of the format off the data.

    Note: columns pasted into the grid must be comma separated.

    If more advanced copy and paste operations are required, they must be implemented by the user.


    Printing A SimpleGrid OCX

    Printing a SimpleGrid control is like priniting any ActiveX control, you obtain the IViewObject interface and call the Draw()method. However, SimpleGrid provides you with an alternative, you can simpley call the StaticDraw() method, passing in a Device Context - this method has been provided to simplify the task of printing. If you have embeded a SimpleGrid in a MFC Document/View OLE-Container, the standard printing mechanism will work, although you will have to call an additional method, EnablePrintPreview(), to allow PrintPreview to work. The sample, SimpleGridSampe2, demonstraites this.



     

    Redistributing The SimpleGrid OCX

    Redistributing a runtime (non-design-time) SimpleGrid is easy. You just distribute the OCX and register it. You may distribute SimpleGrid.ocx with your own programs, you may not, of course, redistribute the full package, and should not divulge your activation key to anyone else.

    Home | FixGateway | AFI/J | SimpleGrid | SBpayroll | SXAzip | InstallScript | DiskUsage/DiskClean | Virtual Desktop Manager | ComBridge | Demos | Purchase