I'm trying to display the minus symbol of a negative number on the left side of an Item in a TListview
that has his property BiDiMode = bdRightToLeft.
I tried the code there:
Function TfrmProjets.IfSign(floatValue: double; howMuchDecimalAfterComa:
integer):string;
var
strResult: string;
strZero: string;
i: integer;
begin
strResult := '';
strZero := '';
for i := 0 to howMuchDecimalAfterComa -1 do
begin
strZero := strZero + '0';
end;
if(Sign(floatValue) = NegativeValue)then
begin
strResult := '-' + FormatFloat('0.' + strZero,Abs(floatValue));
//strResult := '(' + FormatFloat('0.' + strZero,Abs(floatValue)) + ')';
end
else
begin
strResult := FormatFloat('0.' + strZero,floatValue);
end;
result := strResult;
end;
And in fact it work when I use breakpoint to evaluate strResult
.
But when it come to TListView
display in my item:
lvItem := lvPeriodic[0];
lvItem.SubItems.Add(IfSign(-14.2),1) + '%') ;
It display like this: 14.2%-
Is there a way to tell the TListview
not to change the string I'm displaying or something?
Assuming you are using a unicode version of delphi, you can supply explicit RTL and LTR marks to force the position of language neutral or weak characters (like dash -
, exclamation !
, etc).
The rules for parsing LTR and RTL text in various contexts are extensive and complex. For reference you can find the bidirectional algorithm specification here. One pass for weak characters does parse European numbers as LTR (which is why 14.2%
ends up in the correct direction, but the use of the dash -
to indicate minus introduces ambiguity. One would think that substituting a proper minus sign U+2212
would work but this is also a weak character, presumably because arabic numbers can be negative as well (and would need to be rendered in the opposite direction...I'm not sure).
In any case - moving on, we can construct a function like this to force a string into a strict LTR order :
function StrictLTR(const s : string) : string;
const
LTR_EMBED = Char($202A);
POP_DIRECTIONAL = Char($202C);
begin
result := LTR_EMBED + s + POP_DIRECTIONAL;
end;
This places an embedded Left-To-Right character (U+202A
) before the string and follows it with a Pop-Directional-Formatting (U+202C
) character. The latter removes the embedded directional formatting cue and returns the text direction to whatever it was in the previous context. The returned string, therefore, is safe to use in either an RTL or LTR context.
Calling this, then :
ListView1.AddItem(StrictLTR(IfSign(-14.2,1) + '%'), nil);
Will produce the desired result.
As an aside, your IfSign
function can be greatly simplified by using the Format
function :
Function IfSign(floatValue: double; numberOfDecimalPlaces:integer):string;
begin
result := Format('%.'+IntTostr(numberOfDecimalPlaces)+'f', [floatValue]);
end;