سؤال

I need to calculate the total size of all components in my setup. Because of some custom code I cannot use Inno Setup's internal feature for that.

The problem was that the components share a lot of files. So I defined a string for every component which contains variables for the files they use. I then have these strings added into a single string and if a certain variable is found in this string, then the size of the file in bytes is added to the variable "size" of type Single. In the end "size" shows how much space is needed for the installation.

Actually this works pretty well, but I then want to show the size in GB in the next page. But the function FloatToStr adds a lot of numbers after the decimal point whereas I just want to have two.

Here's the script (the problem occurs in the very last lines):

function NextButtonClick(CurPageID: Integer): Boolean;
var
  size: Single;

  if (CurPageID = wpSelectDir) then { I have swapped the Components and SelectDir pages }
  begin

  size := 0; { this will contain the size in the end }
  xg := '';  { this is the string which contains the list of files needed by every single component }
  for I := 0 to GetArrayLength(ComponentArray) - 1 do
  if IsComponentSelected(ComponentArray[I].Component) then
  begin
    xg := xg + ComponentArray[I].GCF; 
  end;    
  { here the files are being added to the string, everything's working as intended.. }


  MsgBox(xg, mbInformation, MB_OK); { this is for testing if the string has been created correctly }
  if Pos('gcf1', xg) > 0 then size := size + 1512820736; { here the Pos-function searches for the given string and if it is found it adds the value to "size", ok... }
  if Pos('gcf2', xg) > 0 then size := size + 635711488;
  if Pos('gcf3', xg) > 0 then size := size + 286273536;
size := size / 1024 / 1024 / 1024; { now all sizes have been added and the number is converted to be displayed GB, not bytes }
  { Format('%.2n', [size]); }
  { size := (round(size * 10) / 10); }
  { size := Format('%.2n', [size]); }
  { FloatToStr(size); }
  MsgBox(FloatToStr(size), mbInformation, MB_OK); { Here the size is shown but with several unneeded places after the decimal point (2.267589569092) }
  end;
end;

As you can see, I tried several things to get rid of the numbers. The problem is the FloatToStr function in the MsgBox, it automatically adds all the numbers. If I choose the type Integer for "size" it still shows that long number but I cannot use Integer and IntToStr in the MsgBox (what would solve the problem), because the numbers handled here are too big and I want to have two decimal places after the point.

I also tried to put the Format function into the MsgBox but I got a "Type mismatch" error as well.

FloatToStrF is not supported by Inno Setup.

Converting "size" using FloatToStr beforehand and truncating it didn't work as well, because the compiler checks what type "size" was declared as and insists on using FloatToStr in the MsgBox again.

I have no clue how to round this number up. Maybe some different approach would help?

I am looking forward to your answers!

هل كانت مفيدة؟

المحلول

You can use the Format function.

Take a look at this example:

procedure TestClick(Sender: TObject);
var
  Size: Extended;
begin
  Size := 0;
  Size := Size + 1512820736
  Size := Size + 635711488;
  Size := Size + 286273536;
  Size := Size / 1024 / 1024 / 1024; { now all sizes have been added and the number is converted to be displayed GB, not bytes }
  MsgBox(Format('%.2f Gb.', [Size]), mbInformation, MB_OK); 
end;

I'm changing the data type from Single to Extended, take it as a personal choice.

Or use this function as a smarter choice to add the correct dimensional depending on the byte count:

const
  KFactor = 1024;

function FormatBytes(const Bytes: Extended): string;
var
  Amount: Extended;
  Idx: Byte;
  Dms: array[1..5] of string;
  FmtStr: string;
begin
  Dms[1] := 'B'; Dms[2] := 'KB'; Dms[3] := 'MB'; Dms[4] := 'GB'; Dms[5] := 'TB';
  Amount := Bytes;
  Idx := 1;
  while Amount > (0.9 * KFactor) do
  begin
    Idx := Idx + 1;
    Amount := Amount / KFactor;
  end;
  if Abs(Amount - Trunc(Amount)) < 0.07 then
    FmtStr := '%.0f %s'
  else
    FmtStr := '%.2f %s';
  Result := Format(FmtStr, [Amount, Dms[Idx]]);
end;

Answer edited to adjust the number of decimal places in case of a near exact amount of KB/MB/GB/TB is to be shown.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top