| 1 | {************************************************} | 
|---|
| 2 | {                                                } | 
|---|
| 3 | { TSevenSegDisplay component                     } | 
|---|
| 4 | {                                                } | 
|---|
| 5 | { A seven-segment display panel for Sibyl        } | 
|---|
| 6 | {                                                } | 
|---|
| 7 | { Copyright (C) 1996-1997 Joerg Pleumann         } | 
|---|
| 8 | {                                                } | 
|---|
| 9 | { Mail bugs to: pleumann@uni-duisburg.de         } | 
|---|
| 10 | {                                                } | 
|---|
| 11 | {************************************************} | 
|---|
| 12 |  | 
|---|
| 13 | unit Seven; | 
|---|
| 14 |  | 
|---|
| 15 | interface | 
|---|
| 16 |  | 
|---|
| 17 | uses | 
|---|
| 18 | Classes, Forms, Graphics; | 
|---|
| 19 |  | 
|---|
| 20 | type | 
|---|
| 21 | TSevenSegDisplay = class(TControl) | 
|---|
| 22 | private | 
|---|
| 23 | FDigits:      string; | 
|---|
| 24 | FSegments:    string; | 
|---|
| 25 | FBorderStyle: TBorderStyle; | 
|---|
| 26 | FMargin:      LongInt; | 
|---|
| 27 |  | 
|---|
| 28 | procedure SetBorderStyle(Value: TBorderStyle); | 
|---|
| 29 | procedure SetDigits(const Value: string); | 
|---|
| 30 | procedure SetMargin(Value: LongInt); | 
|---|
| 31 | public | 
|---|
| 32 | constructor Create(Owner: TComponent); override; | 
|---|
| 33 | procedure Redraw(const Rec: TRect); override; | 
|---|
| 34 |  | 
|---|
| 35 | property XAlign; | 
|---|
| 36 | property XStretch; | 
|---|
| 37 | property YAlign; | 
|---|
| 38 | property YStretch; | 
|---|
| 39 | published | 
|---|
| 40 | property Align; | 
|---|
| 41 | property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle; | 
|---|
| 42 | { Holds the border style of the seven segment | 
|---|
| 43 | display. The following values are supported: | 
|---|
| 44 | bsNone   - No border | 
|---|
| 45 | bsSingle - Border with 3D appearance } | 
|---|
| 46 | property Digits: string read FDigits write SetDigits; | 
|---|
| 47 | { The Digits property holds the current content | 
|---|
| 48 | string of the seven segment display. The | 
|---|
| 49 | following digits and characters are supported: | 
|---|
| 50 |  | 
|---|
| 51 | The characters '0' to '9' and 'A' to 'F', | 
|---|
| 52 | allowing the display of decimal and | 
|---|
| 53 | hexadecimal numbers. | 
|---|
| 54 |  | 
|---|
| 55 | The additional characters 'H', 'I', 'J', 'L', | 
|---|
| 56 | 'N', 'O', 'R', 'S', 'U', and 'Y', allowing the | 
|---|
| 57 | display of the following strings: | 
|---|
| 58 |  | 
|---|
| 59 | 'ON'            'EIN' | 
|---|
| 60 | 'OFF'           'AUS' | 
|---|
| 61 | 'YES'           'JA' | 
|---|
| 62 | 'NO'            'NEIN' | 
|---|
| 63 | 'ERROR'         'FEHLER' | 
|---|
| 64 |  | 
|---|
| 65 | I must, however, admit that some of the | 
|---|
| 66 | strings look very strange... :-) | 
|---|
| 67 |  | 
|---|
| 68 | The minus sign ('-') highlights the center | 
|---|
| 69 | segment. | 
|---|
| 70 |  | 
|---|
| 71 | The space (' ') results in a digit with no | 
|---|
| 72 | segments highlighted. The underscore ('_') | 
|---|
| 73 | results in a place with no segments at all. | 
|---|
| 74 | This might be useful if you want to display | 
|---|
| 75 | date and time in one panel, as an example. | 
|---|
| 76 |  | 
|---|
| 77 | After each character, an additional modifier | 
|---|
| 78 | may be used to control the separators between | 
|---|
| 79 | two digits. The following modifiers are | 
|---|
| 80 | supported: | 
|---|
| 81 |  | 
|---|
| 82 | '~'      - No separator at all, not even | 
|---|
| 83 | the segments are displayed. | 
|---|
| 84 | '.', ',' - Highlights the lower separator | 
|---|
| 85 | segment. | 
|---|
| 86 | ':'      - Highlights both separator segments. | 
|---|
| 87 |  | 
|---|
| 88 | The modifiers are optional. If none of them | 
|---|
| 89 | is present, both separator segments are | 
|---|
| 90 | visible, but not highlighted. } | 
|---|
| 91 | property DragCursor; | 
|---|
| 92 | property DragMode; | 
|---|
| 93 | property Margin: LongInt read FMargin write SetMargin; | 
|---|
| 94 | { Holds the distance between each of the four | 
|---|
| 95 | borders and the digits. } | 
|---|
| 96 | property ParentShowHint; | 
|---|
| 97 | property PopupMenu; | 
|---|
| 98 | property ShowHint; | 
|---|
| 99 | property Visible; | 
|---|
| 100 | property ZOrder; | 
|---|
| 101 |  | 
|---|
| 102 | property OnCanDrag; | 
|---|
| 103 | property OnDblClick; | 
|---|
| 104 | property OnDragDrop; | 
|---|
| 105 | property OnDragOver; | 
|---|
| 106 | property OnEndDrag; | 
|---|
| 107 | property OnMouseClick; | 
|---|
| 108 | property OnMouseDblClick; | 
|---|
| 109 | property OnMouseDown; | 
|---|
| 110 | property OnMouseMove; | 
|---|
| 111 | property OnMouseUp; | 
|---|
| 112 | property OnResize; | 
|---|
| 113 | property OnSetupShow; | 
|---|
| 114 | property OnStartDrag; | 
|---|
| 115 | end; | 
|---|
| 116 |  | 
|---|
| 117 | implementation | 
|---|
| 118 |  | 
|---|
| 119 | {$r Seven} | 
|---|
| 120 |  | 
|---|
| 121 | var | 
|---|
| 122 | Digits: TBitmap; | 
|---|
| 123 |  | 
|---|
| 124 | procedure DrawDigit(Canvas: TCanvas; Dest: TRect; Digit, Separator: Byte); | 
|---|
| 125 | var | 
|---|
| 126 | SourceRect, DestRect: TRect; | 
|---|
| 127 | begin | 
|---|
| 128 | DestRect := Dest; | 
|---|
| 129 | Dec(DestRect.Right, (Dest.Right - Dest.Left) div 5); | 
|---|
| 130 |  | 
|---|
| 131 | with SourceRect do | 
|---|
| 132 | begin | 
|---|
| 133 | Left   := 20 * (Digit mod 10); | 
|---|
| 134 | Bottom := 60 - 30 * Int((Digit / 10)); (* Igitt! *) | 
|---|
| 135 | Right  := Left + 20; | 
|---|
| 136 | Top    := Bottom + 30; | 
|---|
| 137 | end; | 
|---|
| 138 |  | 
|---|
| 139 | Digits.PartialDraw(Canvas, SourceRect, DestRect); | 
|---|
| 140 |  | 
|---|
| 141 | DestRect.Left := DestRect.Right; | 
|---|
| 142 | DestRect.Right := Dest.Right; | 
|---|
| 143 |  | 
|---|
| 144 | with SourceRect do | 
|---|
| 145 | begin | 
|---|
| 146 | Left   := 180 + Separator * 5; | 
|---|
| 147 | Right  := Left + 5; | 
|---|
| 148 | Bottom := 0; | 
|---|
| 149 | Top    := 30; | 
|---|
| 150 | end; | 
|---|
| 151 |  | 
|---|
| 152 | Digits.PartialDraw(Canvas, SourceRect, DestRect); | 
|---|
| 153 | end; | 
|---|
| 154 |  | 
|---|
| 155 | constructor TSevenSegDisplay.Create(Owner: TComponent); | 
|---|
| 156 | begin | 
|---|
| 157 | inherited Create(Owner); | 
|---|
| 158 | Name := 'SevenSegDisplay'; | 
|---|
| 159 | Width := 110; | 
|---|
| 160 | Height := 40; | 
|---|
| 161 | Color := clBlack; | 
|---|
| 162 | PenColor := clBlack; | 
|---|
| 163 | Margin := 5; | 
|---|
| 164 | end; | 
|---|
| 165 |  | 
|---|
| 166 | procedure TSevenSegDisplay.Redraw(const Rec: TRect); | 
|---|
| 167 | var | 
|---|
| 168 | DestRect: TRect; | 
|---|
| 169 | DigitWidth, DigitHeight: LongInt; | 
|---|
| 170 | I, B: Byte; | 
|---|
| 171 | begin | 
|---|
| 172 | inherited Redraw(Rec); | 
|---|
| 173 |  | 
|---|
| 174 | DestRect := ClientRect; | 
|---|
| 175 |  | 
|---|
| 176 | if BorderStyle = bsSingle then | 
|---|
| 177 | DrawSystemBorder(self, DestRect, bsSingle); | 
|---|
| 178 |  | 
|---|
| 179 | if FSegments = '' then Exit; | 
|---|
| 180 |  | 
|---|
| 181 | DigitWidth := (Width - 2 * FMargin) div Length(FSegments); | 
|---|
| 182 | DigitHeight := Height - 2 * FMargin; | 
|---|
| 183 |  | 
|---|
| 184 | DestRect := Rect(FMargin, FMargin, FMargin + DigitWidth, FMargin + DigitHeight); | 
|---|
| 185 |  | 
|---|
| 186 | for I := 1 to Length(FSegments) do | 
|---|
| 187 | begin | 
|---|
| 188 | B := Ord(FSegments[I]); | 
|---|
| 189 |  | 
|---|
| 190 | if not IsRectEmpty(IntersectRect(Rec, DestRect)) then | 
|---|
| 191 | DrawDigit(Canvas, DestRect, B and 31, B shr 5); | 
|---|
| 192 |  | 
|---|
| 193 | Inc(DestRect.Left, DigitWidth); | 
|---|
| 194 | Inc(DestRect.Right, DigitWidth); | 
|---|
| 195 | end; | 
|---|
| 196 | end; | 
|---|
| 197 |  | 
|---|
| 198 | procedure TSevenSegDisplay.SetBorderStyle(Value: TBorderStyle); | 
|---|
| 199 | begin | 
|---|
| 200 | FBorderStyle := Value; | 
|---|
| 201 | Invalidate; | 
|---|
| 202 | end; | 
|---|
| 203 |  | 
|---|
| 204 | procedure TSevenSegDisplay.SetDigits(const Value: string); | 
|---|
| 205 | var | 
|---|
| 206 | I: Integer; | 
|---|
| 207 | C: Char; | 
|---|
| 208 | D: Byte; | 
|---|
| 209 | begin | 
|---|
| 210 | if Value <> FDigits then | 
|---|
| 211 | begin | 
|---|
| 212 | FSegments := ''; | 
|---|
| 213 | I := 1; | 
|---|
| 214 | while I <= Length(Value) do | 
|---|
| 215 | begin | 
|---|
| 216 | C := UpCase(Value[I]); | 
|---|
| 217 | case C of | 
|---|
| 218 | '0' .. '9': D := Ord(C) - Ord('0'); | 
|---|
| 219 | 'A' .. 'F': D := 10 + Ord(C) - Ord('A'); | 
|---|
| 220 | 'H'       : D := 16; | 
|---|
| 221 | 'I'       : D := 17; | 
|---|
| 222 | 'J'       : D := 18; | 
|---|
| 223 | 'L'       : D := 19; | 
|---|
| 224 | 'N'       : D := 20; | 
|---|
| 225 | 'O'       : D := 21; | 
|---|
| 226 | 'R'       : D := 22; | 
|---|
| 227 | 'S'       : D :=  5; | 
|---|
| 228 | 'U'       : D := 23; | 
|---|
| 229 | 'Y'       : D := 24; | 
|---|
| 230 | ' '       : D := 26; | 
|---|
| 231 | '-'       : D := 27; | 
|---|
| 232 | '_'       : D := 28; | 
|---|
| 233 | else | 
|---|
| 234 | D := 255; | 
|---|
| 235 | end; | 
|---|
| 236 | Inc(I); | 
|---|
| 237 |  | 
|---|
| 238 | if I <= Length(Value) then | 
|---|
| 239 | begin | 
|---|
| 240 | C := UpCase(Value[I]); | 
|---|
| 241 | case C of | 
|---|
| 242 | '~':      Inc(I); | 
|---|
| 243 | '.', ',': begin | 
|---|
| 244 | D := D or 64; | 
|---|
| 245 | Inc(I); | 
|---|
| 246 | end; | 
|---|
| 247 | ':':      begin | 
|---|
| 248 | D := D or 96; | 
|---|
| 249 | Inc(I); | 
|---|
| 250 | end; | 
|---|
| 251 | else | 
|---|
| 252 | D := D or 32; | 
|---|
| 253 | end; | 
|---|
| 254 | end | 
|---|
| 255 | else D := D or 32; | 
|---|
| 256 |  | 
|---|
| 257 | if D <> 255 then FSegments := FSegments + Chr(D); | 
|---|
| 258 | end; | 
|---|
| 259 | end; | 
|---|
| 260 |  | 
|---|
| 261 | FDigits := Value; | 
|---|
| 262 |  | 
|---|
| 263 | InvalidateRect(Rect(FMargin, FMargin, Width - FMargin, Height - FMargin)); | 
|---|
| 264 | end; | 
|---|
| 265 |  | 
|---|
| 266 | procedure TSevenSegDisplay.SetMargin(Value: LongInt); | 
|---|
| 267 | begin | 
|---|
| 268 | FMargin := Value; | 
|---|
| 269 | Invalidate; | 
|---|
| 270 | end; | 
|---|
| 271 |  | 
|---|
| 272 | initialization | 
|---|
| 273 | RegisterClasses([TSevenSegDisplay]); | 
|---|
| 274 |  | 
|---|
| 275 | Digits := TBitmap.Create; | 
|---|
| 276 | Digits.LoadFromResourceName('SevenSegDigits'); | 
|---|
| 277 |  | 
|---|
| 278 | finalization | 
|---|
| 279 |  | 
|---|
| 280 | Digits.Free; | 
|---|
| 281 | end. | 
|---|
| 282 |  | 
|---|