I did this (see code below) and fully expected it to show the selected
row as light blue if focued or silver if not focused. But if I started
clicking around the grid, the cells other in the non-selected columns
didn't update correctly. They were always one click behind. If I did a
succession of down-arrows for example, the selected cell was correct,
the other columns had the selected colour in the previously selected
row, i.e. the one above where it should have been.
Any ideas?
TIA,
Mark
procedure TfmMsgTitler.grdFilesDrawCell(Sender: TObject; ACol, ARow:
Integer;
Rect: TRect; State: TGridDrawState);
var
grid: TDrawGrid absolute Sender;
canv: TCanvas;
cell: string;
begin
canv := grid.Canvas;
cell := '';
if ARow = 0 then begin
cell := MsgCols[mc];
end else begin
if ARow = grid.Row then begin
if gdFocused in State then begin
canv.Brush.Color := clBlue or clSilver;
end else begin
canv.Brush.Color := clSilver;
end{if}
end{if};
/// Code that sets "cell" based on ARow and ACol follows
end{if};
canv.FillRect(Rect);
canv.TextOut(Rect.Left + 2, Rect.Top + 1, cell);
end;// grdFilesDrawCell ---------------
>I did this (see code below) and fully expected it to show the selected
>row as light blue if focued or silver if not focused. But if I started
>clicking around the grid, the cells other in the non-selected columns
>didn't update correctly. They were always one click behind. If I did a
>succession of down-arrows for example, the selected cell was correct,
>the other columns had the selected colour in the previously selected
>row, i.e. the one above where it should have been.
If you reformat the code to make the begin / end block and
conditionals structure clearer, it becomes:
if ARow = 0 then
begin
cell := MsgCols[mc];
end
else
begin
if ARow = grid.Row then
begin
if gdFocused in State then
begin
canv.Brush.Color := clBlue or clSilver;
end
else
begin
canv.Brush.Color := clSilver;
end{if}
end{if};
/// Code that sets "cell" based on ARow and ACol follows
end{if};
canv.FillRect(Rect);
canv.TextOut(Rect.Left + 2, Rect.Top + 1, cell);
There are some conditions under which no assignment is ever made to
canv.Brush.Color:
ARow = 0, or
ARow <> grid.Row
In those cases, you draw anyhow, but the color of the brush you're
drawing with is not defined.
Good luck.
Kurt
If the focus moves from one cell to another only the previously focused
cell and the newly focused cell will be redrawn, but your code also
colors other cells in the row containing the focused cell. If you set the
grid options to include goRowSelect and exclude goRangeSelect the code
may work as you intend. Otherwise you will need to also handle the
OnSelectCell event. There you can check the current row against the new
row, if different you have to invalidate both rows to get them to
repaint. The grid inherits a protected InvalidateRow (as well as
InvalidateCell, InvalidateCol) methods from TCustomgrid, you just have to
use a cracker class to access them.
Also keep in mind that focus in a grid is not the same as selection...
Here is an old example for a stringgrid:
Coloring the active row of a stringgrid
type
TGridCracker = Class( TStringgrid );
// required to access protected method Invalidaterow
procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol,
ARow: Integer; var CanSelect: Boolean);
begin
With TGridCracker( Sender As TStringgrid ) Do Begin
InvalidateRow( Row );
InvalidateRow( aRow );
End;
end;
procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow:
Integer;
Rect: TRect; State: TGridDrawState);
var
grid: TStringgrid;
begin
If gdFixed In State Then Exit;
grid := Sender As TStringgrid;
If grid.Row = aRow Then Begin
With Grid.Canvas.Brush Do Begin
Color := $C0FFFF;
Style := bsSolid;
End;
grid.Canvas.FillRect( Rect );
grid.Canvas.Font.Color := clBlack;
grid.Canvas.TextRect( Rect, Rect.Left+2, Rect.Top+2, grid.Cells[acol,
arow]);
Grid.Canvas.Brush := grid.Brush;
End;
end;
--
Peter Below (TeamB)
Use the newsgroup archives :
http://www.mers.com/searchsite.html
http://www.tamaracka.com/search.htm
http://groups.google.com
http://www.prolix.be
> In those cases, you draw anyhow, but the color of the brush you're
> drawing with is not defined.
OK, thanks. I was expecting there to be some useful default.
BTW:
> If you reformat the code to make the begin / end block and
> conditionals structure clearer, it becomes:
I use a style that is closer to what Wirth adopted once he realized what
a mish-mash the original Pascal syntax leads to. Jean Ichbiah and team
must have been thinking the same way when they worked out the sytax for Ada.
Regards,
Mark
> type
> TGridCracker = Class( TStringgrid );
> // required to access protected method Invalidaterow
>
> procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol,
> ARow: Integer; var CanSelect: Boolean);
> begin
> With TGridCracker( Sender As TStringgrid ) Do Begin
> InvalidateRow( Row );
> InvalidateRow( aRow );
> End;
> end;
Thanks! I added code like this to my app (using TDrawGrid instead of
TStringGrid, and it worked sweet. I had grid.Repaint in the SelectCell
event, but I replaced it with the pair of InvalidateRow calls.
Regards,
Mark
>OK, thanks. I was expecting there to be some useful default.
I suppose it depends on what you mean by "useful". At the beginning of
the drawing process the default colors are what you might expect - the
Brush.Color is the Color of the component, the Font and its Color are
set to those for the component's Font. But as each cell is drawn, you
are changing those defaults - or not changing them in some cases. It's
the "not changing" part that is causing your problem - you end up
using the colors you used for the last cell where you did change them.
>I use a style that is closer to what Wirth adopted once he realized what
>a mish-mash the original Pascal syntax leads to. Jean Ichbiah and team
>must have been thinking the same way when they worked out the sytax for Ada.
Yes, the if.. then structure is awkward. I wasn't criticising your
technique, just trying to make the blocks more obvious.
Good luck.
Kurt
I am assuming that the canvas gets set to the defaults each time it
enters the DrawCell routine. I took Peter Below's advice in this thread
and it seemed to work:
// For protected method TCustomGrid.InvalidateRow:
type
TGridCracker = class(TDrawGrid);
procedure TfmMsgTitler.grdFilesSelectCell(Sender: TObject; ACol, ARow:
Integer; var CanSelect: Boolean);
var
grid: TGridCracker absolute Sender;
begin
if (TMsgCol(ACol) = mcSubject) // ACol = 0
and (subjectThread = nil) and (MsgFileAtRow(ARow) <> nil) then begin
grid.Options := grid.Options + [goEditing];
end else begin
grid.Options := grid.Options - [goEditing];
end{if};
grid.InvalidateRow(grid.Row);
grid.InvalidateRow(aRow);
end;// grdFilesSelectCell --------------
When I was setting canv.Brush.Color in every branch but commented out
those calls to InvalidateRow, the problem came back. I'm going to leave
in the extra line setting canv.Brush.Color though, because now the fixed
columns look good even when there is only one row. It looks more
professional now.
procedure TfmMsgTitler.grdFilesDrawCell(Sender: TObject; ACol, ARow:
Integer;
Rect: TRect; State: TGridDrawState);
var
grid: TDrawGrid absolute Sender;
mc: TMsgCol absolute ACol;
canv: TCanvas;
cell: string;
begin
canv := grid.Canvas;
cell := '';
if ARow = 0 then begin
cell := MsgCols[mc];
canv.Brush.Color := clBtnFace;
end else begin
if ARow = grid.Row then begin
if gdFocused in State then begin
canv.Brush.Color := clBlue or clSilver;
end else begin
canv.Brush.Color := clSilver;
end{if}
end{if};
..... etc
Thanks,
Mark Patterson