Was mich ursprünglich dazu veranlasst hatte, mir einen Teatimer zu programmieren war, dass ich einfach mal ausprobieren wollte, wie aufwändig die Erstellung einer digitalen Zahlenanzeige ist, OHNE einen ensprechenden Font einzusetzen. Mit anderen Worten: Welche Grafiken benötige ich und wie blende ich wann die richtigen image-Objekte ein, damit auch alles nach einer altmodischen LED-Anzeige aussieht.
Als erstes legte ich mich auf eine Zahlendarstellung mit Hilfe von 7 Elementen fest, schliesslich ging es nicht um Schönheit sondern um einen grundsätzlichen Funktionstest.
1 -
2u3 | |
4 -
5u6 | |
7 -
Als Grafiken benötigte ich somit 2 Basiselemente ( - und | ), einen Doppelpunkt als Trenner für Minuten und Sekunden sowie eine Hintergrundgrafik, welche in dunkelgrau die ausgeblendeten Elemente visualisieren sollte.
Nachdem die vier Grafiken verfügbar waren musste ich diese nur noch mit Hilfe von Image-Objekten in einen Container verfrachten und sauber positionieren. Der Container bekam den Namen 'cntDigit' und enthielt anschliessend sieben image-Objekte. Der Doppelpunkt und die Hintergrundgrafik kommen in meinem Code erst in einem Hauptcontainer zum Zuge, in dem mehrere 'cntDigit' Container nebeneinander positioniert werden und erkennbar als Stunde : Minute dargestellt werden sollen. Es spricht jedoch nichts dagegen, die 8er-Template bereits im Basiscontainer einzufügen. Der verwendete Code läßt dies ohne Änderung zu.
Optisch war nun alles in Butter. Nun kam die Ausprogrammierung der Klasse 'cntDigit' an die Reihe.
Zunächst war die Image-Klasse an der Reihe. Hier musste zwar kein Code hinterlegt werden, aber sowohl die waagerechten als auch die senkrechten Balken benötigten Eigenschaften, mit deren Hilfe eine Sichtbarkeit in Abhängigkeit von der anzuzeigenden Zahl möglich war. Hierfür erstellte ich 10 individuell zu setzende Eigenschaften die je nach Image-Position gefüllt werden.
Wie die 10 Eigenschaften vom Typ Boolean (-> _0, _1, _2, _3, ..., _9) zu füllen sind liegt letztlich an der Position des jeweiligen Image-Objektes. Wird das Objekt zur Darstellung der anzuzeigenden Zahl benötigt, erhält die Eigenschaft ein .T. andernfalls ein .F. (-> Default). Vorteil diese Methodik ist, dass eine Erweiterung auf eine komplexere Darstellung bzw. Erweiterung auf Buchstaben problemlos umzusetzen ist.
Um eine wertbezogene Anzeige zu generieren erhielt cntDigit zunächst einmal die Eigenschaft '_DisplayDigit' inkl. einer dazugehörigen Assign-Methode '_DisplayDigit_assign'. Zusätzlich kam noch die Methode 'initdigit' dazu, um den Container 'NICHTS' anzeigen zu lassen (Diese Methode wird im Teatimer immer nach dem Ablauf des Timers aufgerufen).
Innerhalb von '_DisplayDigit_assign' wird eine FOR..EACH Schleife durchlaufen, in der mit Hilfe von PEMSTATUS() überprüft wird, ob die zusammengesetzte Eigenschaft im Zielobjekt vorhanden ist. Anschliessend wird deren Wert einfach der Visible-Eigenschaft des Imageobjektes zugewiesen. Voilà, fertig war die digitale Zahlenanzeige. Da kommt einem doch sofort der Werbespruch eines ehemaligen Tennisprofis in den Sinn: Das ging ja einfach!! ;-)
Hier nun das Codesegment von cntDigit:
* // Funktionstest -START-
WITH _screen
.AddObject ( [oShape] , [Shape] )
.oShape.Width = 48
.oShape.Height = 82
.oShape.BackColor = RGB( 0 , 0 , 0 )
.oShape.Visible = .T.
.AddObject ( [oTemplate], [imgTemplate] )
.oTemplate.Top = 5
.oTemplate.Left = 5
.oTemplate.Visible = .T.
.AddObject ( [oDigit] , [cntDigit] )
ENDWITH
WITH _screen.oDigit
.Top = 5
.Left = 5
.Visible = .T.
._DisplayDigit = [1]
WAIT WINDOW [Taste für 2]
._DisplayDigit = [2]
WAIT WINDOW [Taste für 3]
._DisplayDigit = [3]
WAIT WINDOW [Taste für 4]
._DisplayDigit = [4]
WAIT WINDOW [Taste für 5]
._DisplayDigit = [5]
WAIT WINDOW [Taste für 6]
._DisplayDigit = [6]
WAIT WINDOW [Taste für 7]
._DisplayDigit = [7]
WAIT WINDOW [Taste für 8]
._DisplayDigit = [8]
WAIT WINDOW [Taste für 9]
._DisplayDigit = [9]
WAIT WINDOW [Taste für 0]
._DisplayDigit = [0]
WAIT WINDOW [Schliessen]
ENDWITH
WITH _screen
.RemoveObject( [oDigit] )
.RemoveObject( [oTemplate] )
.RemoveObject( [oShape] )
ENDWITH
* // Funktionstest -ENDE-
DEFINE CLASS cntdigit AS container
Width = 38
Height = 71
BackStyle = 0
BorderWidth = 0
_displaydigit = ""
Name = "cntdigit"
ADD OBJECT imgom AS imgdigithorizontal WITH ;
Left = 5, ;
Top = 0, ;
Visible = .F., ;
_0 = .T., ;
_1 = .F., ;
_2 = .T., ;
_3 = .T., ;
_4 = .F., ;
_5 = .T., ;
_6 = .T., ;
_7 = .T., ;
_8 = .T., ;
_9 = .T.
ADD OBJECT imgum AS imgdigithorizontal WITH ;
Left = 5, ;
Top = 62, ;
Visible = .F., ;
_0 = .T., ;
_1 = .F., ;
_2 = .T., ;
_3 = .T., ;
_4 = .F., ;
_5 = .T., ;
_6 = .T., ;
_7 = .F., ;
_8 = .T., ;
_9 = .T.
ADD OBJECT imgmm AS imgdigithorizontal WITH ;
Left = 5, ;
Top = 31, ;
Visible = .F., ;
_0 = .F., ;
_1 = .F., ;
_2 = .T., ;
_3 = .T., ;
_4 = .T., ;
_5 = .T., ;
_6 = .T., ;
_7 = .F., ;
_8 = .T., ;
_9 = .T.
ADD OBJECT imgol AS imgdigitvertical WITH ;
Left = 0, ;
Top = 6, ;
Visible = .F., ;
_0 = .T., ;
_1 = .F., ;
_2 = .F., ;
_3 = .F., ;
_4 = .T., ;
_5 = .T., ;
_6 = .T., ;
_7 = .F., ;
_8 = .T., ;
_9 = .T.
ADD OBJECT imgur AS imgdigitvertical WITH ;
Left = 29, ;
Top = 37, ;
Visible = .F., ;
_0 = .T., ;
_1 = .T., ;
_2 = .F., ;
_3 = .T., ;
_4 = .T., ;
_5 = .T., ;
_6 = .T., ;
_7 = .T., ;
_8 = .T., ;
_9 = .T.
ADD OBJECT imgul AS imgdigitvertical WITH ;
Left = 0, ;
Top = 37, ;
Visible = .F., ;
_0 = .T., ;
_1 = .F., ;
_2 = .T., ;
_3 = .F., ;
_4 = .F., ;
_5 = .F., ;
_6 = .T., ;
_7 = .F., ;
_8 = .T., ;
_9 = .F.
ADD OBJECT imgor AS imgdigitvertical WITH ;
Left = 29, ;
Top = 6, ;
Visible = .F., ;
_0 = .T., ;
_1 = .T., ;
_2 = .T., ;
_3 = .T., ;
_4 = .T., ;
_5 = .F., ;
_6 = .F., ;
_7 = .T., ;
_8 = .T., ;
_9 = .T.
PROCEDURE _displaydigit_assign
LPARAMETERS vNewVal
* // Einblenden der für die darzustellende Zahl
* // benötigten Bits. Gesteuert wird dies über
* // die Properties _0 - _9 die über die
* // FOR...EACH Schleife direkt ausgewertet werden.
IF This._DisplayDigit <> m.vNewVal
LOCAL lcProperty as String
This._DisplayDigit = m.vNewVal
FOR EACH oDigit IN This.Controls
lcProperty = [_] + This._DisplayDigit
IF PEMSTATUS(oDigit,lcProperty,5)
oDigit.Visible = oDigit.&lcProperty
ENDIF
ENDFOR
ENDIF
ENDPROC
PROCEDURE initdigit
* // Ausblenden sämtlicher Bits
FOR EACH oDigit IN This.Controls
oDigit.Visible = .F.
ENDFOR
ENDPROC
ENDDEFINE
DEFINE CLASS imgdigithorizontal AS image
Picture = "..\_bitmaps\inf_digit_horizontal.bmp"
BackStyle = 0
Height = 9
Width = 28
_1 = .F.
_2 = .F.
_3 = .F.
_4 = .F.
_5 = .F.
_6 = .F.
_7 = .F.
_8 = .F.
_9 = .F.
_0 = .F.
ENDDEFINE
DEFINE CLASS imgdigitvertical AS image
Picture = "..\_bitmaps\inf_digit_vertical.bmp"
Height = 28
Width = 9
_1 = .F.
_2 = .F.
_3 = .F.
_4 = .F.
_5 = .F.
_6 = .F.
_7 = .F.
_8 = .F.
_9 = .F.
_0 = .F.
ENDDEFINE
DEFINE CLASS imgTemplate AS image
Picture = "..\_bitmaps\inf_digit_template.bmp"
Height = 71
Width = 38
ENDDEFINE
This is very very cool !
AntwortenLöschenThanks for sharing
Regards
Cesar
Hi Cesar,
AntwortenLöschenI'm glad you like it :-)
-Tom
Hi Thomas,
AntwortenLöschenhmm, da haste wohl das Rad nochmal neu erfunden ;) Guggst du hier:
http://code.msdn.microsoft.com/FoxPro/Release/ProjectReleases.aspx?ReleaseId=131
Datt Dingens hatte ich mal anno 2004 "erfunden" für ein Kassensystem.
Hi wOOdy,
AntwortenLöschenDeine Variante ist ein interessanter Ansatz. Auf den Einsatz von Shapes hatte ich gezielt verzichtet, weil ich bei einer Erhöhung der LED-Objekte zu viele Überlappungen hätte. Aber für mich war es halt einfach nur ein wenig Rumspielen mit der Aufgabenstellung. An einen Echteinsatz wie bei Kassensystemen hatte ich überhaupt nicht gedacht. Wenn es um Resizing geht bist Du mit den Shapes sicherlich flexibler!
Auf jeden Fall haben wir mal wieder ein Beispiel dafür, dass viele Wege nach Rom führen :-)))