Afleveringen In deze aflevering gaan we alle instellingen en de positie van het klokje bewaren, zodat deze weer actief worden bij een volgende start. We gaan twee procedures maken: LeesIni en SchrijfIni. De procedure SchrijfIni is niet zo heel ingewikkeld om te maken. Daar waar Windows programma’s vroeger een .ini-file aanmaakte is dat tegenwoordig een .cfg-file; cfg is de extensie die duidt op een configuratie bestand. Kortweg zijn er twee plaatsen waar een cfg-file kan staan. Wanneer een applicatie een algemeen karakter heeft, dus door alle gebruikers kan worden gebruikt is de eerste map van toepassing, is de applicatie persoonsgebonden dan ligt de tweede map voor de hand. Gelukkig heeft Lazarus hier een mooie functie voor: GetAppConfigFile(Global: Boolean). Als de parameter Global True is dan wordt de algemene map gekozen, is Global False dan wordt de persoonlijke map gekozen. Om gebruik te maken van speciale ini-methodes moet u de unit IniFiles aanroepen. Daar LeesIni en SchrijfIni onderdeel moeten gaan uitmaken van de class TfrmKlokje moeten ze daar ook in worden opgenomen. Dit doen we in de private-sectie van de class-definitie. Tijd om aan de slag te gaan. – Zet in de implementation-sectie onder de regel {$R *.lfm} de volgende regels: – procedure TfrmKlokje.SchrijfIni; Het raam-werk staat. We gaan beginnen met de implementatie van SchrijfIni. De cfg-file moet er (ongeveer) als volgt uit gaan zien: [CLOCK] [FONT] [OPACITY] U ziet dat dit nog erg lijkt op een ouderwetse ini-file. We gaan de eerste code “kloppen”: – Ga naar de implementation-sectie, procedure SchrijIni. – ini.WriteString(‘FONT’,’Name’,lblTijd.Font.Name); – if popOpacity100.Checked then Een hoop om even te bespreken. De class TINIFile zorgt ervoor dat er een ini-file (cfg-file dus) kan worden aangemaakt, er naar toe kan worden geschreven en eruit gelezen kan worden. Vervolgens maken we gebruik van de methode WriteString. Deze methode verwacht drie parameters die allen van het type String zijn. De eerste parameter geeft de sectie aan, de tweede de zogenaamde indent en de derde de waarde van deze indent. Omdat ook de waarde van het type String is moeten dus de andere grootheden die geen String zijn worden omgezet in een string. Omdat er een instantie van de class TINIFile wordt gemaakt moet deze ook weer netjes worden afgesloten (in dit geval moet ook de text-file worden gesloten). Dit gebeurt met de methode Free. Omdat deze ALTIJD moet worden uitgevoerd zetten we de schrijfopdrachten e.d. tussen een try-finally-blok. Mocht er tussen try en finally iets mis gaan, dan wordt toch de code tussen finally en end; uitgevoerd (deze end; hoort dus bij try-finally!). Om de Font-style netjes te kunnen opslaan moeten we weten hoe de Style is opgebouwd. In Lazarus (Free-Pascal) is de Style-property van een Font een zogenaamde Set (een verzameling). We moeten deze Set dus gaan omzetten naar een String. Verder moet u weten dat de Style altijd minimaal Standard is. Voeg op de plek van het commentaar (//Hier komt code voor de Font-Style) de volgende code toe: In bovenstaande code wordt de String fstyle netjes opgebouwd. De verschillende stijlen zijn netjes met een komma+spatie van elkaar gescheiden. Omdat deze komma+spatie ook aan het eind van fstyle staat worden deze d.m.v. een Copy weer weggehaald. Waar we nu nog even voor moeten zorgen is dat bij het sluiten van de klok de procedure SchrijfIni wordt aangeroepen. – Maak het OnClose-event van frmKlokje aan. Dit was al heel wat werk, zei het dat er enige repetitie in zit (ofwel copy-paste). Nu moeten we LeesIni nog gaan implementeren. Laten we maar beginnen. LeesIni gaat gebruik maken van de method ReadString dat een functie is en een String als waarde teruggeeft. ReadString heeft ook drie parameters: sectie, indent en een default waarde. De default waarde wordt toegekend als de indent in de cfg-file leeg is. Ook zullen we de String in voorkomende gevallen moet omzetten naar een Boolean of een getal. Dit doen we met de functies StrToBool en TryStrToInt die een String probeert om te zetten naar een Integer en als dan niet lukt de waarde False terug geeft. Ook moeten we na iedere ReadString een controle uitvoeren, zodat ons klokje niet gaat “hangen” vanwege een verkeerde waarde. Met deze kennis kunnen we aan de slag: – Voeg aan de procedure LeesIni de volgende variabelen toe: – s := ini.ReadString(‘FONT’,’Name’,’Arial’); – popOpacity100.Checked := True; Rest ons niets anders dan LeesIni op de juiste plaats op te nemen in de code. – Activeer het OnActivate event van het form. Als het goed is zijn alle instellingen van de eerste keer de tweede keer actief. In de volgende aflevering gaan we iets geheel nieuw doen. We gaan tekenen. Jawel, de analoge klok staat op het programma.
De ouderwetse ini-file in een nieuw jasje.
Met LeesIni lezen we de opgeslagen instellingen en passen deze toe voordat de klok gaat werken.
Met SchrijfIni slaan we alle instellingen op, op het moment dat de klok wordt afgesloten.
De procedure LeesIni daarentegen is veel lastiger, omdat er dan allerlei controles moeten worden uitgevoerd.Plaats van de cfg-file
Verder is de plaats waar de cfg-file moet komen ook belangrijk, daar Windows tegenwoordig heel veel mappen beveiligt tegen schrijven.
De map C:\ProgramData\[naam applicatie] of een persoonlijke map C:\Users\[naam gebruiker]\AppData\Local\[naam applicatie].
– Uses
– IniFiles;
– Ga naar de class-definitie van TfrmKlokje in de interface-sectie en voeg de volgende regels toe na de regel met {private declarations}:
– procedure LeesIni;
– procedure SchrijfIni;
– Ga naar de implementation-sectie en voeg na de variabele-declaraties, dus onder { TfrmKlokje } de volgende code toe:
– procedure TfrmKlokje.LeesIni;
– begin
– // hier komt de code
– end;
– begin
– // hier komt de code
– end;SchrijfIni
We geven onze klok een globaal karakter, dus de cgf-file moet in de map ProgramData komen te staan.
Verder willen we de volgende zaken opslaan:
OnTop=-1
Position-X=966
Position-Y=76
Name=Microsoft Sans Serif
Size=16
ForeColor=0
BackColor=536870912
Style=Standard
Percentage=75
– Haal het commentaar weg.
– Zet tussen de regels procedure … en begin de volgende regels code:
– var
– ini: TINIFile;
– opacperc, fstyle: String;
– Ga nu tussen begin en end; staan.
– Tik de volgende regels code in:
– ini := TINIFile.Create(GetAppConfigFile(True));
– try
– ini.WriteString(‘CLOCK’,’OnTop’,BoolToStr(frmKlokje.FormStyle = fsSystemStayOnTop));
– ini.WriteString(‘CLOCK’,’Position-X’,IntToStr(frmKlokje.Left));
– ini.WriteString(‘CLOCK’,’Position-Y’,IntToStr(frmKlokje.Top));
– ini.WriteString(‘FONT’,’Size’,IntToStr(lblTijd.Font.Size));
– //Hier komt code voor de Font-Style
– ini.WriteString(‘FONT’,’ForeColor’,IntToStr(lblTijd.Font.Color));
– ini.WriteString(‘FONT’,’BackColor’,IntToStr(frmKlokje.Color));
– opacperc := ‘100’;
– if popOpacity75.Checked then
– opacperc := ’75’;
– if popOpacity50.Checked then
– opacperc := ’50’;
– if popOpacity25.Checked then
– opacperc := ’25’;
– ini.WriteString(‘OPACITY’,’Percentage’,opacperc);
– finally
– ini.Free;
– end;
Deze class is echter, bij declaratie, nog geen instantie. Hij bestaat dus nog niet. Met de methode Create maken we de instantie aan. In dit geval verwacht Create de map en de naam van het ini-bestand. En daarvoor gebruiken we dus de eerder genoemde functie GetAppConfigFile.
Voor een Boolean gebruiken we de functie BoolToStr en voor een geheel getal (integer) de functie IntToStr.Set
– fstyle := ‘Standard, ‘;
– if fsBold in lblTijd.Font.Style then
– fstyle := fstyle + ‘Bold, ‘;
– if fsItalic in lblTijd.Font.Style then
– fstyle := fstyle + ‘Italic, ‘;
– if fsStrikeOut in lblTijd.Font.Style then
– fstyle := fstyle + ‘StrikeOut, ‘;
– if fsUnderline in lblTijd.Font.Style then
– fstyle := fstyle + ‘Underline, ‘;
– fstyle := Copy(fstyle,1,Length(fstyle)-2);
– ini.WriteString(‘FONT’,’Style’,fstyle);
Omdat het klokje op meerdere manieren gesloten kan worden (via het snelmenu, evt. dubbelklikken, maar ook via de taakbalk) is het handig om het OnClose-event van de Form te gaan gebruiken.
– Voeg de volgende regel code toe:
– SchrijfIni;
– Run de klok en sluit deze daarna weer af.
– Bekijk de cfg-file in C:\ProgramData\klokje.
En dit was nog wel het gemakkelijke gedeelte.LeesIni
Overigens wordt door de functie BoolToStr de waarde ‘-1’ omgezet naar True en de waarde ‘0’ omgezet naar False.
– var
– ini: TINIFile;
– s, h: String;
– i: integer;
– Haal het commentaar weg en voeg na begin de volgende regels code toe:
– ini := TINIFile.Create(GetAppConfigFile(True));
– try
– s := ini.ReadString(‘CLOCK’,’OnTop’,”);
– if s = ‘-1’ then
– begin
– frmKlokje.FormStyle := fsSystemStayOnTop;
– popOnTop.Checked := True;
– end
– else
– begin
– frmKlokje.FormStyle := fsNormal;
– popOnTop.Checked := False;
– end;
– s := ini.ReadString(‘CLOCK’,’Position-X’,”);
– if TryStrToInt(s,i) then
– frmKlokje.Left := i
– else
– frmKlokje.Left := 256;
– s := ini.ReadString(‘CLOCK’,’Position-Y’,”);
– if TryStrToInt(s,i) then
– frmKlokje.Top := i
– else
– frmKlokje.Top := 130;
– lblTijd.Font.Name := s;
– s := ini.ReadString(‘FONT’,’Size’,”);
– if TryStrToInt(s,i) then
– lblTijd.Font.Size := i
– else
– lblTijd.Font.Size := 14;
– lblTijd.Font.Style := [];
– s := ini.ReadString(‘FONT’,’Style’,”);
– s := s + ‘,’;
– i := Pos(‘,’, s);
– while i > 0 do
– begin
– h := Trim(Copy(s,1,i-1));
– if UpperCase(h) = ‘BOLD’ then
– lblTijd.Font.Style := lblTijd.Font.Style + [fsBold];
– if UpperCase(h) = ‘ITALIC’ then
– lblTijd.Font.Style := lblTijd.Font.Style + [fsItalic];
– if UpperCase(h) = ‘STRIKEOUT’ then
– lblTijd.Font.Style := lblTijd.Font.Style + [fsStrikeOut];
– if UpperCase(h) = ‘UNDERLINE’ then
– lblTijd.Font.Style := lblTijd.Font.Style + [fsUnderline];
– s := Copy(s,i+1,Length(s));
– i := Pos(‘,’, s);
– end;
– s := ini.ReadString(‘FONT’,’ForeColor’,”);
– if TryStrToInt(s,i) then
– lblTijd.Font.Color := i
– else
– lblTijd.Font.Color := RGBToColor(0, 0, 0); //zwart
– s := ini.ReadString(‘FONT’,’BackColor’,”);
– if TryStrToInt(s,i) then
– frmKlokje.Color := i
– else
– frmKlokje.Color := RGBToColor(127, 127, 127); //grijs
– popOpacity75.Checked := False;
– popOpacity50.Checked := False;
– popOpacity25.Checked := False;
– frmKlokje.AlphaBlendValue := 255;
– s := ini.ReadString(‘OPACITY’,’Percentage’,”);
– if s = ’25’ then
– begin
– popOpacity100.Checked := False;
– popOpacity25.Checked := True;
– frmKlokje.AlphaBlendValue := 64;
– end;
– if s = ’50’ then
– begin
– popOpacity100.Checked := False;
– popOpacity50.Checked := True;
– frmKlokje.AlphaBlendValue := 128;
– end;
– if s = ’75’ then
– begin
– popOpacity100.Checked := False;
– popOpacity75.Checked := True;
– frmKlokje.AlphaBlendValue := 191;
– end;
– finally
– ini.Free;
– end;
Deze plaats is het OnActivate event van de Form.
– Neem de volgende regel code op:
– LeesIni;
– Run de klok, pas wat instellingen aan en verplaats de klok.
– Sluit de klok af en start weer opnieuw op.