Página principal
Artículos y trucos
Catálogo de productos
Ejemplos y descargas
Mis libros
Cursos de formación
Investigación y desarrollo
Libros recomendados
Mis páginas favoritas
Acerca del autor
 
En colaboración con Amazon
 
Intuitive Sight

Cambiar el tipo de letra de un TRichEdit

Si el lector ha intentado utilizar alguna vez el control TRichEdit para editar texto con formato, seguramente se habrá sentido frustrado al comprobar que la forma de modificar el tipo de letra (negritas, itálicas, subrayados) es muy diferente en comparación con la forma de modificación de los procesadores de texto más populares. Al menos, si ha seguido al pie de la letra los ejemplos de la propia Borland para este componente.

Voy a simplificar un poco la técnica de Borland para una mejor presentación. Supondremos que existe un componente TAction, al cual llamaremos acNegritas, que será asociado a un botón de la barra de herramientas y a un comando del menú. Para la acción, debemos definir manejadores para sus eventos OnUpdate (¿está el texto en negritas, o no?) y OnExecute (activar o desactivar las negritas). El código "tradicional" se muestra a continuación:

procedure TForm1.acNegritasUpdate(Sender: TObject);
begin
   if RichEdit1.SelLength > 0 then
      acBold.Checked := fsBold in RichEdit1.SelAttributes.Style
   else
      acBold.Checked := fsBold in RichEdit1.DefAttributes.Style;
end;

procedure TForm1.acNegritasExecute(Sender: TObject);
var
   TextAttrs: TTextAttributes;
   Style: TFontStyles;
begin
   if RichEdit1.SelLength > 0 then
      TextAttrs := RichEdit1.SelAttributes
   else
      TextAttrs := RichEdit1.DefAttributes;
   Style := TextAttrs.Style;
   if fsBold in Style then
      TextAttrs.Style := Style - [fsBold]
   else
      TextAttrs.Style := Style + [fsBold];
end;

TRichEdit tiene dos propiedades públicas, SelAttributes y DefAttributes, que contienen el tipo de letra de la selección actual y el tipo de letra por omisión, respectivamente. En el ejemplo, cuando no hay selección cambiamos o preguntamos por el tipo de letra por omisión. No es eso lo que hace WordPad, sin ir demasiado lejos: si no hay selección, este programa cambia el tipo de letra de la palabra dentro de la cuál está situado el cursor.

¿Podemos lograr ese mismo efecto? Sí, pero a condición de que renunciemos a las propiedades SelAttributes y DefAttributes. El método siguiente muestra cómo cambiar el atributo de negritas a nuestro gusto personal:

procedure TForm1.acNegritasExecute(Sender: TObject);
var
   Format: TCharFormat;
begin
   FillChar(Format, SizeOf(TCharFormat), 0);
   Format.cbSize := SizeOf(TCharFormat);
   Format.dwMask := CFM_BOLD;
   if not (fsBold in RichEdit1.SelAttributes.Style) then
      Format.dwEffects := CFE_BOLD;
   SendMessage(RichEdit1.Handle, EM_SETCHARFORMAT,
      SCF_SELECTION or SCF_WORD, LPARAM(@Format))
end;

El tipo TCharFormat está declarado en la unidad RichEdit, al igual que las constantes utilizadas. Observe que vamos a ignorar completamente el tipo de letra por omisión.

¿Por qué la VCL de Delphi no hace directamente lo que queremos? Si miramos la implementación de la clase TTextAttributes, en específico el método SetAttributes, veremos que Delphi utiliza solamente la constante SCF_SELECTION en el wParam del mensaje EM_SETCHARFORMAT. Lamentablemente, no es sencillo crear una clase derivada de TRichEdit que corrija este fallo, por culpa del mal diseño del componente.