{progz}

Mindig felül lévő óra Delphiben: FormStyle, TTimer és egy kis tálca-trükk

Az első Delphis programjaim apró segédeszközök voltak: gépzár LAN partira, monitor kikapcsoló, egy mindig látható óra. Egyik sem bonyolult, de mindegyiknél tanultam valamit a Windows ablakkezeléséről. Most az órát írom le, mert ebben van a legtöbb apró buktató.

A cél

Egy kis ablak, amely:

  • mindig a többi ablak fölött marad,
  • nagy számokkal mutatja a pontos időt,
  • alatta van egy egysoros jegyzetmező („15:30 – fogorvos”),
  • és a következő indításkor ugyanott jelenik meg.

Az ablak beállításai

Az Object Inspectorban ennyit állítok be a formon:

BorderStyle := bsToolWindow;   { keskeny fejléc, nincs tálcagomb-ikon }
FormStyle   := fsStayOnTop;    { mindig felül }
Position    := poDesigned;

A formra kerül egy TLabel (nagy, félkövér betű), egy TEdit a jegyzetnek és egy TTimer 1000 ms-os Interval értékkel.

Az óra

procedure TfrmOra.Timer1Timer(Sender: TObject);
begin
  lblIdo.Caption := FormatDateTime('hh:nn:ss', Now);
end;

Az egyetlen csapda a formátum: a Delphiben az nn a perc, az mm a hónap. Ha hh:mm:ss-t írsz, az óra márciusban 03-at mutat a perc helyén, és ez elsőre fel sem tűnik.

Hely megjegyzése INI fájlban

uses IniFiles;

procedure TfrmOra.FormCreate(Sender: TObject);
var Ini: TIniFile;
begin
  Ini := TIniFile.Create(ChangeFileExt(Application.ExeName, '.ini'));
  try
    Left := Ini.ReadInteger('Ablak', 'Left', Left);
    Top  := Ini.ReadInteger('Ablak', 'Top', Top);
    edtJegyzet.Text := Ini.ReadString('Ablak', 'Jegyzet', '');
  finally
    Ini.Free;
  end;
  Timer1Timer(nil);   { ne üres címkével induljon }
end;

procedure TfrmOra.FormClose(Sender: TObject; var Action: TCloseAction);
var Ini: TIniFile;
begin
  Ini := TIniFile.Create(ChangeFileExt(Application.ExeName, '.ini'));
  try
    Ini.WriteInteger('Ablak', 'Left', Left);
    Ini.WriteInteger('Ablak', 'Top', Top);
    Ini.WriteString('Ablak', 'Jegyzet', edtJegyzet.Text);
  finally
    Ini.Free;
  end;
end;

A try..finally nem udvariassági forma. Ha olvasás közben kivétel történik, enélkül az objektum a memóriában marad. Egy egész nap futó programnál ez számít.

Az INI fájl itt az EXE mellé kerül, ami pendrive-ról futtatva kényelmes. Ha viszont a program a Program Files alá települ, és a felhasználó nem rendszergazda, oda nem fog tudni írni. Ilyenkor az Application Data könyvtár a jó hely.

Még egy trükk: húzás a fejléc nélkül

Ha a fejlécet teljesen elhagyod (bsNone), az ablakot sehol sem lehet megfogni. A klasszikus megoldás, hogy a címkére kattintáskor elhitetjük a Windowsszal, hogy a fejlécre kattintottunk:

procedure TfrmOra.lblIdoMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  ReleaseCapture;
  Perform(WM_SYSCOMMAND, $F012, 0);   { SC_MOVE + HTCAPTION }
end;

Az egész program lefordítva nagyjából 400 KB. Ezt a VCL mérete adja, nem az én kódom. Aki kisebbet szeretne, írhatja tisztán Windows API-val is, de egy órához ez már túlzás.