THyperGrid FAQ
Marley Software Pablo Pissanetzky


How do I specify a different popup menu for the fixed cells than the popup menu for the grid?

Assume that PopupMenu1 is used only for the fixed cells and PopupMenu2 is used for the grid. First, turn the AutoPopup property to false for PopupMenu2, then attach an event handler for OnFixedCellClick and one for OnMouseUp. Enter the following code in the two handlers:

procedure TForm1.HyperGrid1FixedCellClick(Sender: TObject; ACol, ARow, HeadingIndex: Integer; Button: TMouseButton; Shift: TShiftState; X,Y: Integer);
var
    P : TPoint;
begin
    if Button = mbRight then
        begin
            P := HyperGrid1.ClientToScreen( Point( X , Y ) );
            PopupMenu1.Popup( P.X , P.Y );
        end;
end;

procedure TForm1.HyperGrid1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X,Y: Integer);
var
    P : TPoint;
begin
    if Button = mbRight then
        begin
            P := HyperGrid1.ClientToScreen( Point( X , Y ) );
            PopupMenu2.Popup( P.X , P.Y );
        end;
end;

 

How do I use the OnGetSuggestion Event?

The OnGetSuggestion event allows you to specify a suggestion based on what the user has typed in a cell. THyperGrid provides an automatic suggestion when a cell has a combo box in it and the column's AutoSuggest property is set to true. Otherwise, you can use this event to provide your own custom suggestion. For example, the code below can be used for a yes/no column. If the user has typed a 'y' or a 'Y' then 'Yes' is suggested, otherwise 'No' is suggested. If you leave the Suggestion string empty, no suggestion will be provided.

procedure TForm1.HyperGrid1GetSuggestion(Sender: TObject; ACol, ARow: Integer; CellText: String; var Suggestion: String);
begin
    if ACol = 2 then
        if UpperCase( CellText ) = 'Y' then
            Suggestion := 'Yes'
        else
            Suggestion := 'No';
end;

 

What is ThgCellList and how can I use it?

ThgCellList is a helper class that allows you to maintain a list of column and row pairs. Think of it as a string list ( which is what it is internally ) but instead of strings, you can add column and row coordinates to it.

var
    CellList : ThgCellList;
begin
    CellList := ThgCellList.Create;
    try
        CellList.Add( 1 , 2 );
        if CellList.Contains( 1 , 2 ) then
            ShowMessage( 'Col 1, Row 2 is in my list !' );
        CellList.Remove( 1 , 2 );
    finally
        CellList.Free;
    end;
end;

ThgCellList supports three methods:

Add, which adds a pair to list. If the pair is already in the list, it will be ignored
Remove, which removes a pair from the list and returns true if it was in the list.
Contains, which returns true if the given pair is in the list.

In the following example, a ThgCellList is used in conjunction with the OnButtonClick and OnGetReadOnly events to toggle a cell's read-only state.

procedure TForm1.HyperGrid1ButtonClick(Sender: TObject; ACol, ARow: Integer);
begin
if not ReadOnlyCells.Remove( ACol , ARow ) then
ReadOnlyCells.Add( ACol , ARow );
end;

procedure TForm1.HyperGrid1GetReadOnly(Sender: TObject; ACol, ARow: Integer; var ReadOnly: Boolean);
begin
    ReadOnly := ReadOnlyCells.Contains( ACol , ARow );
end;

The handler for the button click attempts to remove the given col and row pairs from the list, if they are not in the list, it adds them, which works as a toggle. The OnGetReadOnly event returns true if the given cell is in the list.

 

How do I let the user select an entire column or row by clicking on a fixed cell?

THyperGrid has two methods, SelectEntireColumn and SelectEntireRow that can be used for exactly this purpose. First make sure that goEditing in the grid's options is set to False, ( TStringGrid does not allow range selections when editing is turned on ) and attach the following code to HyperGrid's OnButtonClick event

procedure TForm1.HyperGrid1FixedCellClick(Sender: TObject; ACol, ARow, HeadingIndex: Integer; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
    if HeadingIndex = -1 then
        with HyperGrid1 do
            if ( ACol < FixedCols ) and ( ARow >= FixedRows ) then
                SelectEntireRow( ARow )
            else if ( ACol >= FixedCols ) and ( ARow < FixedRows ) then
                SelectEntireColumn( ACol );
end;

Now, by clicking on any fixed cell, you can select that entire column or row.

 

How do I change the color of a specific cell?

This is very easy to do, but there are a couple of things to note. Before THyperGrid draws a cell, it makes decisions about colors, fonts, alignments, etc based on the properties of the columns and whether cells are selected, focused or fixed. After it has made all the decisions, it executes the OnChangeCellAttributes event, with all the attributes of each cell. This event gives you an opportunity to change the decisions that THyperGrid made about all cell attributes. So, attach a handler for the event that looks like this:

Note: The OnChangeCellAttributes event uses paramters of types that may not be in your uses clause, so add the following units to your uses clause: HgColumn , HgGlobal and ExtCtrls.

procedure TForm1.HyperGrid1ChangeCellAttributes(Sender: TObject; ACol, ARow: Longint; Column: ThgHeading; State: ThgCellStates; var AColor: TColor; AFont: TFont; var HAlign: TAlignment; var VAlign: ThgVAlignment; var OuterBevel, InnerBevel: TPanelBevel);
begin
    if not ( hgcsFixed in State ) and Odd( ARow ) then
        AColor := clRed;
end;

The event above will set the color of all non-fixed cells in odd rows to clRed. Its that easy. Notice that the event also allows you to change all font properties, horizontal and vertical alignment, and bevels. The following code segment creates a checkerboard pattern on all non-fixed cells of a THyperGrid:

procedure TForm1.HyperGrid1ChangeCellAttributes(Sender: TObject; ACol, ARow: Longint; Column: ThgHeading; State: ThgCellStates; var AColor: TColor; AFont: TFont; var HAlign: TAlignment; var VAlign: ThgVAlignment; var OuterBevel, InnerBevel: TPanelBevel);
begin
    if not ( hgcsFixed in State ) then
        if Odd( ACol + Ord( Odd( ARow ) ) ) then
            AColor := clRed;
end;

 

How do I add items to a column's combo box at runtime?

You simply use the column's Items property which is of type TStrings as follows:

HyperGrid1.Columns[ 2 ].Items.Add( 'Item 1' );
HyperGrid1.Columns[ 2 ].Items.Add( 'Item 2' );
HyperGrid1.Columns[ 2 ].Items.Add( 'Item 3' );

You can also use any other method of TStrings, such as Assign.

 

Why is it so difficult to click a fixed cell when HyperColumnClick is set to True?

Each fixed cell allows two kinds of manipulation in a normal TStringGrid: one is to click between the cells to adjust the size of the column or row, the other is to click the cell and drag it, to move the column or row. THyperGrid also allows you to click a fixed cell, and attach an event handler to customize the behavior of the click. In order to maintain compatibility with TStringGrid, THyperGrid had to be customized so that a cell click would not interfere with the existing behaviors. So, the rectangle that a fixed cell occupies was divided into three regions each responding differently to a click. In the case of a fixed row, the left and right portions of the cell are used to size the column, the top and bottom portions are used to move the column, which leaves only the inner rectangle to be used for column clicks. If the cell is sized very small, this inner part becomes small too and difficult to click. In the case of a fixed column, the roles change somewhat: the top and bottom portions are used to size the row and the left and right portions to move it. So, that explains it.

In version 1.5, this behavior has been adjusted a bit as follows.

ColumnClick.gif (2596 bytes)

The full rectangle of each cell is used for column click with the following adjustments:

if goColSizing is set : For cells A,B,C the rectangle is reduced horizontally by 4 pixels on each side.
if goColMoving is set : For cells A,B,C the rectangle is reduced vertically by 4 pixels on each side.
if goRowSizing is set : For Cells 1,2,3 the rectangle is reduced vertically by 4 pixels on each side.
if goRowMoving is set : For Cells 1,2,3 the rectangle is reduced horisontally by 4 pixels on each side.

Note that cell 0 never changes, since it cannot be moved or sized.

 

V1.50 - How do I use the new OnComboSelection event?

This new event will fire in the following two cases : one, the user selects an item from a column's drop down or, two, the user types an item and accepts the grid's suggestion. Note that the event will NOT fire if the user edits a drop down cell and types some arbitrary text, including deleting the contents of the cell. You can use TStringGrid.OnSetEditText event for more control, as this event fires with each keystroke.

 

V1.60 - How do I save and load the contents of THyperGrid to/from a file?

In this version, THyperGrid has four new methods that allow you save and load its contents from a file or a stream, as follows:

LoadFromFile( StartCol , StartRow : Longint; const FileName : string );
LoadFromStream( StartCol , StartRow : Longint; Stream : TStream );
SaveToFile( StartCol , StartRow : Longint; const FileName : string );
SaveToStream( StartCol , StartRow : Longint; Stream : TStream );

The xxxFile methods are implemented as calls to the xxxStream methods. THyperGrid loads its contents from comma-delimited files with a text qualifier of " ( double quote ). Each line in the file represents a separate row.

Each item in the file, is separated by a comma. If one of the items includes a comma, it must be enclosed in double quotes. If one of the items, includes a quote, the quote needs to be doubled ( two double quotes ). When a cell is loaded from an item that has double quotes, it is NOT trimmed, that is, all the white space within the quotes is taken exactly as it is. When no quotes are present, the item is trimmed before it is loaded into the cell, using Delphi's Trim function. This format is very similar to TStrings.CommaText ( look at the help for this property ) except that spaces are never interpreted as delimiters. So the string "String 3" will not be broken up into two. This format is also compatible with Excel's CSV format, so files can be easily exchanged between the two.

These methods take into account invisible columns, so items may be loaded/saved into/from them. When using the LoadXXX methods, the arguments StartCol and StartRow do not have to be less than RowCount / ColCount, the Grid will be expanded if necesary.