Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   TDbGrid con un campo RTF. ¿Se puede visualizar como texto plano? (https://www.clubdelphi.com/foros/showthread.php?t=77818)

TiammatMX 28-02-2012 16:43:13

TDbGrid con un campo RTF. ¿Se puede visualizar como texto plano?
 
Pues éso, chic@s, tengo varios campos que contienen texto RTF, con formatos bonitos, etcétera..., pero que a la hora de desplegarse en un TDbGrid se ven como un batiburrillo de letras, códigos y hasta groserías aparecen...

¿Hay alguna manera (que no sea utilizando componentes de terceros, tengo la imposición que de no usarlos) de mostrar los campos con contenido RTF en texto plano, solamente en el TDbGrid?:confused:

Acepto todas las ideas, por alocadas que parezcan.

duilioisola 28-02-2012 18:17:39

Esto es algo que utilizo que puedes modificar a tu gusto...
Recibe un campo blob, donde hay notas en formato RTF.
Las mete dentro de un TRichEdit.
Devuelve la propiedad Text del TRichEdit, que no tiene formato.
Nota: TRichEdit es parte de Delphi.
Código Delphi [-]
function TFMain.DameTexto(Campo: TBlobField): string;
var
  MS : TMemoryStream;
  RichEdit : TRichEdit;
begin
  RichEdit := TRichEdit.Create(Self);
  MS := TMemoryStream.Create;
  try
     RichEdit.Parent := Self;
     RichEdit.Visible := False;
     Campo.SaveToStream(MS);
     MS.Position := 0;
     RichEdit.Lines.LoadFromStream(MS);
     Result := RichEdit.Lines.Text;
  finally
     MS.Free;
     RichEdit.Free;
  end;
end;

Al González 28-02-2012 19:07:44

Hola Felipe.

Como ilustra duilioisola, es la propiedad Lines.Text del cuadro de texto rico (o enriquecido) la que devuelve su contenido sin formato.

Dado que el texto se encuentra en un campo, puedes asociar a éste un objeto TDBRichEdit (visible o invisible), y añadir a la tabla un campo calculado de tipo String para mostrar en la rejilla. Así, en el evento OnCalcFields del conjunto de datos, asignas ese Lines.Text al campo calculado:

Código Delphi [-]
DataSet ['CampoCalc'] := DBRichEdit1.Lines.Text;

Saludos. :)

Al González.

Chris 28-02-2012 21:45:31

Cita:

Empezado por Al González (Mensaje 426372)
Dado que el texto se encuentra en un campo, puedes asociar a éste un objeto TDBRichEdit (visible o invisible), y añadir a la tabla un campo calculado de tipo String para mostrar en la rejilla. Así, en el evento OnCalcFields del conjunto de datos, asignas ese Lines.Text al campo calculado:

Apreciado amigo Al, sino me estoy equivocando, creo que lo que sugieres no funcionaría en este caso. Para dibujar un TDBGrid Delphi no necesariamente notifica a los controles que el cursor se ha movido. Esto ocacionará que dibujes sobre el TDBGrid el texto almacenado en el último registro que fue seleccionado. Otro de los sintomas sería que dibujes texto en blanco al abrir el formulario ya que la clase TDatasource notifica a los controles luego de dibujar el TDBGrid.

Saludos!

Chris 28-02-2012 22:00:06

Puedes revisar esta entrada en StackOverflow. En ella se da un ejemplo de como dibujar el contenido de un Richedit utilizando la interfaz Windowless Rich Edit.

Nuevamente repito, el código de ejemplo en la entrada de StackOverflow documenta como dibujar el texto rico sobre el un objeto TCanvas. Sin embargo si lo que deseas es dibujar un extracto en texto plano, en lugar de hacer la llamada a TxDraw, hazla a TxGetText.

Talvez te hallas quedado con una gran incógnita con lo que te he dicho. Pero si lees el código que te cité verás que realmente está fácil.

Saludos!

TiammatMX 28-02-2012 22:07:02

Cita:

Empezado por Chris (Mensaje 426411)
...Talvez te hallas quedado con una gran incógnita con lo que te he dicho. Pero si lees el código que te cité verás que realmente está fácil...

Pues sí, me quedé con una ENORME incógnita, sobre todo por el hecho de que necesito mostrar el texto de varios campos tipo VarChar (de MS SQL Server 2008 R2) que contienen sendos textos formateados vía TRichEdit, pero que el usuario quiere que en un TDbGrid se muestre únicamente el texto, sin el formato; si en algún momento desea editarlos, le proveo de una ventana donde puede hacerlo.

El punto es que ya tengo CASI todo controlado, excepto el mostrar el texto en el TDbGrid en su correspondiente columna.

roman 28-02-2012 22:19:34

Cita:

Empezado por Chris (Mensaje 426409)
Apreciado amigo Al, sino me estoy equivocando, creo que lo que sugieres no funcionaría en este caso. Para dibujar un TDBGrid Delphi no necesariamente notifica a los controles que el cursor se ha movido. Esto ocacionará que dibujes sobre el TDBGrid el texto almacenado en el último registro que fue seleccionado. Otro de los sintomas sería que dibujes texto en blanco al abrir el formulario ya que la clase TDatasource notifica a los controles luego de dibujar el TDBGrid.

Saludos!

¡Ah caray! Pero esto significaría que ningún campo calculado podría mostrarse en un DBGrid, pero lo cierto es que sí se puede.

// Saludos

Chris 28-02-2012 23:12:40

Cita:

Empezado por roman (Mensaje 426413)
¡Ah caray! Pero esto significaría que ningún campo calculado podría mostrarse en un DBGrid, pero lo cierto es que sí se puede.

// Saludos

Creo que no en este caso. El campo depende de la propiedad de un control (DBRichEdit1) que necesariamente no estará actualizado cuando sea leída la propiedad.

En lo personal preperiría utilizar el evento OnGetText para este caso. Por ejemplo:

Código Delphi [-]
procedure Form1.OnShow(sender: tobject);
begin
    DataSet1.FieldByName('texto_rico').OnGetText := FormatRTF2Text;
end;

function FormatRTF2Text(Sender: TField;
                        var Text: String;
                        DisplayText: Boolean);
begin
    if DisplayText then
    begin
        // utilizar el código de duilioisola
        // para convertir el texto rico a plano
        
        Text := texto_plano;
    end;
end;

Saludos!

TiammatMX 29-02-2012 00:10:45

Como siempre, la solución en varios pasos.

Paso 1.- Al TADOQuery que utilizo para obtener los datos de la rejilla, debo extraerle los nombres de campos hasta llegar al evento OnGetText de cada uno.

Paso 2.- En el dicho evento OnGetText, le incluímos un poquito de código de ésta manera:
Código Delphi [-]
procedure TfrmPrncpl.QueryCampoGetText(Sender: TField; var Text: String; DisplayText: Boolean);
var
  redtTemporal : TRichEdit;
  sTexto : string;
begin
  redtTemporal := TRichEdit.Create(Self);
  with redtTemporal do
  begin
    Parent := frmPrncpl;
    redtTemporal.Text := Query.FieldValues['Campo'];
    redtTemporal.PlainText := True;
    sTexto := redtTemporal.Lines.Text;
    Destroy;
  end;
  Text := sTexto;
end;
Como podemos apreciar, creo un TRichEdit "al vuelo", lo utilizo como "traductor" de los datos contenidos en el campo y devuelvo el texto resultante para ser mostrado en el TDbGrid.

Añado la solución para futuras referencias, sobre todo, mías... jajajajajaja

Al González 29-02-2012 00:12:15

Cita:

Empezado por Chris (Mensaje 426409)
[...] sino me estoy equivocando, creo que lo que sugieres no funcionaría en este caso [...]

Cita:

Empezado por roman (Mensaje 426413)
¡Ah caray! Pero esto significaría que ningún campo calculado podría mostrarse en un DBGrid, pero lo cierto es que sí se puede.

Hola Chris, muchas gracias por la aclaración, tienes razón en lo que dices. :)

Aunque ciertamente depende de cómo sea implementado cada derivado de TDataSet, lo cierto es que la mayoría (TClientDataSet, ADO, IBX, etc.) hacen el cálculo del buffer de registro mucho antes de informar a los enlaces de datos visuales de cualquier movimiento.

Román, esto es similar a aquel asunto del OnValidate que tuvimos el gusto de compartir. :)

En conclusión, un evento OnCalcFields puede asumir que el valor de cualquiera de los campos es del mismo registro cuyos campos calculados se van a actualizar, pero no necesariamente serán los mismos valores mostrados en los controles de datos.

Siendo así, creo que yo también usaría un evento OnGetText o aún un campo calculado (dependiendo de si el campo original va a estar visible o no al mismo tiempo como texto rico), pero eso sí, con un TRichEdit en lugar de TDBRichEdit, al estilo de las sugerencias anteriores. Y claro, con un poco más de tiempo, optar por llamadas directas a la API de Windows no sería mala idea tampoco.

Un abrazo corregido.

Al González.

roman 29-02-2012 01:02:05

Cita:

Empezado por Chris (Mensaje 426419)
Creo que no en este caso. El campo depende de la propiedad de un control (DBRichEdit1)

Tienes razón. Había obviado la parte de que se hablaba de un DBRichEdit.

// Saludos

Al González 29-02-2012 01:09:51

Hola Felipe.

Viendo ahora la solución que obtuviste, si te resultó satisfactoria me permito sugerirte que uses el mismo manejador de evento OnGetText para todos esos campos (no tiene que ser un OnGetText por cada campo). También, con tu debido permiso, me tomo la libertad de mejorarlo un poco:

Código Delphi [-]
procedure TfrmPrncpl.QueryCampoRTFGetText(Sender: TField; var Text: String; DisplayText: Boolean);
Var
  AText :String Absolute Text;  // Trampilla para meter el parámetro "Text" al With
begin
  With TRichEdit.Create (Nil) Do  // Construimos el objeto "al vuelo" (sin usar una variable)
    Try
      Visible := False;  // Evitamos efecto de "parpadeo"
      Parent := frmPrncpl;  // Para que no marque error al leer su texto
      Text := Sender.AsString;  // Asignamos el valor de cualquiera que sea el campo RTF en turno (Sender)
      AText := Lines.Text;  // Esto devuelve texto plano aunque PlainText sea False
    Finally  // Try-Finally asegura que siempre se llamará a lo que esté en Finally (aunque haya error)
      Free;  // Convencionalmente es preferible llamar a Free que a Destroy 
    End;
end;

Sin olvidar que debe estar ComCtrls en el Uses.

Saludos. :)

Chris 29-02-2012 02:50:34

Solo quiero añadir que en el código del evento OnGetText no se debe menospreciar la variable DisplayText. Esto lo digo porque hay algunas malas implementaciones que en lugar de llamar a:
Field.Value, hacen la llamada a Field.DisplayText(DisplayText=False) suponiendo que DisplayText con la condicional en False devolverá el valor verdadero o original el campo, lo cual no puede ser cierto dependiendo de la condición DisplayText y más aún si el programador ignoró esta variable al momento de la implementación de GetText.

Saludos!

roman 29-02-2012 16:47:49

Cita:

Empezado por Al González (Mensaje 426431)
Código Delphi [-]
procedure TfrmPrncpl.QueryCampoRTFGetText(Sender: TField; var Text: String; DisplayText: Boolean);
Var
  AText :String Absolute Text;  // Trampilla para meter el parámetro "Text" al With

Hombre, también queda la opción de cambiar el nombre del parámetro :)

// Saludos

TiammatMX 29-02-2012 16:57:05

Cita:

Empezado por Al González (Mensaje 426431)
Hola Felipe.

Viendo ahora la solución que obtuviste, si te resultó satisfactoria me permito sugerirte que uses el mismo manejador de evento OnGetText para todos esos campos (no tiene que ser un OnGetText por cada campo). También, con tu debido permiso, me tomo la libertad de mejorarlo un poco:

...

Sin olvidar que debe estar ComCtrls en el Uses.

Saludos. :)

¿Un poco? Quedó soberbia... :eek::eek::eek:

Y bien, hoy aprendí algo acerca del RTF. NUNCA utilizarlo voluntariamente a menos que sea de extrema necesidad. Demasiado complicado.

roman 29-02-2012 17:02:41

Cita:

Empezado por tiammat (Mensaje 426512)
Y bien, hoy aprendí algo acerca del RTF. NUNCA utilizarlo voluntariamente a menos que sea de extrema necesidad. Demasiado complicado.

Pues no veo que usar el evento OnGetText sea demasiado complicado. Simplemente es algo nuevo. Pero de ahí a descalificar el uso de un RichEdit por esa razón me parece que está de más.

La parte que a mi no me queda claro es qué logran ver de un richedit en una sólo línea del dbgrid. Vamos, que me parece que un DBGrid no es el control adecuado para visualizar campos de texto, sean richedit o memos.

// Saludos

TiammatMX 29-02-2012 17:50:45

Cita:

Empezado por roman (Mensaje 426514)
Pues no veo que usar el evento OnGetText sea demasiado complicado. Simplemente es algo nuevo. Pero de ahí a descalificar el uso de un RichEdit por esa razón me parece que está de más...

Es que no es nada más el OnGetText, Román. Tu estás viendo la última estación de un periplo por TRichEdit que comenzó para mí desde el viernes, y además comenzando con todas las de la ley, DESDE CERO. Gracias a la ocurrencia de mi patrón de que quiere darle a los usuarios la posibilidad de "embellecer" el texto (ni idea de para qué lo querrían, siendo médicos) y tener control sobre el texto.

Cita:

Empezado por roman (Mensaje 426514)
...La parte que a mi no me queda claro es qué logran ver de un richedit en una sólo línea del dbgrid. Vamos, que me parece que un DBGrid no es el control adecuado para visualizar campos de texto, sean richedit o memos...

Estoy de acuerdo contigo, Román. Hay controles que CASI permiten hacer de todo, y si no pueden, les damos una ayudadita. ¿Para qué ver solamente una línea de texto? Lo mismo me pregunto yo, pero "donde manda capitán no gobierna marinero". Es el problema de ser un programador subcontratado, la creatividad debes dejarla en casa, tristemente.:(

roman 29-02-2012 18:03:43

Cita:

Empezado por tiammat (Mensaje 426517)
Gracias a la ocurrencia de mi patrón de que quiere darle a los usuarios la posibilidad de "embellecer" el texto (ni idea de para qué lo querrían, siendo médicos) y tener control sobre el texto.

Je, je. ¿Has visto la letra que tienen los médicos? Por una vez que lo que escriban se vea bonito :D

// Saludos

Al González 01-03-2012 01:47:26

Cita:

Empezado por roman (Mensaje 426507)
Hombre, también queda la opción de cambiar el nombre del parámetro :)

Touché. :)

Es verdad, Román. Aunque dejar el nombre como está fue involuntario, creo que se debe a mi arraigada costumbre de respetar los nombres de los parámetros como fueron declarados originalmente, esto en métodos virtuales redefinidos y de igual manera en manejadores de eventos, como fue el caso anterior.

Felipe: te recomiendo la fuente Arial Drunk para esos textos, creo que es la que los médicos prefieren. :D

(para mi querido hermano: es chiste, no te ofendas ;))

roman 01-03-2012 02:01:34

En todo caso, una trampilla muy ingeniosa :). Creo que nunca he visto un uso real de absolute.

// Saludos


La franja horaria es GMT +2. Ahora son las 08:15:38.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi