He de confesar que ya había yo intentado algo similar sin mayor éxito. El problema está en que el dibujado de celdas está basado en columnas de manera que el evento OnDrawColumnCell no manda información acerca de la fila a la que pertenece la celda que se va a dibujar.
Al ver este mensaje volví a buscar y en los foros de Borland encontré una respuesta para C++ cuya traducción a Delphi pongo aquí:
Código Delphi
[-]
procedure TForm1.DBGrid1DrawColumnCell(
Sender: TObject; const Rect: TRect; DataCol: Integer;
Column: TColumn; State: TGridDrawState);
var
Grid: TDBGrid;
begin
Grid := Sender as TDBGrid;
if gdSelected in State then
begin
Grid.Canvas.Brush.Color := clRed;
Grid.SelectedRows.CurrentRowSelected := true;
end;
if Grid.SelectedRows.CurrentRowSelected then
begin
if not (gdFocused in State) then
Grid.Canvas.Brush.Color := clGreen;
end;
Grid.DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;
Para que esto funcione debe activarse la opción dgMultiSelect del DBGrid.
En principio, parece funcionar bien, pero tiene un problema: si comenzamos a desplazar el grid mediante la flecha inferior de la barra de desplazamiento vertical, las nuevas líneas aparecen todas con el color verde.
Sin embargo, basándome en este código, lo he adaptado para funcionar sin la opción dgMultiSelect:
Código Delphi
[-]
{$writeableconst on}
procedure TForm1.DBGrid1DrawColumnCell(
Sender: TObject; const Rect: TRect; DataCol: Integer;
Column: TColumn; State: TGridDrawState);
const
Bookmark: String = '';
var
Grid: TDBGrid;
DataSet: TDataSet;
begin
Grid := Sender as TDBGrid;
DataSet := Grid.DataSource.DataSet;
if Grid.Focused then
begin
if (gdSelected in State) and (Bookmark <> Table1.Bookmark) then
begin
Bookmark := DataSet.Bookmark;
Grid.Invalidate;
end;
if (Bookmark = DataSet.Bookmark) then
if gdFocused in State
then Grid.Canvas.Brush.Color := clRed
else Grid.Canvas.Brush.Color := clGreen;
end;
Grid.DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;
{$writeableconst off}
Cualquiera de los dos códigos mantienen el color aún cuando el grid no tenga el foco, como si tuviera activada la opción dgAlwaysShowSelection; y el segundo código tiene el problema de que al perder el foco, el color rojo (el de la celda seleccionada) se pierde, aunque es un problema menor comparado con el otro.
De cualquier forma, el autor original menciona que si se desea ocultar la selección cuando el grid pierde el foco bastaría con borrar la lista SelectedRows en el evento OnExit del grid y englobar todo el código de OnDrawColumnCell en el condicional:
Código Delphi
[-]
if Grid.Focused then
begin
end;
No pongo aquí la referencia original porque la busqué vía
tamaracka y en este servicio las búsquedas caducan al poco tiempo de manera que los enlaces a ellas no funcionan. Pero puedes encontrarla buscando "paint selected row". Escoges la vista por hilo (thread). Es de losprimeros hilos, se llama "TDBGrid custom Drawing" y el autor del código es Ingvar Anderberg.
// Saludos