Recuerda que en las ciencias un error casi siempere suele tener diversas soluciones, de igual modo aquí mostramos lo mejor y más óptimo.
Solución:
Debe dibujar sus propias casillas de verificación, preferiblemente usando temas visuales, si está habilitado. Este es un esquema simple de cómo hacerlo:
const
Checked: array[1..4] of boolean = (false, true, false, true);
procedure TForm4.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
const
PADDING = 4;
var
h: HTHEME;
s: TSize;
r: TRect;
begin
if (ACol = 2) and (ARow >= 1) then
begin
FillRect(StringGrid1.Canvas.Handle, Rect, GetStockObject(WHITE_BRUSH));
s.cx := GetSystemMetrics(SM_CXMENUCHECK);
s.cy := GetSystemMetrics(SM_CYMENUCHECK);
if UseThemes then
begin
h := OpenThemeData(StringGrid1.Handle, 'BUTTON');
if h <> 0 then
try
GetThemePartSize(h,
StringGrid1.Canvas.Handle,
BP_CHECKBOX,
CBS_CHECKEDNORMAL,
nil,
TS_DRAW,
s);
r.Top := Rect.Top + (Rect.Bottom - Rect.Top - s.cy) div 2;
r.Bottom := r.Top + s.cy;
r.Left := Rect.Left + PADDING;
r.Right := r.Left + s.cx;
DrawThemeBackground(h,
StringGrid1.Canvas.Handle,
BP_CHECKBOX,
IfThen(Checked[ARow], CBS_CHECKEDNORMAL, CBS_UNCHECKEDNORMAL),
r,
nil);
finally
CloseThemeData(h);
end;
end
else
begin
r.Top := Rect.Top + (Rect.Bottom - Rect.Top - s.cy) div 2;
r.Bottom := r.Top + s.cy;
r.Left := Rect.Left + PADDING;
r.Right := r.Left + s.cx;
DrawFrameControl(StringGrid1.Canvas.Handle,
r,
DFC_BUTTON,
IfThen(Checked[ARow], DFCS_CHECKED, DFCS_BUTTONCHECK));
end;
r := Classes.Rect(r.Right + PADDING, Rect.Top, Rect.Right, Rect.Bottom);
DrawText(StringGrid1.Canvas.Handle,
StringGrid1.Cells[ACol, ARow],
length(StringGrid1.Cells[ACol, ARow]),
r,
DT_SINGLELINE or DT_VCENTER or DT_LEFT or DT_END_ELLIPSIS);
end;
end;
Por supuesto, en un escenario real, el Checked
array no es una constante, y es posible que desee guardar el s
métricas y h
identificador de tema entre eventos de pintura de celdas. Pero el principio está aquí.
Lo que falta aquí es una función para alterar el estado de las casillas de verificación. Probablemente querrá alternar el estado en un OnClick
manipulador. Si es realmente serio, también deseará responder al movimiento del mouse y mostrar el efecto de desplazamiento del mouse en las casillas de verificación si hay temas disponibles.
EDITAR por azulado: Para alternar el estado de la casilla de verificación, esta respuesta explica cómo puedes usar Invalidate
método.
No trate de colocar un real TCheckBox
controlar dentro de un TStringGrid
. Usa la grilla OnDrawCell
evento con la API de Win32 DrawFrameControl()
en su lugar, para dibujar una imagen de un control CheckBox dentro de cada celda según sea necesario. Puedes usar el OnClick/OnMouse...
eventos con la grilla Objects[][]
propiedad para realizar un seguimiento del estado marcado de cada celda según sea necesario. Creo que esto es mucho más fácil de manejar, ya que TStringGrid
no fue diseñado para albergar controles reales.
Uso una cuadrícula virtual llamada ExGridView de Roman Mochalov, que admite casillas de verificación.
Mi propia bifurcación modificada de GridView, portada para Unicode, etc., llamada TExGridView, en lugar de TGridView, y con una demostración de casillas de verificación está en bitbucket aquí como /wpostma/exgridview.
El componente ExGridView tiene una propiedad Checkbox en el inspector de propiedades que debe configurarse trueLuego, debe configurar las propiedades de su columna para que la columna tenga un tipo de casilla de verificación establecido en casilla de verificación o botón de opción. Luego debe implementar la devolución de llamada del evento GetCheckState. Vea la demostración incluida en el proyecto bitbucket.
La fuente original de este código estaba aquí, pero no se puede compilar en versiones recientes. Mi versión de bitbucket está probada y funciona con Delphi 2007, 2009 y todas las versiones actualizadas a partir de 2016 (Delphi 10 Seattle).
Sección de Reseñas y Valoraciones
Si te apasiona la informática, tienes el poder dejar un tutorial acerca de qué te ha impresionado de este ensayo.