Use the 'OTHER' Mouse button to navigate within frames!

How to Add Color to Your Database Grids

STOCK.GIF

Adding color to your database grids will enhance the appearance and differentiate the importance of certain rows or columns within the database. This technique will add to the UI (user interface) of your applications and give additional meaning to your data.

You have the ability to change the appearance of your DBGrids. This is accomplished by drawing the cells' canvas of the grid yourself. At first, this may seem like a lot of work. But don't worry, we'll step through an example.

The DefaultDrawing property of the DBGrid determines if the cell is painted and the item it contains is drawn automatically. If True, the default drawing occurs. If False, your application must handle all the drawing details in the OnDrawCell event handler, or in the OnDrawDataCell event handler for the data grid. In this example, we will set the DefaultDrawing property to False and specify the code within the OnDrawDataCell event.

The OnDrawDataCell event occurs whenever the contents of a data grid cell needs to be redisplayed. For example, it occurs when the user selects a cell or scrolls the grid.

Let's get going and add some colors to your DBGrid !!!



Note:  This example assumes you have an DBDEMOS alias pointed to the sample 
       database files located in \DELPHI\DEMOS\DATA

     1.  Create a New Project.  ( File | New Project )

     2.  Save the Project.

     3.  Save the unit as STOCKGRD.PAS and the project as STKFOLIO.DPR

     4.  With Form1
           - Set the Name Property to 'MyStockForm'
           - Set the BorderStyle to bsSingle
           - Add a public declaration to the TMyStockForm

               Added code:

                 public
                 { Public declarations }
                   AlertAmount: Double;

     5.  Set the Caption Property of MyStockForm to 'My Stock Portfolio'

     6.  Add a TPanel component on your form

     7.  With Panel1 do
           - Clear the Caption Property
           - Set the Align Property to alClient
           - Set the BevelInner Property to bvLowered
           - Set the BevelOuter Property to bvRaised
           - Set the BevelWidth Property to 2
           - Set the BorderWidth Poperty to 1

     8.  Add a TTable, TDataSource, and TDBGrid to the form

     9.  With Table1 do
           - Set the DatabaseName Property to DBDEMOS
           - Set the IndexFieldNames to SYMBOL
           - Set the TableName to HOLDINGS.DBF

    10.  Select the Table component on the form and double-click it 
         (Bring up the Fields Editor)

         With the Fields Editor
           - Click the Add.. button, select and add all fields except 
             for ACCT_NBR and then click OK
           - Click the Define.. button and define a new calculated field 
	     from the Define Field Dialog.  Name the field CURRENT_VAL 
             and set the Field Type to a StringField.
 
    11.  Select the Table Component and set the Active Property to True

    12.  Select the Table component on the form and edit the
         OnCalcFields Event.  

         OnCalcFields Event Code: 
 
           ---------------------------------------------------------------
           procedure TMyStockForm.Table1CalcFields(DataSet: TDataset);
           var
             z: Double;
           begin
             z:=Table1PUR_PRICE.Value * Table1SHARES.Value;
             Table1CURRENT_VAL.Value:= 
                 FormatFloat('$###,##0.00;;(0.00#.##)',z);
           end;
           ---------------------------------------------------------------

    13.  Select the DataSource Component on the form and Set the DataSet
         Property to Table1

    14.  With DBGrid1 
           - Set the DataSource Property to DataSource1
           - Set the DefaultDrawing Property to False
           - Edit the OnDrawDataCell Event

         OnDrawDataCell Event Code:

           --------------------------------------------------------------- 
           procedure TMyStockForm.DBGrid1DrawDataCell(Sender: TObject; 
             const Rect: TRect; Field: TField; State: TGridDrawState);
           begin

           {Optional code if you only want to color highlight the 
            CURRENT_VAL column}

           {Use this as an example in combination to put color effects 
            on the grid}

           {if Field.FieldName = 'CURRENT_VAL' then begin}

             if (Table1PUR_PRICE.Value * Table1SHARES.Value) >= 
               AlertAmount then
               DBGrid1.Canvas.Brush.Color:= ColorGrid1.ForeGroundColor
             else
               DBGrid1.Canvas.Brush.Color:= ColorGrid1.BackGroundColor;
             DBGrid1.Canvas.FillRect(Rect);
           {  end;}
             DBGrid1.Canvas.TextOut(Rect.left + 2, Rect.top + 2, 
                                    Field.AsString);

           end;
           ---------------------------------------------------------------  

           Commentary:  This Event is called each time the cell is drawn.
                        In this Event, if the value of the stock 
                        (Purchased Price * Shares) is greater than the 
                        variable AlertValue, then the cells of the record
                        (row) is highlighted in the color specified in
                        ColorGrid.  

                        Each individual cell is a Rect of TRect.  It is 
                        sent as a parameter of the Procedure.  Normally,
                        if you weren't controlling the drawing of cells,
                        the grid would call both the FillRect and TextOut 
                        methods of the canvas.  It would also initializes 
                        the Canvas' font and brush to the control font 
                        and the cell color.

                        But since we are controlling the drawing of the 
                        cell, we also have the ability to change the Canvas' 
                        font and brush.  This is what gives us the ability 
                        to change the color of the cells.


    15.  Add three TLabel components, two TSpinEdit components, and one
         TColorGrid component to the form.

    16.  Align the Label components and the SpinEdit components such 
         that Label1 is near SpinEdit1.  The same is for Label2 and
         SpinEdit2.

    17.  With Label1 
           - Set the Caption Property to 
              'Highlight current values greater than -->'
           - Set the WordWrap Property to True
           - Set the Alignment Property to taRightJustify

    18.  With Label2
           - Set the Caption Property to 
              'Increment by:'
           - Set the WordWrap Property to True
           - Set the Alignment Property to taRightJustify

    19.  With SpinEdit1 
           - Set the Value Property to 100000
           - Edit the OnChange Event

         OnChange Event Code:

           --------------------------------------------------------------- 
           procedure TMyStockForm.SpinEdit1Change(Sender: TObject);
           begin
             AlertAmount:= SpinEdit1.Value;
             dbGrid1.refresh;
           end;
           --------------------------------------------------------------- 

    20.  With SpinEdit2
           - Set the Value Property to 10000
           - Set the Increment Property to 1000
           - Edit the OnChange Event

         OnChange Event Code:

           --------------------------------------------------------------- 
           procedure TMyStockForm.SpinEdit2Change(Sender: TObject);
           begin
             spinedit1.increment:= spinedit2.value;
           end;
           ---------------------------------------------------------------         

    21.  With ColorGrid1
           - Set the GridOrdering Property to 16x1
           - Edit the OnChange Event

         OnChange Event Code:

           --------------------------------------------------------------- 
           procedure TMyStockForm.ColorGrid1Change(Sender: TObject);
           begin
             dbGrid1.refresh;
           end;
           ---------------------------------------------------------------  

    22.  With Label3
           - Set the WordWrap Property to True
           - Set the Caption Property to  
               'To Change Foreground Color, left mouse click and drag FG. 
               To change Background Color, right mouse click and drag BG.'

    23.  With MyStockForm
           - Edit the OnCreate Event

         OnCreate Event Code:

           ---------------------------------------------------------------  
           procedure TMyStockForm.FormCreate(Sender: TObject);
           begin
             colorgrid1.foregroundindex:= 9;
             colorgrid1.backgroundindex:= 15;
             AlertAmount:= SpinEdit1.Value;
             SpinEdit1.Increment:= SpinEdit2.Value;
           end;
           ---------------------------------------------------------------  

    24.  Compile and Run the Form.  

           Commentary:  This demonstrated how you can control the cell 
                        drawing on a grid.  This knowledge can be applied
                        to other components where you also have the ability 
	                to control the drawing.  

                        Remember that within the OnDrawDataCell Event of the 
                        TDBGrid, you have access to the Field information 
                        and also the information of the record you're 
                        currently on.  With this, you have the flexibility 
                        to create some very complex grids to display your 
                        data.



*************************************************

{STOCKGRD.PAS}

unit Stockgrd;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls, DB, DBTables, Grids, DBGrids, ExtCtrls,
  Spin, ColorGrd;

type
  TMyStockForm = class(TForm)
    Table1: TTable;
    DataSource1: TDataSource;
    Table1SYMBOL: TStringField;
    Table1SHARES: TFloatField;
    Table1PUR_PRICE: TFloatField;
    Table1PUR_DATE: TDateField;
    Panel1: TPanel;
    DBGrid1: TDBGrid;
    Table1CURRENT_VAL: TStringField;
    Label1: TLabel;
    ColorGrid1: TColorGrid;
    SpinEdit1: TSpinEdit;
    Label2: TLabel;
    SpinEdit2: TSpinEdit;
    Label3: TLabel;
    procedure DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;
      Field: TField; State: TGridDrawState);
    procedure Table1CalcFields(DataSet: TDataset);
    procedure SpinEdit1Change(Sender: TObject);
    procedure SpinEdit2Change(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ColorGrid1Change(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    AlertAmount: Double;
  end;

var
  MyStockForm: TMyStockForm;

implementation

{$R *.DFM}

procedure TMyStockForm.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;
  Field: TField; State: TGridDrawState);
begin

{Optional code if you only want to color highlight the CURRENT_VAL column}
{Use this as an example in combination to put color effects on the grid}

{ if Field.FieldName = 'CURRENT_VAL' then begin}
    if (Table1PUR_PRICE.Value * Table1SHARES.Value) >= AlertAmount then
      DBGrid1.Canvas.Brush.Color:= ColorGrid1.ForeGroundColor
    else
      DBGrid1.Canvas.Brush.Color:= ColorGrid1.BackGroundColor;
    DBGrid1.Canvas.FillRect(Rect);
{  end;}
  DBGrid1.Canvas.textout(rect.left + 2, rect.top + 2, Field.AsString);
end;

procedure TMyStockForm.Table1CalcFields(DataSet: TDataset);
var
  z: double;
begin
  z:=Table1PUR_PRICE.Value * Table1SHARES.Value;
  Table1CURRENT_VAL.Value:= FormatFloat('$###,##0.00;;(0.00#.##)',z);
end;

procedure TMyStockForm.SpinEdit1Change(Sender: TObject);
begin
  AlertAmount:= SpinEdit1.Value;
  dbGrid1.refresh;
end;

procedure TMyStockForm.SpinEdit2Change(Sender: TObject);
begin
  spinedit1.increment:= spinedit2.value;
end;

procedure TMyStockForm.FormCreate(Sender: TObject);
begin
  colorgrid1.foregroundindex:= 9;
  colorgrid1.backgroundindex:= 15;
  AlertAmount:= SpinEdit1.Value;
  SpinEdit1.Increment:= SpinEdit2.Value;
end;

procedure TMyStockForm.ColorGrid1Change(Sender: TObject);
begin
  dbGrid1.refresh;
end;

end.

-------------------------------------------------

{STOCKGRD.DFM}

object MyStockForm: TMyStockForm
  Left = 143
  Top = 83
  BorderStyle = bsSingle
  Caption = 'My Stock Portfolio'
  ClientHeight = 417
  ClientWidth = 544
  Font.Color = clWindowText
  Font.Height = -13
  Font.Name = 'System'
  Font.Style = []
  PixelsPerInch = 96
  OnCreate = FormCreate
  TextHeight = 16
  object Panel1: TPanel
    Left = 0
    Top = 0
    Width = 544
    Height = 417
    Align = alClient
    BevelInner = bvLowered
    BevelWidth = 2
    BorderWidth = 1
    TabOrder = 0
    object Label1: TLabel
      Left = 16
      Top = 257
      Width = 175
      Height = 33
      Alignment = taRightJustify
      Caption = 'Highlight current values greater than -->'
      WordWrap = True
    end
    object Label2: TLabel
      Left = 351
      Top = 258
      Width = 68
      Height = 32
      Alignment = taRightJustify
      Caption = 'Increment by:'
      WordWrap = True
    end
    object Label3: TLabel
      Left = 76
      Top = 368
      Width = 399
      Height = 33
      Caption = 'To Change Foreground Color, left mouse click and drag FG. To change Background Color, right mouse click and drag BG.'
      WordWrap = True
    end
    object DBGrid1: TDBGrid
      Left = 17
      Top = 15
      Width = 513
      Height = 224
      DataSource = DataSource1
      DefaultDrawing = False
      TabOrder = 0
      TitleFont.Color = clWindowText
      TitleFont.Height = -13
      TitleFont.Name = 'System'
      TitleFont.Style = []
      OnDrawDataCell = DBGrid1DrawDataCell
    end
    object ColorGrid1: TColorGrid
      Left = 24
      Top = 306
      Width = 496
      Height = 54
      GridOrdering = go16x1
      TabOrder = 1
      OnChange = ColorGrid1Change
    end
    object SpinEdit1: TSpinEdit
      Left = 211
      Top = 264
      Width = 121
      Height = 26
      MaxValue = 0
      MinValue = 0
      TabOrder = 2
      Value = 100000
      OnChange = SpinEdit1Change
    end
    object SpinEdit2: TSpinEdit
      Left = 433
      Top = 264
      Width = 91
      Height = 26
      Increment = 1000
      MaxValue = 0
      MinValue = 0
      TabOrder = 3
      Value = 1000
      OnChange = SpinEdit2Change
    end
  end
  object Table1: TTable
    Active = True
    OnCalcFields = Table1CalcFields
    DatabaseName = 'DBDEMOS'
    IndexFieldNames = 'SYMBOL'
    TableName = 'HOLDINGS.DBF'
    Left = 10
    Top = 12
    object Table1SYMBOL: TStringField
      FieldName = 'SYMBOL'
      Size = 7
    end
    object Table1SHARES: TFloatField
      FieldName = 'SHARES'
    end
    object Table1PUR_PRICE: TFloatField
      FieldName = 'PUR_PRICE'
    end
    object Table1PUR_DATE: TDateField
      FieldName = 'PUR_DATE'
    end
    object Table1CURRENT_VAL: TStringField
      Calculated = True
      FieldName = 'CURRENT_VAL'
    end
  end
  object DataSource1: TDataSource
    DataSet = Table1
    Left = 10
    Top = 38
  end
end

*************************************************