Board index » delphi » TStringGrid highlight cells in row[0] and col[0]

TStringGrid highlight cells in row[0] and col[0]

Hi

I have a stringgrid that is the basis for an appointment book, and as such
every cell is colored differently, meaning re-draws can be a bit slow.  I
would like to highlight the Cells[0, SelectedRow] and Cells[SelectedColumn,
0] by either drawing the fixed column or fixed row text in bold or the cell
border as a button (ala Excel '97) to indicate the users selection.

Problem is, the re-draws make the display flash as the entire grid is
re-drawn.

Is it possible to just re-draw the Col[0] or Row[0] without drawing the
entire grid?

Any help would be appreciated.

--
Peter Crain

 

Re:TStringGrid highlight cells in row[0] and col[0]


On Thu, 16 Jul 1998 19:47:41 +1000, "Peter Crain" <pcr...@ecn.net.au>
wrote:

Quote
> Is it possible to just re-draw the Col[0] or Row[0] without drawing the
> entire grid?

Where are you drawing? You should only do so in the OnDrawCell event.
Delphi will only fire OnDrawCell for those cells which actually need
to be drawn -- not the entire grid.

--
Rick Rogers (TeamB) | Fenestra Technologies
http://www.fenestra.com/

Re:TStringGrid highlight cells in row[0] and col[0]


Peter,

i used a similar scheme in one of my apps. TCustomGrid has a couple of very
useful but protected methods:

    procedure InvalidateCell(ACol, ARow: Longint);
    procedure InvalidateCol(ACol: Longint);
    procedure InvalidateRow(ARow: Longint);

Since they are protected you have to derive a new class from TStringGrid to
be able to access them (or use a cracker class). I used a cracker class to
handle a plain TDrawgrid. The grid has border cells on all four sides, not
only on the top and left, that is the reason why four border cells need to
be redrawn when a cell is selected.

{+------------------------------------------------------------
 | Procedure TMTPlateMain.SelectCell
 |
 | Parameters:
 |  none
 | Call method:
 |  static
 | Description:
 |  Selects a well and invalidates the affected cells on the
 |  active grid. In addition to the
 |  cell holding the well data four border cells need to be
 |  redrawn. They display the marker arrow for the well.
 | Error Conditions:
 |  none
 |
 |Created: 21.07.97 14:44:56 by P. Below
 +------------------------------------------------------------}
Procedure TMTPlateMain.SelectCell( aCol, aRow: Integer );
  Begin
    Include(Wells[aCol,aRow].State, wsSelected);
    With TGridCracker(ActiveGrid) Do Begin
      InvalidateCell(aCol,aRow);
      InvalidateCell(aCol,0);
      InvalidateCell(aCol,NumWellsY+1);
      InvalidateCell(0,aRow);
      InvalidateCell(NumWellsX+1,aRow);
    End; { With }
  End; { TMTPlateMain.SelectCell }

TGridCracker is simply declared as

  Type TGridCracker = Class( TCustomGrid );

Peter Below (TeamB)  100113.1...@compuserve.com)

Re:TStringGrid highlight cells in row[0] and col[0]


Hi Peter!

What's about:
TStringGrid.Canvas.TextRect(Rect: TRect; X, Y: Integer; const Text: string);
combined with:
TStringGrid.CellRect(ACol, ARow: Longint): TRect;
See delphi-help for further details.

Hope this helps,
Michael

Re:TStringGrid highlight cells in row[0] and col[0]


Rick

In this case, only in Col[0] and Row[0], in the cells that are the X & Y
axes of the selected cell.

Peter Belows' code that exposes a couple of unknown (to me) methods, looks
promising, I'll have a play with that. If you have any other ideas I would
appreciate your help.

Regards

Peter Crain

Quote
>Where are you drawing? You should only do so in the OnDrawCell event.
>Delphi will only fire OnDrawCell for those cells which actually need
>to be drawn -- not the entire grid.

Re:TStringGrid highlight cells in row[0] and col[0]


Peter

That would appear to cover it, thank you very much for your help, I'll go &
look at it.

Regards

Peter Crain

Quote
>Peter,

>i used a similar scheme in one of my apps. TCustomGrid has a couple of very
>useful but protected methods:

Re:TStringGrid highlight cells in row[0] and col[0]


Rick

I sent a response days ago, and it hasn't appeared here yet. Weird.

In response, I was calling StringGrid1.invalidate, hence the thrashing
around, but I have adapted Peter Belows' idea and cracked the grid class,
and used the InvalidateCell method.

Thank you for your help Rick.

Regards

Quote

>Where are you drawing? You should only do so in the OnDrawCell event.
>Delphi will only fire OnDrawCell for those cells which actually need
>to be drawn -- not the entire grid.

Re:TStringGrid highlight cells in row[0] and col[0]


Peter,

I actually composed a thankyou response 2 days ago, and it hasn't appeared
yet.

Thank you. I did as you suggested, but I found that the Col[0] & Row[0]
cells that _previously_ been highlighted stayed that way, so I looped
through all those cells and reset them, then set the highlight to the new
cells. No probs, no flashing. I expect that your OnCellDraw was set out a
bit more intelligently then mine.

However, your Wells setting has me intrigued. Is it a ButtonDown type of
cell border drawing thing? I didn't want to take over _all_ the drawing in
this thing, preferring to use default drawing on, but if it is a simple
thing to do I would appreciate some tips.

Regards

Quote
Peter Below <100113.1...@compuserve.com> wrote in message ...
>Peter,

>i used a similar scheme in one of my apps. TCustomGrid has a couple of very
>useful but protected methods:

>    procedure InvalidateCell(ACol, ARow: Longint);
>    procedure InvalidateCol(ACol: Longint);
>    procedure InvalidateRow(ARow: Longint);

Re:TStringGrid highlight cells in row[0] and col[0]


Quote
In article <6oohsj$bj...@forums.borland.com>, Peter Crain wrote:
> I did as you suggested, but I found that the Col[0] & Row[0]
> cells that _previously_ been highlighted stayed that way, so I looped
> through all those cells and reset them, then set the highlight to the new
> cells.

My code has a DeselectCell method similar to the SelectCell i showed that
invalidates the border cells for the previously selected cell. The
OnDrawCell event then paints the cells in the unselected state.

Quote
> However, your Wells setting has me intrigued. Is it a ButtonDown type of
> cell border drawing thing?

Not exactly. The grid is an image of a 96 well microtiter plate, a
storage device used for example in biochemical laboratories to hold samples
for testing. The application allows a user to enter information identifying
the samples and amount in each well. The wells can have different states,
empty, used, reserved and in addition (for display purposes only) selected
or unselected. The Ondrawcell handler uses the well state (a set of the
allowed values) to figure out which colors to use for the cell background
and the circle representing the well itself. The border cells either show a
column or row number (for unselected cells) or a red arrow pointing towards
the cell for the selected cell (there can be only one). The border cell
background is always the standard clBtnFace gray.

Type
  TWellState = ( wsEmpty, wsSelected, wsFilled, wsReserved );
  TWellStates= Set Of TWellState;
  TWellItem  = ( wiBackground, wiBorder, wiWell );
    { The three display items on a well }
  TWellColors = Array [TWellItem, TWellState ] of TColor;
    { Display colors for well items in the different states of a well. }
Const
  { Default well color scheme. }
  DefWellColors : TWellColors =(
    (clWhite, clBlue, clYellow, clSilver),
    (clBlack, clWhite, clBlack, clBlack),
    (clWhite, clNavy, clOlive, clDkGray)
    );

{+------------------------------------------------------------
 | Procedure TMTPlateMain.MicrotiterplateDrawCell
 |
 | Parameters:
 |  Sender: the microtiterplate draw grid
 |  Col, Row: coordinates of the cell to draw
 |  Rect: bounding rectangle of the cell
 |  State: cell state, not used since we keep state internally.
 | Call method:
 |  static
 | Description:
 |  This method handles the drawing of cells. Depending on the
 |  cell coordinates it will either draw a border cell (which
 |  displays a column/row number) or a well. The well state
 |  determines which colors are used to display the elements of
 |  a well.
 | Error Conditions:
 |  none
 |
 |Created: 21.07.97 13:54:13 by P. Below
 +------------------------------------------------------------}
Procedure TMTPlateMain.MicrotiterplateDrawCell(Sender: TObject; Col,
  Row: Longint; Rect: TRect; State: TGridDrawState);
  Procedure DrawDataCell;
    { Draw a well. The well is composed of three items: the background,
      the well circle and the inner area of that circle. Each item has
      a color determined by the wells state and the current color scheme.
      The matter of state is a bit complicated by the fact that several
      of the state bits can be set at the same time. We define a priority
      sequence and the first state in the sequence that is found in the
well
      is used to determine the colors.}
    Type
      TDrawSequence = Array [1..4] of TWellState;
    Const
      DrawSequence: TDrawSequence =
         (wsSelected, wsReserved, wsFilled, wsEmpty );  
    Var
      i: Integer;
    Procedure DrawItem(state: TWellState);
      Begin
        With (Sender As TDrawGrid).Canvas Do Begin
          Brush.Color := WellColors[wiBackground, state];
          FillRect(Rect);
          Pen.Color := WellColors[wiBorder, state];
          Brush.Color:= WellColors[wiWell, state];
          InflateRect( rect, -3, -3 );
          With rect Do
            Ellipse( left, top, right, bottom );
        End; { With }
      End; { DrawItem }
    Begin { DrawDataCell }
      Brush.Style := bsSolid;
      For i := Low(DrawSequence) To High(DrawSequence) Do
        If DrawSequence[i] In Wells[col, row].State Then Begin
          DrawItem(DrawSequence[i]);
          Exit;
        End; { For }
    End; { DrawDataCell }
  Begin { TMTPlateMain.MicrotiterplateDrawCell }
    If (Col = 0) or (Col = Succ(NumWellsX)) Then
      DrawRowBordercell( Sender, Col, Row, Rect )
    Else If (Row = 0) or (Row = Succ(NumWellsY)) Then
      DrawColumnBordercell( Sender, Col, Row, Rect )
    Else
      DrawDataCell;
  End; { TMTPlateMain.MicrotiterplateDrawCell }

{+------------------------------------------------------------
 | Procedure TMTPlateMain.DrawRowBorderCell
 |
 | Parameters:
 |  Sender: the microtiterplate or worksheet drawgrid
 |  Col, Row: coordinates of cell to paint
 |  Rect; cell bounding rectangle
 | Call method:
 |  static
 | Description:
 |  This is a helper routine used by the OnDrawCell event handlers
 |  of the two grids. It paints the first and last cell of a row
 |  which displays the row letter.
 | Error Conditions:
 |  none
 |
 |Created: 25.07.97 14:40:26 by P. Below
 +------------------------------------------------------------}
Procedure TMTPlateMain.DrawRowBorderCell( Sender: TObject; Col, Row:
Longint; Rect: TRect );
  { Draw the first or last cell of a row. This cell will display one
    of the letters A to H, if the row contains wells. }
  Var
    ch: Char;
  Begin
    With (Sender As TDrawGrid).Canvas Do Begin
      { Fill cell with background color. }
      Brush.Color := TDrawGrid(Sender).FixedColor;
      FillRect( Rect );

      { If we have a corner cell, nothing needs to be displayed on it. }
      If (row = 0) or (row = Succ(numWellsY)) Then
        Exit;

      { If a selected cell is in the current row we display a marker
        arrow instead of the well number. The marker is a character
        in the WingDings character set and painted in red to be suspicious.

Quote
}

      If SelectionInRow( row ) Then Begin
        If col = 0 Then
          ch := #232
        Else
          ch := #231;
        Font.Name := 'WingDings';
        Font.Color:= clRed;
      End { If }
      Else
        ch := Chr(Ord('@')+row);

      { The character is aligned to give a constant distance from the
        well array. }
      If col = 0 Then
        TextOut(rect.right - textwidth(ch)- 5,
                rect.top + (rect.bottom-rect.top - TextHeight(ch)) div 2,
                ch)
      Else
        TextOut(rect.left + 5,
                rect.top + (rect.bottom-rect.top - TextHeight(ch)) div 2,
                ch)
    End; { With }
  End; { TMTPlateMain.DrawRowBorderCell }

{+------------------------------------------------------------
 | Procedure TMTPlateMain.DrawColumnBorderCell
 |
 | Parameters:
 |  Sender: the microtiterplate or worksheet drawgrid
 |  Col, Row: coordinates of cell to paint
 |  Rect; cell bounding rectangle
 | Call method:
 |  static
 | Description:
 |  This is a helper routine used by the OnDrawCell event handlers
 |  of the two grids. It paints the top and bottom cell of a column
 |  which displays the column number.
 | Error Conditions:
 |  none
 |
 |Created: 25.07.97 14:40:26 by P. Below
 +------------------------------------------------------------}
Procedure TMTPlateMain.DrawColumnBorderCell( Sender: TObject; Col, Row:
Longint; Rect: TRect );
  Var
    S: String[2];
  Begin
  { Draw the first or last cell of a column. This cell will display a
    number 1 to 12, if the column contains wells. }
    With (Sender As TDrawGrid).Canvas Do Begin
      { Fill cell with background color. }
      Brush.Color := TDrawGrid(Sender).FixedColor;
      FillRect( Rect );

      { If we have a corner cell, nothing needs to be displayed on it. }
      If (col = 0) or (col = Succ(numWellsX)) Then
        Exit;

      { If a selected cell is in the current column we display a marker
        arrow instead of the well number. The marker is a character
        in the WingDings character set and painted in red to be suspicious.

Quote
}

      If SelectionInCol( col ) Then Begin
        If row = 0 Then
          S := #234
        Else
          S := #233;
        Font.Name := 'WingDings';
        Font.Color:= clRed;
      End { If }
      Else
        S := IntToStr(Col);

      { The character is aligned to give a constant distance from the
        well array. }
      If row = 0 Then
        TextOut(rect.left + (rect.right-rect.left - TextWidth(S)) div 2,
                rect.bottom - TextHeight(S) - 3,
                S)
      Else
        TextOut(rect.left + (rect.right-rect.left - TextWidth(S)) div 2,
                rect.top + 3,
                S)
    End; { With }
  End; { TMTPlateMain.DrawColumnBorderCell }

Peter Below (TeamB)  100113.1...@compuserve.com)

Other Threads