... afisajul lor digital imi placea foarte mult. Daca era ceas cu calculator incorporat, erai deja "cool"
... Era ceva diferit decat lucrurile uzuale care se puteau gasi pe atunci. Acum gasesti afisaje digitale si la ceasuri desteptatoare, la cuptoarele cu microunde, etc. Am tot vazut, de-a lungul timpului, chiar si programe pe calculator care foloseau afisaje digitale - nu ca ar fi neaparat necesar. Oricum, m-am decis (aseara, dar nu m-am urnit pana azi
) sa fac o replica a acelor afisaje digitale in Delphi.Sa vedem, totusi, cum desenam cifrele. M-am gandit sa encodez fiecare piesa posibila pe cate un bit, ca in "diagrama" urmatoare:

Dupa cum se observa, daca tot mi-a ramas un bit, am adaugat si semnul de doua puncte (" : ") pe ultima pozitie - 7.
Folosind diagrama si convertind din binar in zecimal, se gasesc, rapid, valorile care se vor hard-coda in program - formele cifrelor - intr-un array care foloseste ca indecsi chiar caracterele cifrelor (ASCII). Dupa cum se poate calcula (si observa in programul de mai jos), caracterul "3" are valoarea 109 - care, in binar, salveaza forma cifrei 3. Easy as that !
In functie de bit si pozitionarea piesei corespunzatoare, desenatul unei cifre este floare la ureche. Eu am decis ca piesele care nu fac parte din caracter sa fie totusi afisate cu un gri inchis - tot in amintirea zilelor in care afisajurile digitale erau, oarecum, o noutate.
Codul, in toata splendoarea lui, este urmatorul:
- unit Unit1;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, ExtCtrls, StdCtrls, DateUtils, ShellAPI;
- type
- TForm1 = class(TForm)
- imgWatch: TImage;
- imgOriz1: TImage;
- imgOriz2: TImage;
- imgVert1: TImage;
- imgVert2: TImage;
- imgB1: TImage;
- imgB2: TImage;
- Timer1: TTimer;
- imgNumber: TImage;
- imgNumber2: TImage;
- Label1: TLabel;
- procedure FormCreate(Sender: TObject);
- procedure Timer1Timer(Sender: TObject);
- procedure Label1Click(Sender: TObject);
- public
- procedure DrawFigure(X, Y: Integer; aFigure: Char; aCanvas: TCanvas; aDraw: Boolean = True);
- procedure DrawNumber(X, Y: Integer; aNumber: String; aCanvas: TCanvas;
- aShowLeadingZero: Boolean = False; aDraw: Boolean = True);
- end;
- const
- figures: array ['0' .. ':'] of byte =
- (119, 36, 93, 109, // bit values
- 46, 107, 123, 37,
- 127, 111, 128);
- var
- Form1: TForm1;
- lFormatSettings: TFormatSettings;
- someNumber: Cardinal;
- implementation
- {$R *.dfm}
- function GetBit(const Value: Byte; const Bit: Byte): Boolean;
- begin
- Result := (Value and (1 shl Bit)) <> 0;
- end;
- function LeadingZero(aNumber: String; aZeroes: Integer = 8): String;
- begin
- while (Length(aNumber) < aZeroes) do
- aNumber := '0' + aNumber;
- Result := aNumber;
- end;
- procedure TForm1.DrawFigure(X, Y: Integer; aFigure: Char; aCanvas: TCanvas; aDraw: Boolean = True);
- var
- bit: Byte;
- DoDraw: Boolean;
- lX, lY: Integer;
- begin
- for bit := 0 to 7 do
- begin
- lX := X;
- lY := Y;
- if not GetBit(figures[aFigure], bit) // if bit is set, we draw green
- then DoDraw := False // if bit is NOT set, dark grey
- else DoDraw := aDraw;
- case bit of // get piece position
- 0:
- begin
- lX := X + 3;
- end;
- 1:
- begin
- lY := Y + 3;
- end;
- 2:
- begin
- lX := X + imgOriz1.Width + 3;
- lY := Y + 3;
- end;
- 3:
- begin
- lX := X + 3;
- lY := Y + imgVert1.Height + 3;
- end;
- 4:
- begin
- lY := Y + imgVert1.Height + 6;
- end;
- 5:
- begin
- lX := X + imgOriz1.Width + 3;
- lY := Y + imgVert1.Height + 6;
- end;
- 6:
- begin
- lX := X + 3;
- lY := Y + imgVert1.Height * 2 + 6;
- end;
- 7:
- begin
- lX := X + imgOriz1.Width div 2 + 2;
- lY := Y + imgVert1.Height div 2 + 6;
- end;
- end;
- case bit of // display required piece - in green OR dark grey
- 0, 3, 6:
- begin
- if DoDraw
- then aCanvas.Draw(lX, lY, imgOriz1.Picture.Graphic)
- else aCanvas.Draw(lX, lY, imgOriz2.Picture.Graphic);
- end;
- 1, 2, 4, 5:
- begin
- if DoDraw
- then aCanvas.Draw(lX, lY, imgVert1.Picture.Graphic)
- else aCanvas.Draw(lX, lY, imgVert2.Picture.Graphic);
- end;
- 7:
- begin
- if DoDraw
- then aCanvas.Draw(lX, lY, imgB1.Picture.Graphic)
- else aCanvas.Draw(lX, lY, imgB2.Picture.Graphic);
- end;
- end;
- end;
- end;
- procedure TForm1.DrawNumber(X, Y: Integer; aNumber: String; aCanvas: TCanvas;
- aShowLeadingZero: Boolean = False; aDraw: Boolean = True);
- var
- i: Integer;
- zero: Boolean;
- begin
- zero := not aShowLeadingZero;
- for i := 1 to Length(aNumber) do
- begin
- if zero and (aNumber[i] <> '0') then
- zero := False;
- if not zero
- then DrawFigure(X + (i - 1) * imgOriz1.Width * 2, Y, aNumber[i], aCanvas, aDraw)
- else DrawFigure(X + (i - 1) * imgOriz1.Width * 2, Y, aNumber[i], aCanvas, False);
- end;
- end;
- procedure TForm1.FormCreate(Sender: TObject);
- begin
- GetLocaleFormatSettings(LOCALE_SYSTEM_DEFAULT, lFormatSettings);
- lFormatSettings.TimeSeparator := ':';
- lFormatSettings.ShortTimeFormat := 'hh:mm:ss';
- lFormatSettings.LongTimeFormat := 'hh:mm:ss';
- imgWatch.Canvas.Brush.Color := clBlack;
- imgWatch.Canvas.FillRect(imgWatch.ClientRect);
- imgNumber.Canvas.Brush.Color := clBlack;
- imgNumber.Canvas.FillRect(imgNumber.ClientRect);
- imgNumber2.Canvas.Brush.Color := clBlack;
- imgNumber2.Canvas.FillRect(imgNumber2.ClientRect);
- end;
- procedure TForm1.Timer1Timer(Sender: TObject);
- begin
- DrawNumber(5, 5, TimeToStr(NOW, lFormatSettings), imgWatch.Canvas, True);
- inc(someNumber);
- DrawNumber(5, 5, LeadingZero(IntToStr(someNumber), 8), imgNumber.Canvas, True, True);
- DrawNumber(5, 5, LeadingZero(IntToStr(someNumber), 8), imgNumber2.Canvas, False, True);
- end;
- procedure TForm1.Label1Click(Sender: TObject);
- begin
- ShellExecute(Handle, 'open', 'http://www.bitcell.info', nil, nil, SW_SHOWNORMAL);
- end;
- end.
Pentru a exemplifica posibilitatile codului, programul afiseaza ora curenta si un numar incrementat de cateva ori pe secunda (afisand - sau nu - zero-urile dinaintea lui).
Screenshot:

Imaginile din dreapta ceasului sunt imaginile din care sunt compuse cifrele - le puteti modifica manual si recompila programul - sau puteti modifica programul pentru a le incarca la pornire, cum se procedeaza in jocul Snake.
O alta idee pentru imbunatatirea programul ar consta in adaugarea unor noi caractere/pozitii. Acest lucru ar necesita, evident, trecerea de la byte la word sau cardinal (1 byte vs 2 sau chiar 4 bytes). Daca va simtiti norocosi, puteti chiar incerca cu 64 de bytes (int64)

Spor la butonat

Sursa si executabilul: atasate.
Bafta
Welcome to BitCell. Click here to register !


