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.
|