tags:

views:

170

answers:

2

Can someone help me fix this:

{$IFDEF UNICODE}
function FormatStringByteSize( TheSize: Cardinal ): string;
{ Return a cardinal as a string formated similar to the statusbar of Explorer }
var
  Buff: string;
  Count: Integer;
begin
  Count := Length(Buff);
  FillChar(Buff, Count, 0);
  ShLwApi.StrFormatByteSize( TheSize, PWideChar(Buff), Length( Buff ) * SizeOf( WideChar ) );
  Result := Buff;
end;
{$ENDIF}
+1  A: 

You need to set the length of buff first. (Length buff = 0)

Then

  1. Change TheSize to Int64 - you need this for sizes > 4GB anyway.
  2. Maybe change the call to StrFormatByteSizeW (the Delphi "headers" should have done this in D2009+)
  3. In spite of the name, FillChar expects the size to be in bytes, not characters. However this won't affect the result.
function FormatStringByteSize( TheSize: int64 ): string;
// Return an Int64 as a string formatted similar to the status bar of Explorer 
var
  Buff: string;
begin
  SetLength(Buff, 20);
  ShLwApi.StrFormatByteSizeW( TheSize, PWideChar(Buff), Length(Buff));
  Result := PChar(Buff);
end;

I can't test this in D2009/10 at moment as haven't started the move to Unicode yet (next project!) It works in D2006 with WideString.

Gerry
The call to FillChar isn't very useful anyway. Avoid the risk of calling it incorrectly (as Bill did) by not calling it at all.
Rob Kennedy
A: 

At least in Delphi 2009 (can't test in version 2010 as I don't have it) the StrFormatByteSize() function is an alias to the Ansi version (StrFormatByteSizeA()), not to the wide char version (StrFormatByteSizeW()) as it is for most of the other Windows API functions. Therefore you should use the wide char version directly - also for earlier Delphi versions, to be able to work with file (system) sizes larger than 4 GB.

There's no need for an intermediate buffer, and you can make use of the fact that StrFormatByteSizeW() returns a pointer to the converted result as a PWideChar:

{$IFDEF UNICODE}
function FormatStringByteSize(ASize: int64): string;
{ Return a cardinal as a string formatted similar to the status bar of Explorer }
const
  BufLen = 20;
begin
  SetLength(Result, BufLen);
  Result := StrFormatByteSizeW(ASize, PChar(Result), BufLen);
end;
{$ENDIF}
mghie
That's a bug in the header translation. The unadorned API should be directed to the "W" version. In fact, it is declared with PChar, which in D2009 and D2010, is the same as PWideChar. So even if you called it, it would be wrong.
Allen Bauer
Thank-you mghie... it returns a string perfectly now. Thanks Allen. I did not notice the header bug. Has StrFormatByteSize been flagged to be fixed in an update?
Bill Miller