Switches

During the last weeks it happened often that I had to write some command line apps. The reason for this is that more and more things are running automatically in tools like FinalBuilder (I will write an article about this later).

One thing that makes the command line app life easier is the encapsulation of the switches in a record (Current Delphi versions allow records with methods).

type
  TSwitches = record
  strict private const
    cHelpSwitch = '?';
    cBackupCountSwitch = 'c';
  public
    class function BackupCount: Integer; static;
    class function Help: Boolean; static;
    class procedure PrintHelp; static;
  end;

...

class function TSwitches.BackupCount: Integer;
var
  sCount: string;
begin
  FindCmdLineSwitch(cBackupCountSwitch, sCount);
  TryStrToInt(sCount, Result);
end;

class function TSwitches.Help: Boolean;
var
  sHelp: string;
begin
  Result := (ParamCount = 0) or (FindCmdLineSwitch(cHelpSwitch, sHelp));
end;

class procedure TSwitches.PrintHelp;
begin
  Writeln(Format(SUsageSample, [TDBSwitches.cBackupFolderSwitch, TDBSwitches.cBackupCountSwitch]));

  Writeln;
  Writeln(SOptions);
  Writeln;

  Writeln(Format(SHelpSwitch, [TDBSwitches.cHelpSwitch]));
  Writeln(Format(SBackupCountSwitch, [TDBSwitches.cBackupCountSwitch]));
end;

This record can be used directly in the .dpr file.

begin
  if TDBSwitches.Help then
    TDBSwitches.PrintHelp
  else
    TDBWork.DeleteBackup(TDBSwitches.BackupFolder, TDBSwitches.BackupCount);
end.
Posted in Tips and Tricks | Tagged | Comments Off on Switches

try…finally for multiple objects

Today I found another common mistake. Someone used more than one object and has to free them.

var
  pObject1: TMyObject1;
  pObject2: TMyObject2;
begin
  pObject1 := TMyObject1.Create;
  try
    pObject1.DoSomething;
    pObject2 := TMyObject2.Create;
    try
      pObject2.DoSomethingElse;
    finally
      pObject2.Free;
    end;
  finally
    pObject1.Free;
  end;
end;

Instead of nested try…finally blocks it is easier and more readable to do the same with one try…finally block

var
  pObject1: TMyObject1;
  pObject2: TMyObject2;
begin
  pObject2 := nil;
  pObject1 := nil;
  try
    pObject1 := TMyObject1.Create;
    pObject1.DoSomething;
    pObject2 := TMyObject2.Create;
    pObject2.DoSomethingElse;
  finally
    pObject1.Free;
    pObject2.Free;
  end;
end;

This solution can still be improved. The first object can be created outside the try…finally block

var
  pObject1: TMyObject1;
  pObject2: TMyObject2;
begin
  pObject2 := nil;
  pObject1 := TMyObject1.Create;
  try
    pObject1.DoSomething;
    pObject2 := TMyObject2.Create;
    pObject2.DoSomethingElse;
  finally
    pObject1.Free;
    pObject2.Free;
  end;
end;

Please remember that all variables that are freed in the finally block must be initialized before the try statement.

I guess that most of you know this practice for many years but there are still people around who don’t.

Posted in Tips and Tricks | Tagged | Comments Off on try…finally for multiple objects

ANSIToOEM

Today I found some old source code. Someone wanted to write a file in the old OEM codepage. Therefore he wrote a small function that encapsulates the Windows API CharToOem function.

class function TStrUtil.ANSIToOEM(const ANSI: string): string;
var
  sBuffer: AnsiString;
begin
  if ANSI = '' then
    Exit('');

  SetLength(sBuffer, Length(ANSI));
  if CharToOem(PChar(ANSI), PAnsiChar(sBuffer)) then
    Result := string(sBuffer)
  else
    Result := ANSI;
end;

After that he added the OEM string to a TStringList and saved the TStringList to a file.

function TMyForm.SaveTheFile(const AFileName: string)
var
  pList: TStringList;
begin
  pList := TStringList.Create;
  try
    pList.Add(TStrUtils.ANSIToOEM('ÄÖÜ'));
    pList.SaveToFile(AFileName);
  finally
    pList.Free;
  end;
end;

I’m surprised that this code does work. Since Delphi 2010 strings are Unicode strings. This means that the OEM string is stored in a Unicode string variable.

Instead, I think is is much easier to use the wonderful TEncoding class.

function TMyForm.SaveTheFile(const AFileName: string)
var
  pList: TStringList;
  pOEMEncoding: TEncoding;
begin
  pOEMEncoding := nil;
  pList := TStringList.Create;
  try
    pOEMEncoding := TEncoding.GetEncoding(437);
    pList.Add('ÄÖÜ');
    pList.SaveToFile(AFileName, pOEMEncoding);
  finally
    pList.Free;
    pOEMEncoding.Free:
  end;
Posted in Tips and Tricks | Tagged | Comments Off on ANSIToOEM

PowerPDF

In this article I would like to give some details about PowerPDF. PowerPDF is a Delphi VCL component that allows to create pdf documents visually.

PowerPDF has originally been created by Takeshi Kanno, a Japanese Delphi Developer. Since he stopped maintaining the project I continued it.

Currently PowerPDF is hosted under sourceforge. It supports Delphi 2007, Delphi 2010, Delphi XE, Delphi XE2 and the new Delphi XE3.

Posted in Third Party Components | Tagged | Comments Off on PowerPDF