Cómo hacer que DBGrid dibuje Sí/No en lugar de Verdadero/Falso

Estoy tratando de reemplazar Verdadero/Falso con Sí/No en un DBGrid. El siguiente código casi funciona:

procedure TDatamodule1.DBGridDrawColumnCell(Sender: TObject;
  const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);

  var
    sText : String;

begin
  if (UpperCase(Column.Field.FieldName) = UpperCase('Approved')) or
     (UpperCase(Column.Field.FieldName) = UpperCase('Obsolete')) then
    begin
      if Column.Field.Value = True then
        sText := 'Yes'
      Else
        If Column.Field.Value = False Then
          sText := 'No'
        Else
          sText := '';
      (Sender as TDBGrid).Canvas.FillRect(Rect);
      (Sender as TDBGrid).Canvas.TextRect(Rect, Rect.Left+3, Rect.Top+2, sText);
    end;
end;

Esto pareció funcionar hasta que comencé a usar las teclas de cursor del teclado para moverme por la cuadrícula. La celda que tiene el foco siempre tiene tanto Verdadero como Sí o Falso y No dibujados uno encima del otro. ¿Cómo evito que se dibuje la etiqueta predeterminada Verdadero/Falso en la celda que tiene el foco? Todas las demás celdas de la cuadrícula son perfectas.

Editar: no mencioné que la cuadrícula está configurada en Solo lectura y me di cuenta de que el problema está tanto seleccionado como enfocado. Gracias por adelantado.

preguntado el 10 de septiembre de 13 a las 01:09

Utilice el depurador para descubrir el origen del problema. ¿Ya está dibujado el texto no deseado cuando ingresa este controlador de eventos? Si es así, entonces necesita hacer un mejor trabajo encubriéndolo. De lo contrario, debe encontrar dónde se dibuja y luego determinar qué condición debe efectuar para suprimir esa pintura posterior. En cuanto a sus problemas de enfoque y selección, preste atención a las State parámetro. -

gracias roberto Me tomó bastante tiempo, pero como puede ver en la respuesta que publiqué. Eventualmente lo descubrí. También quiero agradecer a todos por las otras respuestas a continuación. Son mucho más elegantes que redibujar; sin embargo, tengo planes más grandes para esta técnica y debo aceptar mi propia solución. Mi pregunta principal era cómo evito que DBGrid dibuje mis cambios. De nuevo, gracias a todos. -

4 Respuestas

Una solución simple sería configurar su campo booleano DisplayValues:

MyField.DisplayValues := 'Yes;No';

Respondido el 10 de Septiembre de 13 a las 10:09

Una forma de lograr esto es establecer un controlador de eventos OnGetText para estos campos. Si tiene campos estáticos, puede configurarlos durante el tiempo de diseño. Con campos dinámicos puedes hacerlo en el evento FormCreate.

procedure TMyForm.MyFieldGetText(Sender: TField; var Text: string; DisplayText: Boolean);
begin
  if Sender.AsBoolean then
    Text := 'Yes'
  else
    Text := 'No';
end;

Respondido el 10 de Septiembre de 13 a las 07:09

Uwe, todavía no estoy lo suficientemente familiarizado con Delphi para entender cómo aplicar esto a los campos "dinámicos". En este caso, mi conjunto de datos de cliente no tiene estructura hasta que se ejecuta la consulta de la base de datos (tengo varias consultas). Un procedimiento MyFieldGetText me confunde cuando "MyField" no se conoce hasta después de la consulta. Debo decir que estoy realmente impresionado con la profundidad del conocimiento aquí en SO, ¡es bastante humillante para el principiante! - Mike

Yo diría que estás trabajando en el nivel equivocado de abstracción. Use dos columnas calculadas (AFlag y OFlag en el ejemplo a continuación) y defina un evento OnCalcFields para su conjunto de datos de cliente. El siguiente código se adjunta a un conjunto de datos llamado 'qCpap'.

procedure TView.qCpapCalcFields(DataSet: TDataSet);
begin
 if qCpapApproved.AsBoolean 
  then qCpapAFlag.AsString:= 'Yes'
  else qCpapAFlag.AsString:= 'No';

 if qCpapObsolete.AsBoolean 
  then qCpapOFlag.AsString:= 'Yes'
  else qCpapOFlag.AsString:= 'No';
end;

Por cierto, no tiene sentido usar la función 'mayúsculas' en una constante de cadena: también puede escribir la cadena en mayúsculas usted mismo.

Respondido el 10 de Septiembre de 13 a las 04:09

No'am, gracias por la respuesta. Preferiría volver a dibujar en lugar de tener campos de cálculo, ya que puedo usar este concepto para otros propósitos. Si no se puede volver a dibujar, probaré tu sugerencia. Anotado en el comentario en mayúsculas, está ahí por mi propia pereza. Si alguna vez lo edito más tarde, no tengo que preocuparme por usar el caso incorrecto. - Mike

@Mike: intente mirar el evento OnGetData de los campos. Nunca he usado esto, pero creo que puedes sobrecargarlo y sustituir tus valores aquí. Sería mucho más simple que su método. - No soy Newman

Resolví mi problema con mucha prueba y error. Primero, en los componentes de DBGrid configuré dgEditing en falso porque no era necesario (mi cuadrícula es de solo lectura). Esto evita que el usuario coloque la celda en el modo enfocado. En segundo lugar, establecí DefaultDrawing en False. Actualicé mi procedimiento DBGridDrawColumnCell de la siguiente manera:

procedure TDatamodule1.DBGridDrawColumnCell(Sender: TObject;
  const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);

  var
    sText : String;

begin
  if gdselected in state then { set proper colors if cell is selected }
    Begin
      (Sender as TDBGrid).Canvas.Font.Color := 
        TStyleManager.ActiveStyle.GetSystemColor(clwindowtext);
      (Sender as TDBGrid).Canvas.Brush.Color := 
        TStyleManager.ActiveStyle.GetSystemColor(clhighlight);
    End;

  if (UpperCase(Column.Field.FieldName) = 'APPROVED') or
     (UpperCase(Column.Field.FieldName) = 'OBSOLETE')) then
    begin
      if Column.Field.Value = True then
        sText := 'Yes'
      Else
        If Column.Field.Value = False Then
          sText := 'No'
        Else
          sText := '';
      (Sender as TDBGrid).Canvas.FillRect(Rect);
      (Sender as TDBGrid).Canvas.TextRect(Rect, Rect.Left+3, Rect.Top+2, sText);
    end
  Else
    Begin { I added this to draw all other columns as defaultdrawing is off }
      (Sender as TDBGrid).defaultdrawcolumncell(Rect, DataCol, Column, State);
    End;
end;

Respondido el 10 de Septiembre de 13 a las 06:09

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.