Ir al contenido


Foto

Checkbox en un DBGrid


  • Por favor identifícate para responder
9 respuestas en este tema

#1 darkerviti

darkerviti

    Member

  • Miembros
  • PipPip
  • 21 mensajes

Escrito 31 mayo 2013 - 06:02

Buenos días,

Estoy pegándome con un dbgrid que tiene dentro un checkbox, he probado varias versiones, buscando por internet he encontrado esto:



delphi
  1. procedure TForm1.DBGrid1DrawColumnCell(
  2.   Sender: TObject; const Rect: TRect; DataCol:
  3.   Integer; Column: TColumn; State: TGridDrawState);
  4.  
  5. const IsChecked : array[Boolean] of Integer =
  6.       (DFCS_BUTTONCHECK, DFCS_BUTTONCHECK or DFCS_CHECKED);
  7. var
  8.   DrawState: Integer;
  9.   DrawRect: TRect;
  10. begin
  11.   if (gdFocused in State) then
  12.   begin
  13.     if (Column.Field.FieldName = DBCheckBox1.DataField) then
  14.     begin
  15.     DBCheckBox1.Left := Rect.Left + DBGrid1.Left + 2;
  16.     DBCheckBox1.Top := Rect.Top + DBGrid1.top + 2;
  17.     DBCheckBox1.Width := Rect.Right - Rect.Left;
  18.     DBCheckBox1.Height := Rect.Bottom - Rect.Top;
  19.  
  20.     DBCheckBox1.Visible := True;
  21.     end
  22.   end
  23.   else
  24.   begin
  25.     if (Column.Field.FieldName = DBCheckBox1.DataField) then
  26.     begin
  27.       DrawRect:=Rect;
  28.       InflateRect(DrawRect,-1,-1);
  29.  
  30.       DrawState := ISChecked[Column.Field.AsBoolean];
  31.  
  32.       DBGrid1.Canvas.FillRect(Rect);
  33.       DrawFrameControl(DBGrid1.Canvas.Handle, DrawRect,
  34.                       DFC_BUTTON, DrawState);
  35.     end;
  36.   end;
  37. end;



Y luego una versión infinitamente más sencilla:



delphi
  1. procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject;
  2.   const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
  3. const
  4.   CtrlState: array[Boolean] of integer = (DFCS_BUTTONCHECK, DFCS_BUTTONCHECK or DFCS_CHECKED) ;
  5. begin
  6.   if (Column.Field.DataType=ftBoolean) then
  7.   begin
  8.     DBGrid1.Canvas.FillRect(Rect) ;
  9.     if VarIsNull(Column.Field.Value) then
  10.       DrawFrameControl(DBGrid1.Canvas.Handle,Rect, DFC_BUTTON, DFCS_BUTTONCHECK or DFCS_INACTIVE) {grayed}
  11.     else
  12.       DrawFrameControl(DBGrid1.Canvas.Handle,Rect, DFC_BUTTON, CtrlState[Column.Field.AsBoolean]) ; {checked or unchecked}
  13.   end;
  14. end;



Funcionar funciona, el problema es que al lado de checkbox me muestra true/false en la linea seleccionada del grid (el grid solo muestra informacion, no se puede editar)

Os adjunto pantallazo de como queda.

Imagen Enviada

¿Alguno sabe como evitar que muestre el True/False?

Muchas gracias.

  • 0

#2 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 31 mayo 2013 - 07:47

Es raro, yo he hecho la prueba y no tengo ese detalle

¿ Será que le asignaste algún valor al campo en tiempo de diseño ?
¿ Qué base de datos usas ? el ejemplo que muestro es con tablas paradox.

A mi me muestra únicamente el checkBox.

Saludos

Archivos adjuntos


  • 0

#3 darkerviti

darkerviti

    Member

  • Miembros
  • PipPip
  • 21 mensajes

Escrito 31 mayo 2013 - 08:01

Si, el datasource esta conectado a un clientdataset que genero en tiempo de ejecución.

El funcionamiento es el siguiente, tengo varias tablas postgresql, y al iniciar el form hago lo siguiente:



delphi
  1. procedure TDataAvailable.FormCreate(Sender: TObject);
  2. var
  3.   I : Integer;
  4.   Method, msg : string;
  5. begin
  6.   if not DM.cdsMethodShow.Active then
  7.     DM.cdsMethodShow.Open;
  8.   SetLength(Methods, DM.cdsMethodShow.RecordCount);
  9.   I := 0;
  10.   DM.cdsMethodShow.First;
  11.   With cdsPatientDataAvailable do
  12.   begin
  13.     FieldDefs.Add('id', ftInteger);
  14.     FieldDefs.Add('name', ftString, 60);
  15.     FieldDefs.Add('lastname', ftString, 60);
  16.     while not DM.cdsMethodShow.Eof do
  17.     begin
  18.       Methods[I] := DM.cdsMethodShow.FieldByName('acronym').AsString;
  19.       FieldDefs.Add(Methods[I], ftBoolean);
  20.       I := I + 1;
  21.       DM.cdsMethodShow.Next;
  22.     end;
  23.     CreateDataSet;
  24.     LogChanges := False;
  25.   end;
  26.   DM.cdsMethodShow.Close;
  27.   cdsPatientDataAvailable.Open;
  28.   if not DM.cdsPatientShow.Active then
  29.     DM.cdsPatientShow.Open;
  30.   DM.cdsPatientShow.First;
  31.   if not DM.cdsDataShow.Active then
  32.     DM.cdsDataShow.Open;
  33.   while not DM.cdsPatientShow.Eof do
  34.   begin
  35.     cdsPatientDataAvailable.Insert;
  36.     cdsPatientDataAvailable.FieldByName('id').AsInteger := DM.cdsPatientShow.FieldByName('idpatient').AsInteger;
  37.     cdsPatientDataAvailable.FieldByName('name').AsString := DM.cdsPatientShow.FieldByName('name').AsString;
  38.     cdsPatientDataAvailable.FieldByName('lastname').AsString := DM.cdsPatientShow.FieldByName('lastname').AsString;
  39.     for method in Methods do
  40.     begin
  41.       cdsPatientDataAvailable.FieldByName(method).AsBoolean := DM.cdsDataShow.Locate('method', VarArrayOf([method]),[]);
  42.     end;
  43.     cdsPatientDataAvailable.Post;
  44.     DM.cdsPatientShow.Next;
  45.   end;
  46.   ResizeDBGrid(dbgPatients);
  47.   for method in Methods do
  48.   begin
  49.     with TDBCheckBox.Create(scbxChecks) do
  50.     begin
  51.       DataField := method;
  52.       Color := dbgPatients.Color;
  53.       Name := 'dbckbx' + method;
  54.       Caption := '';
  55.       ValueChecked := 'Yes';
  56.       ValueUnchecked := 'No';
  57.     end;
  58.   end;
  59.   ResizeDBGrid(DBGrid1);
  60. end;


  • 0

#4 FerCastro

FerCastro

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 636 mensajes
  • LocationCiudad de México

Escrito 31 mayo 2013 - 10:57

Compañero

A falta del ejemplo, que tengo en casa, te dejo la página de donde tomé la solución para el problema que tu tienes

http://delphi.about....l/aa082003a.htm

El gran gurú Zarko ya lo puso hace unos añitos.

Saludos!! y espero te sirva, y si no le hallas mañana lo busco y con gusto.
  • 0

#5 darkerviti

darkerviti

    Member

  • Miembros
  • PipPip
  • 21 mensajes

Escrito 31 mayo 2013 - 07:17

Compañero

A falta del ejemplo, que tengo en casa, te dejo la página de donde tomé la solución para el problema que tu tienes

http://delphi.about....l/aa082003a.htm

El gran gurú Zarko ya lo puso hace unos añitos.

Saludos!! y espero te sirva, y si no le hallas mañana lo busco y con gusto.


Lo primero, gracias por la ayuda, justo una de las 2 versiones que tengo en pruebas esta sacada de esa web, la verdad es que ahí se encuentra muchisima información.

El tema es que sigue pasando, no se si será por que los datos están generados en un clientdataset q cargo "a mano" y no desde una db.

He encontrado una "chapuza" que me permite saltar el problema, pero me gustaría encontrar el problema.

Por ahora lo he solucionado de la siguiente forma:

Como no quería que pudiesen editar el grid, que es solo de consulta, tengo por costumbre seleccionar toda la linea, pero eso hace que me muestre los textos,  por ahora he quitado la selección de la linea completa y le he forzado a que siempre me marque la primera columna.



delphi
  1. procedure FocusCell(
  2.   const DBGrid : TDBGrid;
  3.   const column : integer) ; overload;
  4. begin
  5.   with TStringGrid(DBGrid) do
  6.   begin
  7.     Col := column;
  8.     SetFocus;
  9.   end;
  10. end;
  11.  
  12. procedure FocusCell(
  13.   const DBGrid : TDBGrid;
  14.   const fieldName : string) ; overload;
  15. var
  16.   column : integer;
  17.   idx : integer;
  18. begin
  19.   column := 0;
  20.   for idx:= 0 to -1 + DBGrid.Columns.Count do
  21.   begin
  22.     if DBGrid.Columns[idx].FieldName = fieldName then
  23.     begin
  24.       column := 1 + idx;
  25.       Break;
  26.     end;
  27.   end;
  28.  
  29.   if column > 0 then FocusCell(DBGrid,column) ;
  30. end;
  31.  
  32. procedure TDataAvailable.dbgPatientsCellClick(Column: TColumn);
  33. begin
  34.   FocusCell(dbgPatients,'id') ;
  35. end;



Si se os ocurre cualquier otra posible solución, será recibida con los brazo abiertos.

  • 0

#6 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 31 mayo 2013 - 08:21

Se me ocurre una chapuza más breve, prueba a ver si te funciona, se trata de asignar al color de la fuente de la columna en cuestión, el mismo color del fondo, lo cual haría invisibles las letras, quedaría más o menos así:



delphi
  1. procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject;
  2.   const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
  3. const
  4.   CtrlState: array[Boolean] of integer = (DFCS_BUTTONCHECK, DFCS_BUTTONCHECK or DFCS_CHECKED) ;
  5. begin
  6.   if (Column.Field.DataType=ftBoolean) then
  7.   begin
  8.     DBGrid1.Canvas.FillRect(Rect) ;
  9.     DBGrid1.Canvas.Font.Color := DBGrid1.Canvas.Brush.Color; //Esta es la línea sugerida
  10.     if VarIsNull(Column.Field.Value) then
  11.       DrawFrameControl(DBGrid1.Canvas.Handle,Rect, DFC_BUTTON, DFCS_BUTTONCHECK or DFCS_INACTIVE) {grayed}
  12.     else
  13.       DrawFrameControl(DBGrid1.Canvas.Handle,Rect, DFC_BUTTON, CtrlState[Column.Field.AsBoolean]) ; {checked or unchecked}
  14.   end;
  15. end;



No he probado.

Un saludo
  • 0

#7 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 01 junio 2013 - 06:27

Saqué un poco de tiempo y probé lo que te puse en el post anterior y no funciona.

Pero acabo de diseñar una solución que si funciona y bien, presta atención:

Primero que todo NO vamos a crear columnas para los campos booleanos, en su defecto vamos a agregar  columnas  al DbGrid pero sin asignar ningún campo en la propiedad FieldName de estas, lo único que necesitamos conocer es el índice de las recién creadas columnas.

En el ejemplo siguiente tengo 3 campos booleanos persistentes de nombres Bol1, Bol2 y Bol3  y he creado las columnas de índices, (2, 3 y 4) que dibujarán los respectivos checkbox de los tres campos.

He creado un procedimiento para dibujar cada checkBox y se lo he pasado en el evento OnDrawCollumnCell del DBgrid y funciona de maravilla.



delphi
  1. procedure TForm1.DibujarCheckBox(Grid: TDBGrid; Campo: TField; const Rect: TRect);
  2. const
  3.   CtrlState: array [Boolean] of Integer = (DFCS_BUTTONCHECK, DFCS_BUTTONCHECK or
  4.     DFCS_CHECKED);
  5. begin
  6.   Grid.Canvas.FillRect(Rect);
  7.   if VarIsNull(Campo.Value) then
  8.     DrawFrameControl(Grid.Canvas.Handle, Rect, DFC_BUTTON, DFCS_BUTTONCHECK or
  9.       DFCS_INACTIVE) { grayed }
  10.   else
  11.     DrawFrameControl(Grid.Canvas.Handle, Rect, DFC_BUTTON,
  12.       CtrlState[Campo.AsBoolean]); { checked or unchecked }
  13. end;
  14.  
  15. procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  16.   DataCol: Integer; Column: TColumn; State: TGridDrawState);
  17. begin
  18.   case DataCol of
  19.     2:
  20.       DibujarCheckBox(DBGrid1, Bol1,Rect);
  21.     3:
  22.       DibujarCheckBox(DBGrid1, Bol2, Rect);
  23.     4:
  24.       DibujarCheckBox(DBGrid1, Bol3, Rect);
  25.   end;
  26. end;



En la imagen puedes ver que tengo seleccionado un registro sin letrero alguno, espero te sirva.

Saludos.

Archivos adjuntos


  • 0

#8 darkerviti

darkerviti

    Member

  • Miembros
  • PipPip
  • 21 mensajes

Escrito 03 junio 2013 - 02:26

No he debido entender bien tu código, si no le asigno los FieldName, ¿como hago para que me pille los valores que necesito?

He probado con tu código, pasándole el valor de Column.Field y no me pinta los checkbox.

Saqué un poco de tiempo y probé lo que te puse en el post anterior y no funciona.

Pero acabo de diseñar una solución que si funciona y bien, presta atención:

Primero que todo NO vamos a crear columnas para los campos booleanos, en su defecto vamos a agregar  columnas  al DbGrid pero sin asignar ningún campo en la propiedad FieldName de estas, lo único que necesitamos conocer es el índice de las recién creadas columnas.

En el ejemplo siguiente tengo 3 campos booleanos persistentes de nombres Bol1, Bol2 y Bol3  y he creado las columnas de índices, (2, 3 y 4) que dibujarán los respectivos checkbox de los tres campos.

He creado un procedimiento para dibujar cada checkBox y se lo he pasado en el evento OnDrawCollumnCell del DBgrid y funciona de maravilla.



delphi
  1. procedure TForm1.DibujarCheckBox(Grid: TDBGrid; Campo: TField; const Rect: TRect);
  2. const
  3.   CtrlState: array [Boolean] of Integer = (DFCS_BUTTONCHECK, DFCS_BUTTONCHECK or
  4.     DFCS_CHECKED);
  5. begin
  6.   Grid.Canvas.FillRect(Rect);
  7.   if VarIsNull(Campo.Value) then
  8.     DrawFrameControl(Grid.Canvas.Handle, Rect, DFC_BUTTON, DFCS_BUTTONCHECK or
  9.       DFCS_INACTIVE) { grayed }
  10.   else
  11.     DrawFrameControl(Grid.Canvas.Handle, Rect, DFC_BUTTON,
  12.       CtrlState[Campo.AsBoolean]); { checked or unchecked }
  13. end;
  14.  
  15. procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  16.   DataCol: Integer; Column: TColumn; State: TGridDrawState);
  17. begin
  18.   case DataCol of
  19.     2:
  20.       DibujarCheckBox(DBGrid1, Bol1,Rect);
  21.     3:
  22.       DibujarCheckBox(DBGrid1, Bol2, Rect);
  23.     4:
  24.       DibujarCheckBox(DBGrid1, Bol3, Rect);
  25.   end;
  26. end;



En la imagen puedes ver que tengo seleccionado un registro sin letrero alguno, espero te sirva.

Saludos.


  • 0

#9 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 03 junio 2013 - 06:58

No he debido entender bien tu código, si no le asigno los FieldName, ¿como hago para que me pille los valores que necesito?

He probado con tu código, pasándole el valor de Column.Field y no me pinta los checkbox.


Si le pasas Column.FieldName no te los va a pintar porque justo esas columnas no tienen nada en FieldName, en ese punto justo bebes pasarle es el nombre de los campos booleanos, si estás creando el dataset dinámicamente puede hacer uso de la función FieldByName que devuelve un TField.

Saludos



delphi
  1. procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  2.   DataCol: Integer; Column: TColumn; State: TGridDrawState);
  3. begin
  4.   case DataCol of
  5.     2:
  6.       DibujarCheckBox(DBGrid1, ClientDataSet1.FieldByName('Bol1'), Rect);
  7.     3:
  8.       DibujarCheckBox(DBGrid1, ClientDataSet1.FieldByName('Bo2'), Rect);
  9.     4:
  10.       DibujarCheckBox(DBGrid1, ClientDataSet1.FieldByName('Bol3'), Rect);
  11.   end;
  12. end;


  • 0

#10 look

look

    Advanced Member

  • Miembros
  • PipPipPip
  • 418 mensajes
  • LocationLa Ceiba-Atlantida-Honduras

Escrito 03 junio 2013 - 09:50

Hola amigos ,el JvDbGrid de las JEDI tiene una propiedad que se llama EditControls la cual te permite asignar un control al campo en el grid , sea CheckBox, Combo y otros.

Saludos!
  • 0




IP.Board spam blocked by CleanTalk.