Lazarus-Klokje-Analoog opmaak

Afleveringen

We hebben de analoge klok!

We willen de klok echter nog wat netter maken en we moeten wat mogelijkheden van opmaak toevoegen aan het menu. Tevens moeten de nieuwe instellingen bewaard worden.

Wijzerplaat

Als eerste gaan we er voor zorgen dat de analoge klok wordt voorzien van een heuse wijzerplaat:

En dit is gemakkelijker dan u denkt. Het enige wat we nodig hebben is een “wijzerplaat” en een Image-component en wat kleine instellingen. Google even op “clockfaces” in Google-afbeeldingen en u vindt vast een plaat naar uw zin. Als u er meer mooi vindt, zorg er dan voor dat ze wel allemaal ongeveer dezelfde afmeting hebben. Later gaan we er dan voor zorgen dat u in de klok kunt wisselen van wijzerplaat.

U kunt natuurlijk ook even onderstaande wijzerplaten downloaden (klikken en daarna met rechts klik afbeelding downloaden):

– Zet een Image control (4e knop van links op de tab Additional) op de Form.
– Geef de property Name de waarde imgFace.
– Zet de property Stretch op True.
– Zet de property Transparent op True.
– Klik op de ellips-knop () naast de property Picture.
– Laad een wijzerplaat naar keuze.
– Ga in de code naar FormActivate.
– Voeg voor LeesIni de volgende regels code toe:
  imgFace.Left := 0;
  imgFace.Top := 0;
  imgFace.Width := 100;
  imgFace.Height := 100;
  imgFace.Visible := False;
– Ga naar FormPaint.
– Voeg in het Analoog gedeelte na de regel lblTijd.Visible := False; de volgende regel toe:
  imgFace.Visible := True;
– Haal in het Analoog gedeelte de regel frmKlokje.Canvas.Ellipse(0,0,100,100); weg of becommentarieer deze regel.
– Voeg in het Digitaal gedeelte direct na begin de volgende regel toe:
  imgFace.Visible := False;
– Run het klokje in Analoge stand en geniet ervan.

Grootte analoge klok

De volgende stap is dat de analoge klok van grootte moet kunnen veranderen. We gaan drie groottes maken: Small, Medium en Big. We gaan hiervoor een globale variabele ClockSize (integer) gebruiken. De keuze moet, uiteraard, in het menu te maken zijn.

– Voeg in de code in het implementation-gedeelte de variabele ClockSize van het type integer toe (dus bij MyX en MyY).
– Voeg de volgende code na Analoog := False; toe in FormActivate:
  ClockSize := 120;
– Verander de regels imgFace.Width en imgFace.Height als volgt:
  imgFace.Width := ClockSize;
  imgFace.Height := ClockSize;
– Ga naar FormPaint.
– Vervang hier de volgende regels als volgt:
  aBitmap.Width := ClockSize; // was frmKlokje.Width;
  aBitmap.Height := ClockSize; // was frmKlokje.Height;

–   aBitmap.Canvas.Ellipse(-1,-1,ClockSize+1,ClockSize+1); // was aBitmap.Canvas.Ellipse(-1,-1,frmKlokje.Width+1,frmKlokje.Height+1);

–   frmKlokje.Width := ClockSize; // was 100;
  frmKlokje.Height := ClockSize; // was 100;
– Voeg drie nieuwe regels toe boven frmKlokje.Width:
  imgFace.Width := ClockSize;
  imgFace.Height := ClockSize;
  imgFace.Visible := True;
– Run het klokje.

Wat is hier aan de hand?
We hebben ClockSize op 120 gezet, terwijl de wijzers nog worden getekend met een klokgrootte van 100, dus vanuit het middelpunt (50,50). Dat middelpunt moet nu dus (60,60) zijn. Maar omdat we ook nog andere groottes gaan implementeren moeten we dit middelpunt variabel maken, namelijk (ClockSize div 2, ClockSize div 2).

– Ga naar tmrTijdTimer.
– Voeg een variabele c van het type integer toe.
– Voeg de volgende regel code in het Analoog gedeelte toe, direct na begin:
  c := ClockSize div 2;
– Vervang nu in de formules wx en wy de + 50 door + c.
– Vervang in de regels met Line(50,50,… de 50 door c.
– Run de klok.

Dit ziet er gelukkig weer beter uit.
Wat misschien niet zo opvalt is dat de wijzers naar verhouding kleiner zijn dan toen de klok 100 x 100 was. Dit wordt beter zichtbaar als de klok bijvoorbeeld 200 x 200 is.

– Verander in FormActivate ClockSize van 120 naar 200.
– Run de klok.

Ziet u wat ik bedoel? Dit zijn toch wel hele zielige wijzertjes geworden. De wijzers moeten dus mee groeien met de grootte van de klok. We hadden de volgende verhoudingen: Voor de seconde wijzer 40/50 ofwel 0.8 van de ClockSize div 2, voor de minuten wijzer een verhouding van 30/50 = 0.6 en voor de uren 20/50 = 0.4. En deze verhoudingen gaan we gebruiken.

– Ga naar tmrTijdTimer.
– Declareer helemaal bovenaan, dus nog boven var de volgende constanten:
  const
    fhw: Real = 0.4;
    fmw: Real = 0.6;
    fsw: Real = 0.8;
– Vervang bij de urenwijzer-formules wx en wy de * 20 door * c * fhw.
– Vervang bij de minutenwijzer-formules wx en wy de * 30 door * c * fmw.
– Vervang bij de secondenwijzer-formules wx en wy de * 40 door * c * fsw.
– Run de klok.

En dit ziet er al weer veel beter uit. We gaan de grootte door de gebruiker laten kiezen.

– Verander in FormActivate ClockSize weer terug van 200 naar 120.
– Voeg aan het popMenu de volgende items toe:
– In het submenu van Analog na het item On het item Size met Name = popAnalogSize.
– Maak een submenu bij Size met de volgende items:
Small: Name = popAnalogSizeSmall en Checked = True,
Medium: Name = popAnalogSizeMedium,
Big: Name = popAnalogSizeBig
– Maak het event popAnalogSizeClick aan.

Sender

In dit event gaan we de drie size-opties afwerken. Dus 1 event voor drie opties. Daarvoor gaan we handig gebruik maken van de parameter Sender.

– Implementeer de event popAnalogSizeClick als volgt: 
– Voeg de variabele s van het type String toe (voor begin).
– Zet de volgende regels tussen begin en end:
  popAnalogSizeSmall.Checked := False;
  popAnalogSizeMedium.Checked := False;
  popAnalogSizeBig.Checked := False;
  (Sender as TMenuItem).Checked := True;
  s := (Sender as TMenuItem).Name;
  s := Uppercase(Trim(Copy(s,14,Length(s))));
  Case s of
    ‘MEDIUM’: ClockSize := 160;
    ‘BIG’: ClockSize := 200
  else
    ClockSize := 120;
  end;
  frmKlokje.Repaint;
– Haal vanuit de Object Inspector (tab Gebeurtenissen) bij popAnalogSize de event-handler weg (kies (geen)).
– Voeg de event handler popAnalogSizeClick toe bij de opties popAnalogSizeSmallpopAnalogSizeMedium en popAnalogSizeBig.

Even wat uitleg over de code. In de parameter Sender zitten de gegevens van de aanroepende control. Omdat Sender van het type TObject (zeg maar het basis object in Lazarus) is moet deze “gecast” worden naar het juiste type. In dit voorbeeld gaat het over een menuoptie dus wordt er gecast naar TMenuItem. Dat casten gebeurt met de as-operator. Door middel van dit soort constructies is het mogelijk om hele efficiënte code te schrijven.

– Run het klokje en verander een aantal malen de grootte van de analoge klok.

We hebben nu aardig wat nieuwe functionaliteiten toegevoegd wat ook nieuwe instellingen met zich mee brengt. Deze instellingen moeten natuurlijk ook bewaard worden via SchrijfIni en bij het starten door LeesIni weer verwerkt worden.
Ik ga ervan uit dat u nu weet hoe dat moet.

– Zorg voor de volgende uitbreidingen van de cfg-file klokje.cfg:
– Voeg in de sectie [CLOCK] een indent Analog toe dat aangeeft of de klok analoog is (-1) of niet (0); is dus een Boolean.
– Maak een nieuwe sectie [ANALOG] met de indent ClockSize dat de waarde Small, Medium of Big heeft.
– Breid dus zowel SchrijfIni als LeesIni uit.

Mocht dit niet meteen lukken, dan geen nood. In de laatste aflevering zal de complete code staan.

Andere wijzerkleurtjes

We gaan nu de kleuren van de wijzers variabel maken en laten het aan de gebruiker over om deze te kunnen wijzigen.

– Voeg in het implementation-gedeelte de volgende drie globale variabelen toe:
  ColorHour, ColorMinute, ColorSecond: TColor;
– Voeg bij FormActivate voor LeesIni de volgende regels code toe:
  ColorHour := clGreen;
  ColorMinute := clBlue;
  ColorSecond := clRed;
– Voeg in het popMenu in het submenu Analog onder het item Size het item Colors (Name = popAnalogColors) toe.
– Voeg een submenu aan het item Colors toe met de volgende items:
Hour: Name = popAnalogColorsHour
Minute: Name = popAnalogColorsMinute
Second: Name = popAnalogColorsSecond
– Implementeer het event popAnalogColorsClick.
– Voeg de volgende variabelen toe:
  var
  s: String;
  c: TColor;
– En hierna (na begin) de volgende code:
  s := (Sender as TMenuItem).Name;
  s := UpperCase(Copy(s,16,Length(s)));
  case s of
    ‘HOUR’: c := ColorHour;
    ‘MINUTE’: c := ColorMinute;
    ‘SECOND’: c := ColorSecond;
  end;
  if s <> ” then
    begin
      dlgColor.Color := c;
      if dlgColor.Execute then
        begin
          c := dlgColor.Color;
          case s of
            ‘HOUR’: ColorHour := c;
            ‘MINUTE’: ColorMinute := c;
            ‘SECOND’: ColorSecond := c;
          end;
        end;
    end;
– Haal via de Object Inspector (tab Gebeurtenissen) bij popAnalogColors het OnClick-event weg.
– Koppel de event handler popAnalogColorsClick toe aan de opties popAnalogColorsHourpopAnalogColorsMinute en popAnalogColorsSecond.
– Vervang in het tmrTijdTimer event clGreen door ColorHour, clBlue door ColorMinute en clRed door ColorSecond.
– Run de klok en speel wat met de kleuren voor de verschillende wijzers.

– Voeg in de cfg-file onder de sectie [ANALOG] de volgende indents toe:
ColorHour
ColorMinute
ColorSecond
– Waardes van het type TColor zijn gewone integers.

De cfg-file zou er nu als volgt kunnen uitzien:

[CLOCK]
OnTop=-1
Position-X=907
Position-Y=67
Analog=-1

[FONT]
Name=Microsoft Sans Serif
Size=16
Style=Standard
ForeColor=0
BackColor=536870912

[OPACITY]
Percentage=75

[ANALOG]
ClockSize=Small
ColorHour=32768
ColorMinute=16711680
ColorSecond=255

Ons klokje begint nu aardig te werken.

In de volgende aflevering gaan we nieuwe vensters toevoegen voor onder andere het kiezen van de wijzerplaat en een zogenaamde About-venster.

Naar de volgende aflevering…