2011. május 23., hétfő
Set the character format in a TRichEdit to subscript or superscript
Problem/Question/Abstract:
I need to set the character format in a RichEdit control to subscript or superscipt. When I produce an RTF file including this formatting, the Delphi TRichEdit shows it correctly. But I cannot set the formatting by code. I tried to send a EM_SETCHARFORMAT message to the TRichEdit with dwEffects set to CFE_SUBSCRIPT but this doesn't have the desired effect.
Answer:
Solve 1:
You have to use a little API here since the TTextAttributes class used to implement DefAttributes does not surface this ability (since it was designed to be compatible to TFont). You should be able to set sub/ superscripts by sending an EM_SETCHARFORMAT message to a TRichedit. Something like this:
var
format: TCharFormat; {defined in Unit RichEdit}
FillChar(format, sizeof(format), 0);
with format do
begin
cbSize := Sizeof(format);
dwMask := CFM_OFFSET;
yOffset := 60; {superscript by 60 twips, negative values give subscripts}
end;
richedit1.Perform(EM_SETCHARFORMAT, SCF_SELECTION, LongInt(@format));
The message affects the current selection. If there is none it will affect new text inserted via seltext.
The problem with this is that the rich edit common control version 1 does not properly adjust the line spacing in lines containing super- or subscripted text. So if you don't reduce the font size as well, the text may be cut off at top or bottom. This version of the control also has no way to manually adjust the linespacing. There are wrappers for version 2 and 3 of the control around, e.g. the TRxrichEdit component in RXLib. These versions handle sub/superscripted text correctly but they require riched20.dll on the target system and it may not be present on all of them.
Solve 2:
Pressing the Up arrow sets to SuperScript, the down arrow to SubScript and the Left arrow back to normal.
procedure TForm1.RichEdit1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
var
ref: TCharFormat;
begin
FillChar(ref, sizeof(ref), 0);
if ssAlt in Shift then
case Key of
VK_UP:
begin
with ref do
begin
cbSize := Sizeof(ref);
dwMask := CFM_OFFSET;
yOffset := 60;
end;
end;
VK_DOWN:
begin
with ref do
begin
cbSize := Sizeof(ref);
dwMask := CFM_OFFSET;
yOffset := -60;
end;
end;
VK_LEFT:
begin
with ref do
begin
cbSize := Sizeof(ref);
dwMask := CFM_OFFSET;
yOffset := 0;
end;
end;
end;
(Sender as TRichEdit).Perform(EM_SETCHARFORMAT, SCF_SELECTION, LongInt(@ref));
end;
Solve 3:
{ ... }
type
TCharacterFormat = (CFM_Superscript, CFM_Subscript, CFM_Normal);
procedure RE_SetCharFormat(RichEdit: TRichEdit; CharacterFormat: TCharacterFormat);
var
{The CHARFORMAT structure contains information about character formatting
in a rich edit control}
Format: TCharFormat;
begin
FillChar(Format, SizeOf(Format), 0);
with Format do
begin
cbSize := SizeOf(Format);
dwMask := CFM_OFFSET;
{Character offset, in twips, from the baseline. If the value of this member
is positive, the character is a superscript; if it is negative, the
character is a subscript}
case CharacterFormat of
CFM_Superscript: yOffset := 60;
CFM_Subscript: yOffset := -60;
CFM_Normal: yOffset := 0;
end;
end;
{The EM_SETCHARFORMAT message sets character formatting in a rich edit control.
SCF_SELECTION: Applies the formatting to the current selection}
Richedit.Perform(EM_SETCHARFORMAT, SCF_SELECTION, Longint(@Format));
end;
Examples:
{Apply Subscript to the current selection}
procedure TForm1.Button1Click(Sender: TObject);
begin
RE_SetCharFormat(RichEdit1, CFM_Superscript);
end;
{Apply subscript to the current selection}
procedure TForm1.Button2Click(Sender: TObject);
begin
RE_SetCharFormat(RichEdit1, CFM_Subscript);
end;
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése