/[projects]/dao/DelphiScanner/Components/tpsystools_4.04/source/StBarC.pas
ViewVC logotype

Contents of /dao/DelphiScanner/Components/tpsystools_4.04/source/StBarC.pas

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2671 - (show annotations) (download)
Tue Aug 25 18:15:15 2015 UTC (8 years, 9 months ago) by torben
File size: 71915 byte(s)
Added tpsystools component
1 // Upgraded to Delphi 2009: Sebastian Zierer
2
3 (* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1
5 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 *
16 * The Original Code is TurboPower SysTools
17 *
18 * The Initial Developer of the Original Code is
19 * TurboPower Software
20 *
21 * Portions created by the Initial Developer are Copyright (C) 1996-2002
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * ***** END LICENSE BLOCK ***** *)
27
28 {*********************************************************}
29 {* SysTools: StBarC.pas 4.04 *}
30 {*********************************************************}
31 {* SysTools: bar code components *}
32 {*********************************************************}
33
34 {$I StDefine.inc}
35
36 unit StBarC;
37
38 interface
39
40 uses
41 Windows,
42 Classes, ClipBrd, Controls, Graphics, Messages, SysUtils,
43 StBase, StConst;
44
45 const
46 {.Z+}
47 bcMaxBarCodeLen = 255;
48 bcGuardBarAbove = True;
49 bcGuardBarBelow = True;
50 bcDefNarrowToWideRatio = 2;
51 {.Z-}
52
53 type
54 TStBarKind = (bkSpace, bkBar, bkThreeQuarterBar, bkHalfBar, bkGuard, bkSupplement, bkBlankSpace);
55 {.Z+}
56 TStBarKindSet = set of TStBarKind;
57 TStDigitArray = array[1..bcMaxBarCodeLen] of Byte;
58 {.Z-}
59
60 {.Z+}
61 TStBarData = class
62 FKind : TStBarKindSet;
63 FModules : Integer;
64 public
65 property Kind : TStBarKindSet
66 read FKind
67 write FKind;
68 property Modules : Integer
69 read FModules
70 write FModules;
71 end;
72 {.Z-}
73
74 {.Z+}
75 TStBarCodeInfo = class
76 private
77 FBars : TList;
78
79 function GetBars(Index : Integer) : TStBarData;
80 function GetCount : Integer;
81
82 public
83 constructor Create;
84 virtual;
85 destructor Destroy;
86 override;
87 procedure Add(ModuleCount : Integer; BarKind : TStBarKindSet);
88 procedure Clear;
89
90 property Bars[Index : Integer] : TStBarData
91 read GetBars;
92 default;
93
94 property Count : Integer
95 read GetCount;
96 end;
97 {.Z-}
98
99 TStBarCodeType = (bcUPC_A, bcUPC_E, bcEAN_8, bcEAN_13,
100 bcInterleaved2of5, bcCodabar, bcCode11,
101 bcCode39, bcCode93, bcCode128);
102 TStCode128CodeSubset = (csCodeA, csCodeB, csCodeC);
103
104 TStBarCode = class(TGraphicControl)
105 protected {private}
106 {property variables}
107 {.Z+}
108 FAddCheckChar : Boolean;
109 FBarCodeType : TStBarCodeType;
110 FBarColor : TColor;
111 FBarToSpaceRatio : Double;
112 FBarNarrowToWideRatio : Integer;
113 FBarWidth : Double; {in mils}
114 FCode128Subset : TStCode128CodeSubset;
115 FBearerBars : Boolean;
116 FShowCode : Boolean;
117 FShowGuardChars : Boolean;
118 FSupplementalCode : string;
119 FTallGuardBars : Boolean;
120 FExtendedSyntax : Boolean;
121
122 {internal variables}
123 bcBarInfo : TStBarCodeInfo;
124 bcBarModWidth : Integer; {width of single bar}
125 bcCheckK : Integer; {"K" check character for use by Code11}
126 bcDigits : TStDigitArray;
127 bcDigitCount : Integer;
128 bcSpaceModWidth : Integer; {width of empty space between bars}
129 bcNormalWidth : Integer;
130 bcSpaceWidth : Integer;
131 bcSupplementWidth: Integer;
132
133 {property methods}
134 function GetCode : string;
135 function GetVersion : string;
136 procedure SetAddCheckChar(Value : Boolean);
137 procedure SetBarCodeType(Value : TStBarCodeType);
138 procedure SetBarColor(Value : TColor);
139 procedure SetBarToSpaceRatio(Value : Double);
140 procedure SetBarNarrowToWideRatio(Value: Integer);
141 procedure SetBarWidth(Value : Double);
142 procedure SetBearerBars(Value : Boolean);
143 procedure SetCode(const Value : string);
144 procedure SetCode128Subset(Value : TStCode128CodeSubset);
145 procedure SetExtendedSyntax (const v : Boolean);
146 procedure SetShowCode(Value : Boolean);
147 procedure SetShowGuardChars(Value : Boolean);
148 procedure SetSupplementalCode(const Value : string);
149 procedure SetTallGuardBars(Value : Boolean);
150 procedure SetVersion(const Value : string);
151
152 {internal methods}
153 procedure CalcBarCode;
154 procedure CalcBarCodeWidth;
155 function DrawBar(XPos, YPos, AWidth, AHeight : Integer) : Integer;
156 procedure DrawBarCode(const R : TRect);
157 function GetDigits(Characters : string) : Integer;
158 procedure PaintPrim(const R : TRect);
159 function SmallestLineWidth(PixelsPerInch : Integer) : Double;
160
161 {VCL message methods}
162 procedure CMTextChanged(var Msg : TMessage);
163 message CM_TEXTCHANGED;
164
165 protected
166 procedure Loaded;
167 override;
168 procedure Paint;
169 override;
170 public
171 constructor Create(AOwner : TComponent);
172 override;
173 destructor Destroy;
174 override;
175 {.Z-}
176
177 procedure CopyToClipboard;
178 procedure GetCheckCharacters(const S : string; var C, K : Integer);
179 function GetBarCodeWidth(ACanvas : TCanvas) : Double;
180 procedure PaintToCanvas(ACanvas : TCanvas; ARect : TRect);
181 procedure PaintToCanvasSize(ACanvas : TCanvas; X, Y, H : Double);
182 procedure PaintToDC(DC : hDC; ARect : TRect);
183 procedure PaintToDCSize(DC : hDC; X, Y, W, H : Double);
184 procedure SaveToFile(const FileName : string);
185 function Validate(DisplayError : Boolean) : Boolean;
186
187 published
188 {properties}
189 property Align;
190 property Color;
191 property Cursor;
192 property Enabled;
193 property Font;
194 property ParentColor;
195 property ParentFont;
196 property ParentShowHint;
197 property ShowHint;
198 property Visible;
199
200 property AddCheckChar : Boolean
201 read FAddCheckChar
202 write SetAddCheckChar;
203
204 property BarCodeType : TStBarCodeType
205 read FBarCodeType
206 write SetBarCodeType;
207
208 property BarColor : TColor
209 read FBarColor
210 write SetBarColor;
211
212 property BarToSpaceRatio : Double
213 read FBarToSpaceRatio
214 write SetBarToSpaceRatio;
215
216 property BarNarrowToWideRatio : Integer
217 read FBarNarrowToWideRatio
218 write SetBarNarrowToWideRatio
219 default bcDefNarrowToWideRatio;
220
221 property BarWidth : Double
222 read FBarWidth
223 write SetBarWidth;
224
225 property BearerBars : Boolean
226 read FBearerBars
227 write SetBearerBars;
228
229 property Code : string
230 read GetCode
231 write SetCode;
232
233 property Code128Subset : TStCode128CodeSubset
234 read FCode128Subset
235 write SetCode128Subset;
236
237 property ExtendedSyntax : Boolean
238 read FExtendedSyntax write SetExtendedSyntax
239 default False;
240
241 property ShowCode : Boolean
242 read FShowCode
243 write SetShowCode;
244
245 property ShowGuardChars : Boolean
246 read FShowGuardChars
247 write SetShowGuardChars;
248
249 property SupplementalCode : string
250 read FSupplementalCode
251 write SetSupplementalCode;
252
253 property TallGuardBars : Boolean
254 read FTallGuardBars
255 write SetTallGuardBars;
256
257 property Version : string
258 read GetVersion
259 write SetVersion
260 stored False;
261
262 {events}
263 property OnClick;
264 property OnDblClick;
265 property OnMouseDown;
266 property OnMouseMove;
267 property OnMouseUp;
268 end;
269
270
271 implementation
272
273 const
274 {left and right codes for UPC_A}
275 UPC_A_LeftHand : array[0..9] of string =
276 ('0001101', {0}
277 '0011001', {1}
278 '0010011', {2}
279 '0111101', {3}
280 '0100011', {4}
281 '0110001', {5}
282 '0101111', {6}
283 '0111011', {7}
284 '0110111', {8}
285 '0001011' {9} );
286
287 UPC_A_RightHand : array[0..9] of string =
288 ('1110010', {0}
289 '1100110', {1}
290 '1101100', {2}
291 '1000010', {3}
292 '1011100', {4}
293 '1001110', {5}
294 '1010000', {6}
295 '1000100', {7}
296 '1001000', {8}
297 '1110100' {9} );
298
299 const
300 UPC_E_OddParity : array[0..9] of string =
301 ('0001101', {0}
302 '0011001', {1}
303 '0010011', {2}
304 '0111101', {3}
305 '0100011', {4}
306 '0110001', {5}
307 '0101111', {6}
308 '0111011', {7}
309 '0110111', {8}
310 '0001011' {9} );
311
312 UPC_E_EvenParity : array[0..9] of string =
313 ('0100111', {0}
314 '0110011', {1}
315 '0011011', {2}
316 '0100001', {3}
317 '0011101', {4}
318 '0111001', {5}
319 '0000101', {6}
320 '0010001', {7}
321 '0001001', {8}
322 '0010111' {9} );
323
324 const
325 EAN_LeftHandA : array[0..9] of string =
326 ('0001101', {0}
327 '0011001', {1}
328 '0010011', {2}
329 '0111101', {3}
330 '0100011', {4}
331 '0110001', {5}
332 '0101111', {6}
333 '0111011', {7}
334 '0110111', {8}
335 '0001011' {9} );
336
337 EAN_LeftHandB : array[0..9] of string =
338 ('0100111', {0}
339 '0110011', {1}
340 '0011011', {2}
341 '0100001', {3}
342 '0011101', {4}
343 '0111001', {5}
344 '0000101', {6}
345 '0010001', {7}
346 '0001001', {8}
347 '0010111' {9} );
348
349 const
350 Interleaved_2of5 : array[0..9] of string =
351 ('00110', {0}
352 '10001', {1}
353 '01001', {2}
354 '11000', {3}
355 '00101', {4}
356 '10100', {5}
357 '01100', {6}
358 '00011', {7}
359 '10010', {8}
360 '01010' {9} );
361
362 const
363 Codabar : array[0..19] of string =
364 {BSBSBSB} {bar-space-bar-space-bar...}
365 ('0000011', {0}
366 '0000110', {1}
367 '0001001', {2}
368 '1100000', {3}
369 '0010010', {4}
370 '1000010', {5}
371 '0100001', {6}
372 '0100100', {7}
373 '0110000', {8}
374 '1001000', {9}
375 '0001100', {-}
376 '0011000', { $}
377 '1000101', {:}
378 '1010001', {/}
379 '1010100', {.}
380 '0010101', {+}
381 '0011010', {A}
382 '0101001', {B}
383 '0001011', {C}
384 '0001110' {D});
385
386 const
387 Code11 : array[0..11] of string =
388 {BSBSB} {bar-space-bar-space-bar...} {0-narrow, 1-wide}
389 ('00001', {0}
390 '10001', {1}
391 '01001', {2}
392 '11000', {3}
393 '00101', {4}
394 '10100', {5}
395 '01100', {6}
396 '00011', {7}
397 '10010', {8}
398 '10000', {9}
399 '00100', {-}
400 '00110'); {stop character}
401
402 const
403 Code39 : array[0..43] of string =
404 {BSBSBSBSB} {bar-space-bar-space-bar...} {0-narrow, 1-wide}
405 ('000110100', {0}
406 '100100001', {1}
407 '001100001', {2}
408 '101100000', {3}
409 '000110001', {4}
410 '100110000', {5}
411 '001110000', {6}
412 '000100101', {7}
413 '100100100', {8}
414 '001100100', {9}
415 '100001001', {A}
416 '001001001', {B}
417 '101001000', {C}
418 '000011001', {D}
419 '100011000', {E}
420 '001011000', {F}
421 '000001101', {G}
422 '100001100', {H}
423 '001001100', {I}
424 '000011100', {J}
425 '100000011', {K}
426 '001000011', {L}
427 '101000010', {M}
428 '000010011', {N}
429 '100010010', {O}
430 '001010010', {P}
431 '000000111', {Q}
432 '100000110', {R}
433 '001000110', {S}
434 '000010110', {T}
435 '110000001', {U}
436 '011000001', {V}
437 '111000000', {W}
438 '010010001', {X}
439 '110010000', {Y}
440 '011010000', {Z}
441 '010000101', {-}
442 '110000100', {.}
443 '011000100', {SPACE}
444 '010101000', { $}
445 '010100010', {/}
446 '010001010', {+}
447 '000101010', {%}
448 '010010100'); {*}
449
450 const
451 Code93 : array[0..46] of string =
452 {BSBSBS} {bar-space-bar-space-bar...} {0-narrow, 1-wide}
453 ('131112', {0}
454 '111213', {1}
455 '111312', {2}
456 '111411', {3}
457 '121113', {4}
458 '121212', {5}
459 '121311', {6}
460 '111114', {7}
461 '131211', {8}
462 '141111', {9}
463 '211113', {A}
464 '211212', {B}
465 '211311', {C}
466 '221112', {D}
467 '221211', {E}
468 '231111', {F}
469 '112113', {G}
470 '112212', {H}
471 '112311', {I}
472 '122112', {J}
473 '132111', {K}
474 '111123', {L}
475 '111222', {M}
476 '111321', {N}
477 '121122', {O}
478 '131121', {P}
479 '212112', {Q}
480 '212211', {R}
481 '211122', {S}
482 '211221', {T}
483 '221121', {U}
484 '222111', {V}
485 '112122', {W}
486 '112221', {X}
487 '122121', {Y}
488 '123111', {Z}
489 '121131', {-}
490 '311112', {.}
491 '311211', {SPACE}
492 '321111', { $}
493 '112131', {/}
494 '113121', {+}
495 '211131', {%}
496 '121221', {($)}
497 '312111', {(%)}
498 '311121', {(/)}
499 '122211'); {(+)}
500
501 Code93Map : array[#0..#127] of string =
502 {Circle Code} {ASCII Code 93 }
503 ('%U', {NL (%)U }
504 '$A', {SH ($)A }
505 '$B', {SX ($)B }
506 '$C', {EX ($)C }
507 '$D', {ET ($)D }
508 '$E', {EQ ($)E }
509 '$F', {AK ($)F }
510 '$G', {BL ($)G }
511 '$H', {BS ($)H }
512 '$I', {HT ($)I }
513 '$J', {LF ($)J }
514 '$K', {VT ($)K }
515 '$L', {FF ($)L }
516 '$M', {CR ($)M }
517 '$N', {SO ($)N }
518 '$O', {SI ($)O }
519 '$P', {DL ($)P }
520 '$Q', {D1 ($)Q }
521 '$R', {D2 ($)R }
522 '$S', {D3 ($)S }
523 '$T', {D4 ($)T }
524 '$U', {NK ($)U }
525 '$V', {SY ($)V }
526 '$W', {EB ($)W }
527 '$X', {CN ($)X }
528 '$Y', {EM ($)Y }
529 '$Z', {SB ($)Z }
530 '%A', {EC (%)A }
531 '%B', {FS (%)B }
532 '%C', {GS (%)C }
533 '%D', {RS (%)D }
534 '%E', {US (%)E }
535 ' ', {Space Space }
536 '/A', {! (/)A }
537 '/B', {" (/)B }
538 '/C', {# (/)C }
539 '$', { $ (/)D or $}
540 '%', {% (/)E or %}
541 '/F', {& (/)F }
542 '/G', {' (/)G }
543 '/H', {( (/)H }
544 '/I', {) (/)I }
545 '/J', {* (/)J }
546 ' +', {+ (/)K or +}
547 '/L', {, (/)L }
548 '-', {- (/)M or -}
549 '.', {. (/)N or .}
550 '/', {/ (/)O or /}
551 '0', {0 (/)P or 0}
552 '1', {1 (/)Q or 1}
553 '2', {2 (/)R or 2}
554 '3', {3 (/)S or 3}
555 '4', {4 (/)T or 4}
556 '5', {5 (/)U or 5}
557 '6', {6 (/)V or 6}
558 '7', {7 (/)W or 7}
559 '8', {8 (/)X or 8}
560 '9', {9 (/)Y or 9}
561 '/Z', {: (/)Z }
562 '%F', {; (%)F }
563 '%G', {< (%)G }
564 '%H', {= (%)H }
565 '%I', {> (%)I }
566 '%J', {? (%)J }
567 '%V', { (%)V }
568 'A', {A A }
569 'B', {B B }
570 'C', {C C }
571 'D', {D D }
572 'E', {E E }
573 'F', {F F }
574 'G', {G G }
575 'H', {H H }
576 'I', {I I }
577 'J', {J J }
578 'K', {K K }
579 'L', {L L }
580 'M', {M M }
581 'N', {N N }
582 'O', {O O }
583 'P', {P P }
584 'Q', {Q Q }
585 'R', {R R }
586 'S', {S S }
587 'T', {T T }
588 'U', {U U }
589 'V', {V V }
590 'W', {W W }
591 'X', {X X }
592 'Y', {Y Y }
593 'Z', {Z Z }
594 '%K', {[ (%)K }
595 '%L', {\ (%)L }
596 '%M', {] (%)M }
597 '%N', {^ (%)N }
598 '%O', {_ (%)O }
599 '%W', {` (%)W }
600 '+A', {a (+)A }
601 '+B', {b (+)B }
602 '+C', {c (+)C }
603 '+D', {d (+)D }
604 '+E', {e (+)E }
605 '+F', {f (+)F }
606 '+G', {g (+)G }
607 '+H', {h (+)H }
608 '+I', {i (+)I }
609 '+J', {j (+)J }
610 '+K', {k (+)K }
611 '+L', {l (+)L }
612 '+M', {m (+)M }
613 '+N', {n (+)N }
614 '+O', {o (+)O }
615 '+P', {p (+)P }
616 '+Q', {q (+)Q }
617 '+R', {r (+)R }
618 '+S', {s (+)S }
619 '+T', {t (+)T }
620 '+U', {u (+)U }
621 '+V', {v (+)V }
622 '+W', {w (+)W }
623 '+X', {x (+)X }
624 '+Y', {y (+)Y }
625 '+Z', {z (+)Z }
626 '%P', {{ (%)P }
627 '%Q', {| (%)Q }
628 '%R', {}{ (%)R }
629 '%S', {~ (%)S }
630 '%T'); { DEL (%)T }
631
632 const
633 Code128 : array[0..106] of string =
634 {BSBSBS} {Value CodeA CodeB CodeC}
635 ('212222', {0 SPACE SPACE 00}
636 '222122', {1 ! ! 01}
637 '222221', {2 " " 02}
638 '121223', {3 # # 03}
639 '121322', {4 $ $ 04}
640 '131222', {5 % % 05}
641 '122213', {6 & & 06}
642 '122312', {7 ' ' 07}
643 '132212', {8 ( ( 08}
644 '221213', {9 ) ) 09}
645 '221312', {10 * * 10}
646 '231212', {11 + + 11}
647 '112232', {12 , , 12}
648 '122132', {13 - - 13}
649 '122231', {14 . . 14}
650 '113222', {15 / / 15}
651 '123122', {16 0 0 16}
652 '123221', {17 1 1 17}
653 '223211', {18 2 2 18}
654 '221132', {19 3 3 19}
655 '221231', {20 4 4 20}
656 '213212', {21 5 5 21}
657 '223112', {22 6 6 22}
658 '312131', {23 7 7 23}
659 '311222', {24 8 8 24}
660 '321122', {25 9 9 25}
661 '321221', {26 : : 26}
662 '312212', {27 ; ; 27}
663 '322112', {28 < < 28}
664 '322211', {29 = = 29}
665 '212123', {30 > > 30}
666 '212321', {31 ? ? 31}
667 '232121', {32 @ @ 32}
668 '111323', {33 A A 33}
669 '131123', {34 B B 34}
670 '131321', {35 C C 35}
671 '112313', {36 D D 36}
672 '132113', {37 E E 37}
673 '132311', {38 F F 38}
674 '211313', {39 G G 39}
675 '231113', {40 H H 40}
676 '231311', {41 I I 41}
677 '112133', {42 J J 42}
678 '112331', {43 K K 43}
679 '132131', {44 L L 44}
680 '113123', {45 M M 45}
681 '113321', {46 N N 46}
682 '133121', {47 O O 47}
683 '313121', {48 P P 48}
684 '211331', {49 Q Q 49}
685 '231131', {50 R R 50}
686 '213113', {51 S S 51}
687 '213311', {52 T T 52}
688 '213131', {53 U U 53}
689 '311123', {54 V V 54}
690 '311321', {55 W W 55}
691 '331121', {56 X X 56}
692 '312113', {57 Y Y 57}
693 '312311', {58 Z Z 58}
694 '332111', {59 [ [ 59}
695 '314111', {60 \ \ 60}
696 '221411', {61 ] ] 61}
697 '431111', {62 ^ ^ 62}
698 '111224', {63 _ _ 63}
699 '111422', {64 NU ` 64}
700 '121124', {65 SH a 65}
701 '121421', {66 SX b 66}
702 '141122', {67 EX c 67}
703 '141221', {68 ET d 68}
704 '112214', {69 EQ e 69}
705 '112412', {70 AK f 70}
706 '122114', {71 BL g 71}
707 '122411', {72 BS h 72}
708 '142112', {73 HT i 73}
709 '142211', {74 LF j 74}
710 '241211', {75 VT k 75}
711 '221114', {76 FF l 76}
712 '413111', {77 CR m 77}
713 '241112', {78 SO n 78}
714 '134111', {79 SI o 79}
715 '111242', {80 DL p 80}
716 '121142', {81 D1 q 81}
717 '121241', {82 D2 r 82}
718 '114212', {83 D3 s 83}
719 '124112', {84 D4 t 84}
720 '124211', {85 NK u 85}
721 '411212', {86 SY v 86}
722 '421112', {87 EB w 87}
723 '421211', {88 CN x 88}
724 '212141', {89 EM y 89}
725 '214121', {90 SB z 90}
726 '412121', (*91 EC { 91*)
727 '111143', {92 FS 92}
728 '111341', (*93 GS } 93*)
729 '131141', {94 RS ~ 94}
730 '114113', {95 US DEL 95}
731 '114311', {96 FNC 3 FNC 3 96} {use #132}
732 '411113', {97 FNC 2 FNC 2 97} {use #131}
733 '411311', {98 SHIFT SHIFT 98} {use #130}
734 '113141', {99 CODE C CODE C 99} {use #135}
735 '114131', {100 CODE B FNC 4 CODE B} {use #134}
736 '311141', {101 FNC 4 CODE A CODE A} {use #133}
737 '411131', {102 FNC 1 FNC 1 FNC 1 } {use #130}
738 '211412', {103 CODE A} {use #136}
739 '211214', {104 CODE B} {use #137}
740 '211232', {105 CODE C} {use #138}
741 '2331112');{106 STOP} {use #139}
742
743
744 {*** helper routines ***}
745
746 function RectWidth(const R : TRect) : Integer;
747 begin
748 Result := R.Right-R.Left;
749 end;
750
751 function RectHeight(const R : TRect) : Integer;
752 begin
753 Result := R.Bottom-R.Top;
754 end;
755
756
757 {*** TStBarCodeInfo ***}
758
759 procedure TStBarCodeInfo.Add(ModuleCount : Integer; BarKind : TStBarKindSet);
760 var
761 Bar : TStBarData;
762 begin
763 Bar := TStBarData.Create;
764 Bar.Modules := ModuleCount;
765 Bar.Kind := BarKind;
766 FBars.Add(Bar);
767 end;
768
769 procedure TStBarCodeInfo.Clear;
770 var
771 I : Integer;
772 begin
773 for I := 0 to FBars.Count-1 do
774 TStBarData(FBars[I]).Free;
775 FBars.Clear;
776 end;
777
778 constructor TStBarCodeInfo.Create;
779 begin
780 inherited Create;
781
782 FBars := TList.Create;
783 end;
784
785 destructor TStBarCodeInfo.Destroy;
786 begin
787 Clear;
788 FBars.Free;
789 FBars := nil;
790
791 inherited Destroy;
792 end;
793
794 function TStBarCodeInfo.GetBars(Index : Integer) : TStBarData;
795 begin
796 Result := FBars[Index];
797 end;
798
799 function TStBarCodeInfo.GetCount : Integer;
800 begin
801 Result := FBars.Count;
802 end;
803
804
805 {*** TStBarCode ***}
806
807 procedure TStBarCode.CalcBarCode;
808 var
809 I, J, X : Integer;
810 CheckC : Integer;
811 CheckK : Integer;
812 CSP : string;
813 C : string;
814 C1, C2 : string;
815
816 procedure AddCode(const S : string; AKind : TStBarKindSet);
817 var
818 I : Integer;
819 begin
820 for I := 1 to Length(S) do
821 if S[I] = '0' then
822 bcBarInfo.Add(1, AKind - [bkBar, bkThreeQuarterBar, bkHalfBar] + [bkSpace])
823 else
824 bcBarInfo.Add(StrToInt(S[I]), AKind);
825 end;
826
827 procedure AddECode(const Parity : string);
828 var
829 I : Integer;
830 begin
831 for I := 1 to Length(Parity) do begin
832 if Parity[I] = 'E' then
833 AddCode(UPC_E_EvenParity[bcDigits[I]], [bkBar])
834 else
835 AddCode(UPC_E_OddParity[bcDigits[I]], [bkBar]);
836 end;
837 end;
838
839 procedure AddSupCode(const Parity : string);
840 var
841 I : Integer;
842 begin
843 for I := 1 to Length(Parity) do begin
844 if Parity[I] = 'E' then
845 AddCode(UPC_E_EvenParity[bcDigits[I]], [bkThreeQuarterBar, bkSupplement])
846 else
847 AddCode(UPC_E_OddParity[bcDigits[I]], [bkThreeQuarterBar, bkSupplement]);
848 if I < Length(Parity) then
849 AddCode('01', [bkThreeQuarterBar, bkSupplement]);
850 end;
851 end;
852
853 procedure AddCodeModules(const S : string);
854 var
855 K : Integer;
856 begin
857 for K := 1 to Length(S) do begin
858 if Odd(K) then
859 bcBarInfo.Add(StrToInt(S[K]), [bkBar])
860 else
861 bcBarInfo.Add(StrToInt(S[K]), [bkSpace]);
862 end;
863 end;
864
865 procedure AddCodeWideNarrow(const S : string);
866 var
867 K : Integer;
868 begin
869 for K := 1 to Length(S) do begin
870 case S[K] of
871 '0' : if Odd(K) then
872 bcBarInfo.Add(1, [bkBar])
873 else
874 bcBarInfo.Add(1, [bkSpace]);
875 '1' : if Odd(K) then
876 bcBarInfo.Add(FBarNarrowToWideRatio, [bkBar])
877 else
878 bcBarInfo.Add(FBarNarrowToWideRatio, [bkSpace]);
879 end;
880 end;
881 end;
882
883 begin
884 if csLoading in ComponentState then
885 Exit;
886
887 bcBarInfo.Clear;
888 if Code = '' then
889 Exit;
890
891 {get copy of code}
892 C := Code;
893
894 {get digits}
895 case FBarCodeType of
896 bcUPC_A, bcUPC_E, bcEAN_8, bcEAN_13, bcCodabar, bcCode11, bcCode93 :
897 begin
898 bcDigitCount := GetDigits(C);
899 end;
900 bcInterleaved2of5 :
901 begin
902 {adjust odd length code}
903 if FAddCheckChar then begin
904 if not Odd(Length(C)) then
905 C := '0' + C;
906 end else begin
907 if Odd(Length(C)) then
908 C := '0' + C;
909 end;
910 bcDigitCount := GetDigits(C);
911 end;
912 bcCode39 :
913 begin
914 {add guard characters}
915 if C[1] <> '*' then
916 C := '*' + C;
917 if C[Length(C)] <> '*' then
918 C := C + '*';
919 bcDigitCount := GetDigits(C);
920 end;
921 bcCode128 :
922 begin
923 {add start code}
924 if not (C[1] in [#136, #137, #138]) then
925 case FCode128Subset of
926 csCodeA : C := #136 + C;
927 csCodeB : C := #137 + C;
928 csCodeC : C := #138 + C;
929 end;
930 bcDigitCount := GetDigits(C);
931 end;
932 end;
933
934 case FBarCodeType of
935 bcUPC_A :
936 begin
937 {get check digit}
938 if Length(C) = 11 then
939 GetCheckCharacters(C, CheckC, CheckK)
940 else
941 CheckC := bcDigits[12];
942
943 {encode left hand guard bars}
944 AddCode('101', [bkGuard, bkBar]);
945
946 {first six characters as left hand characters}
947 for I := 1 to 6 do
948 AddCode(UPC_A_LeftHand[bcDigits[I]], [bkBar]);
949
950 {center guard pattern}
951 AddCode('01010', [bkGuard, bkBar]);
952
953 {last five data characters as right hand characters}
954 for I := 7 to 11 do
955 AddCode(UPC_A_RightHand[bcDigits[I]], [bkBar]);
956
957 {check character}
958 AddCode(UPC_A_RightHand[CheckC], [bkBar]);
959
960 {encode right hand guard bars}
961 AddCode('101', [bkGuard, bkBar]);
962 end;
963 bcUPC_E :
964 begin
965 {encode left hand guard bars, 101}
966 AddCode('101', [bkGuard, bkBar]);
967 GetCheckCharacters(C, CheckC, CheckK);
968 case CheckC of
969 0 : AddECode('EEEOOO');
970 1 : AddECode('EEOEOO');
971 2 : AddECode('EEOOEO');
972 3 : AddECode('EEOOOE');
973 4 : AddECode('EOEEOO');
974 5 : AddECode('EOOEEO');
975 6 : AddECode('EOOOEE');
976 7 : AddECode('EOEOEO');
977 8 : AddECode('EOEOOE');
978 9 : AddECode('EOOEOE');
979 end;
980 {encode right hand guard bars}
981 AddCode('010101', [bkGuard, bkBar]);
982 end;
983 bcEAN_8 :
984 begin
985 {get check digit}
986 if Length(C) = 7 then
987 GetCheckCharacters(C, CheckC, CheckK)
988 else
989 CheckC := bcDigits[8];
990
991 {encode left hand guard bars}
992 AddCode('101', [bkGuard, bkBar]);
993 {two flag two data characters, encoded as left hand A characters}
994 for I := 1 to 4 do
995 AddCode(EAN_LeftHandA[bcDigits[I]], [bkBar]);
996 {encode center guard bars}
997 AddCode('01010', [bkGuard, bkBar]);
998 {last three data characters, encoded as right hand characters}
999 for I := 5 to 7 do
1000 AddCode(UPC_A_RightHand[bcDigits[I]], [bkBar]);
1001 {check character}
1002 AddCode(UPC_A_RightHand[CheckC], [bkBar]);
1003 {encode right hand guard bars}
1004 AddCode('101', [bkGuard, bkBar]);
1005 end;
1006 bcEAN_13 :
1007 begin
1008 {get check digit}
1009 if Length(C) = 12 then
1010 GetCheckCharacters(C, CheckC, CheckK)
1011 else
1012 CheckC := bcDigits[13];
1013
1014 {determine which left hand table to use based on first flag character}
1015 {EAN refers to this as the 13th digit - counting from the right}
1016 case bcDigits[1] of
1017 { 12345}
1018 0 : CSP := 'AAAAAA';
1019 1 : CSP := 'AABABB';
1020 2 : CSP := 'AABBAB';
1021 3 : CSP := 'AABBBA';
1022 4 : CSP := 'ABAABB';
1023 5 : CSP := 'ABBAAB';
1024 6 : CSP := 'ABBBAA';
1025 7 : CSP := 'ABABAB';
1026 8 : CSP := 'ABABBA';
1027 9 : CSP := 'ABBABA';
1028 end;
1029 {encode left hand guard bars}
1030 AddCode('101', [bkGuard, bkBar]);
1031 {start with second flag character and next five data characters}
1032 for I := 2 to 7 do
1033 if CSP[I-1] = 'A' then
1034 AddCode(EAN_LeftHandA[bcDigits[I]], [bkBar])
1035 else
1036 AddCode(EAN_LeftHandB[bcDigits[I]], [bkBar]);
1037 {encode center guard bars}
1038 AddCode('01010', [bkGuard, bkBar]);
1039 {encode last five data characters}
1040 for I := 8 to 12 do
1041 AddCode(UPC_A_RightHand[bcDigits[I]], [bkBar]);
1042 {check character}
1043 AddCode(UPC_A_RightHand[CheckC], [bkBar]);
1044 {encode right hand guard bars}
1045 AddCode('101', [bkGuard, bkBar]);
1046 end;
1047 bcInterleaved2of5 :
1048 begin
1049 {add check character}
1050 if FAddCheckChar then begin
1051 {get check digit}
1052 GetCheckCharacters(C, CheckC, CheckK);
1053 Inc(bcDigitCount);
1054 bcDigits[bcDigitCount] := CheckC;
1055 end;
1056
1057 {encode left guard pattern}
1058 bcBarInfo.Add(1, [bkGuard, bkBar]);
1059 bcBarInfo.Add(1, [bkGuard, bkSpace]);
1060 bcBarInfo.Add(1, [bkGuard, bkBar]);
1061 bcBarInfo.Add(1, [bkGuard, bkSpace]);
1062
1063 I := 1;
1064 while I < bcDigitCount do begin
1065 {take two characters at a time - odd as bars, even as spaces}
1066 C1 := Interleaved_2of5[bcDigits[I]];
1067 C2 := Interleaved_2of5[bcDigits[I+1]];
1068 {interleave data}
1069 for J := 1 to 5 do begin
1070 if C1[J] = '1' then
1071 bcBarInfo.Add(FBarNarrowToWideRatio, [bkBar]) {wide bar}
1072 else
1073 bcBarInfo.Add(1, [bkBar]); {narrow bar}
1074 if C2[J] = '1' then
1075 bcBarInfo.Add(FBarNarrowToWideRatio, [bkSpace]){wide space}
1076 else
1077 bcBarInfo.Add(1, [bkSpace]); {narrow space}
1078 end;
1079 Inc(I, 2);
1080 end;
1081
1082 {encode right guard pattern}
1083 bcBarInfo.Add(FBarNarrowToWideRatio,
1084 [bkGuard, bkBar]); {double-width bar}
1085 bcBarInfo.Add(1, [bkGuard, bkSpace]);
1086 bcBarInfo.Add(1, [bkGuard, bkBar]);
1087 end;
1088 bcCodabar :
1089 begin
1090 for I := 1 to bcDigitCount do begin
1091 AddCodeWideNarrow(Codabar[bcDigits[I]]);
1092 if I < bcDigitCount then
1093 bcBarInfo.Add(1, [bkSpace]);
1094 end;
1095 end;
1096 bcCode11 :
1097 begin
1098 AddCodeWideNarrow(Code11[11]); {start}
1099 bcBarInfo.Add(1, [bkSpace]);
1100 {add check characters}
1101 if FAddCheckChar then begin
1102 {get check digits}
1103 GetCheckCharacters(C, CheckC, CheckK);
1104 Inc(bcDigitCount);
1105 bcDigits[bcDigitCount] := CheckC;
1106 Inc(bcDigitCount);
1107 bcDigits[bcDigitCount] := CheckK;
1108 end;
1109
1110 for I := 1 to bcDigitCount do begin
1111 AddCodeWideNarrow(Code11[bcDigits[I]]);
1112 bcBarInfo.Add(1, [bkSpace]);
1113 end;
1114 AddCodeWideNarrow(Code11[11]); {stop}
1115 end;
1116 bcCode39 :
1117 begin
1118 for I := 1 to bcDigitCount do begin
1119 C1 := Code39[bcDigits[I]];
1120 for J := 1 to Length(C1) do begin
1121 case C1[J] of
1122 '0' : if Odd(J) then
1123 bcBarInfo.Add(1, [bkBar])
1124 else
1125 bcBarInfo.Add(1, [bkSpace]);
1126 '1' : if Odd(J) then
1127 bcBarInfo.Add(2, [bkBar])
1128 else
1129 bcBarInfo.Add(2, [bkSpace]);
1130 end;
1131 end;
1132 bcBarInfo.Add(1, [bkSpace]);
1133 end;
1134 end;
1135 bcCode93 :
1136 begin;
1137 {start character}
1138 AddCodeModules('111141');
1139 {add check characters}
1140 if FAddCheckChar then begin
1141 {get check digits}
1142 GetCheckCharacters(C, CheckC, CheckK);
1143 Inc(bcDigitCount);
1144 bcDigits[bcDigitCount] := CheckC;
1145 Inc(bcDigitCount);
1146 bcDigits[bcDigitCount] := CheckK;
1147 end;
1148 for I := 1 to bcDigitCount do
1149 AddCodeModules(Code93[bcDigits[I]]);
1150 {stop character}
1151 AddCodeModules('1111411');
1152 end;
1153 bcCode128 :
1154 begin
1155 {add check character}
1156 if FAddCheckChar then begin
1157 GetCheckCharacters(C, CheckC, CheckK);
1158 Inc(bcDigitCount);
1159 bcDigits[bcDigitCount] := CheckC;
1160 end;
1161 {add stop code}
1162 Inc(bcDigitCount);
1163 bcDigits[bcDigitCount] := 106;
1164 for I := 1 to bcDigitCount do
1165 AddCodeModules(Code128[bcDigits[I]]);
1166 end;
1167 end;
1168
1169 if FBarCodeType in [bcUPC_A, bcUPC_E, bcEAN_8, bcEAN_13] then begin
1170 {add supplemental encodings if requested}
1171 if Length(FSupplementalCode) in [2, 5] then begin
1172 {get digits}
1173 bcDigitCount := GetDigits(FSupplementalCode);
1174 {7 spaces after primary code - 0000000}
1175 AddCode('0000000', [bkThreeQuarterBar, bkBlankSpace]);
1176 {encode left hand guard bars, 1011}
1177 AddCode('1011', [bkThreeQuarterBar, bkSupplement]);
1178
1179 if bcDigitCount = 2 then begin
1180 {two digit supplement}
1181 {determine parity table to use for each of the two characters}
1182 X := bcDigits[1] * 10 + bcDigits[2];
1183 case X mod 4 of
1184 0 : AddSupCode('OO');
1185 1 : AddSupCode('OE');
1186 2 : AddSupCode('EO');
1187 3 : AddSupCode('EE');
1188 end;
1189 end else begin
1190 {five digit supplement}
1191 {determine the parity pattern to use for each of the five}
1192 X := ((bcDigits[1] + bcDigits[3] + bcDigits[5])*3 + (bcDigits[2] + bcDigits[4])*9) mod 10;
1193 case X of
1194 0 : AddSupCode('EEOOO');
1195 1 : AddSupCode('EOEOO');
1196 2 : AddSupCode('EOOEO');
1197 3 : AddSupCode('EOOOE');
1198 4 : AddSupCode('OEEOO');
1199 5 : AddSupCode('OOEEO');
1200 6 : AddSupCode('OOOEE');
1201 7 : AddSupCode('OEOEO');
1202 8 : AddSupCode('OEOOE');
1203 9 : AddSupCode('OOEOE');
1204 end;
1205 end;
1206 end;
1207 end;
1208 end;
1209
1210 procedure TStBarCode.CalcBarCodeWidth;
1211 var
1212 I : Integer;
1213 begin
1214 bcNormalWidth := 0;
1215 bcSpaceWidth := 0;
1216 bcSupplementWidth := 0;
1217 for I := 0 to bcBarInfo.Count-1 do begin
1218 if bkSpace in bcBarInfo[I].Kind then begin
1219 if bkBlankSpace in bcBarInfo[I].Kind then
1220 Inc(bcSpaceWidth, bcSpaceModWidth*bcBarInfo[I].Modules)
1221 else if bkSupplement in bcBarInfo[I].Kind then
1222 Inc(bcSupplementWidth, bcSpaceModWidth*bcBarInfo[I].Modules)
1223 else
1224 Inc(bcNormalWidth, bcSpaceModWidth*bcBarInfo[I].Modules)
1225 end else begin
1226 if bkBlankSpace in bcBarInfo[I].Kind then
1227 Inc(bcSpaceWidth, bcBarModWidth*bcBarInfo[I].Modules)
1228 else if bkSupplement in bcBarInfo[I].Kind then
1229 Inc(bcSupplementWidth, bcBarModWidth*bcBarInfo[I].Modules)
1230 else
1231 Inc(bcNormalWidth, bcBarModWidth*bcBarInfo[I].Modules)
1232 end;
1233 end;
1234 end;
1235
1236 procedure TStBarCode.CMTextChanged(var Msg : TMessage);
1237 begin
1238 CalcBarCode;
1239 Invalidate;
1240 end;
1241
1242 procedure TStBarCode.CopyToClipboard;
1243 var
1244 MetaFile : TMetaFile;
1245 MetaFileCanvas : TMetaFileCanvas;
1246 Bitmap : TBitmap;
1247 begin
1248 Clipboard.Clear;
1249 Clipboard.Open;
1250 try
1251 {bitmap}
1252 Bitmap := TBitmap.Create;
1253 try
1254 Bitmap.Width := ClientWidth;
1255 Bitmap.Height := ClientHeight;
1256 PaintToDC(Bitmap.Canvas.Handle, ClientRect);
1257 Clipboard.Assign(Bitmap);
1258
1259 {metafile}
1260 MetaFile := TMetaFile.Create;
1261 try
1262 MetaFileCanvas := TMetaFileCanvas.Create(MetaFile, 0);
1263 try
1264 MetaFile.Enhanced := True;
1265 MetaFile.Width := ClientWidth;
1266 MetaFile.Height := ClientHeight;
1267 MetaFileCanvas.Draw(0, 0, Bitmap);
1268 finally
1269 MetaFileCanvas.Free;
1270 end;
1271 Clipboard.Assign(MetaFile);
1272 finally
1273 MetaFile.Free;
1274 end;
1275
1276 finally
1277 Bitmap.Free;
1278 end
1279 finally
1280 Clipboard.Close;
1281 end;
1282 end;
1283
1284 constructor TStBarCode.Create(AOwner : TComponent);
1285 begin
1286 inherited Create(AOwner);
1287
1288 bcBarInfo := TStBarCodeInfo.Create;
1289
1290 {defaults}
1291 Color := clWhite;
1292 Width := 200;
1293 Height := 75;
1294 Text := '123456789012';
1295
1296 FAddCheckChar := True;
1297 FBarColor := clBlack;
1298 FBarToSpaceRatio := 1;
1299 FBarNarrowToWideRatio := bcDefNarrowToWideRatio;
1300 FBarWidth := 12;
1301 FShowCode := True;
1302 FShowGuardChars := False;
1303 FTallGuardBars := False;
1304 FExtendedSyntax := False;
1305 end;
1306
1307 destructor TStBarCode.Destroy;
1308 begin
1309 bcBarInfo.Free;
1310 bcBarInfo := nil;
1311
1312 inherited Destroy;
1313 end;
1314
1315 function TStBarCode.DrawBar(XPos, YPos, AWidth, AHeight : Integer) : Integer;
1316 begin
1317 Canvas.Rectangle(XPos, YPos, XPos+AWidth, YPos+AHeight);
1318 Result := XPos + AWidth;
1319 end;
1320
1321 procedure TStBarCode.DrawBarCode(const R : TRect);
1322 var
1323 I, X, Y : Integer;
1324 CheckC : Integer;
1325 CheckK : Integer;
1326 TH, GA, TQ, BB : Integer;
1327 BarCodeHeight : Integer;
1328 BarCodeWidth : Integer;
1329 PixelsPerInchX : Integer;
1330 TR : TRect;
1331 SmallestWidth : Double;
1332 C : string;
1333 Buf : array[0..512] of Char;
1334 begin
1335 Canvas.Brush.Color := FBarColor;
1336 Canvas.Brush.Style := bsSolid;
1337
1338 PixelsPerInchX := GetDeviceCaps(Canvas.Handle, LOGPIXELSX);
1339
1340 {determine narrowest line width}
1341 SmallestWidth := SmallestLineWidth(PixelsPerInchX);
1342
1343 {find sizes for the BarCode elements}
1344 bcBarModWidth := Round(FBarWidth/1000 * PixelsPerInchX);
1345 if bcBarModWidth < FBarToSpaceRatio then
1346 bcBarModWidth := Round(BarToSpaceRatio);
1347 if bcBarModWidth < SmallestWidth then
1348 bcBarModWidth := Round(SmallestWidth);
1349 bcSpaceModWidth := Round(bcBarModWidth / FBarToSpaceRatio);
1350
1351 {total width of BarCode and position within rect}
1352 CalcBarCodeWidth;
1353 BarCodeWidth := bcNormalWidth + bcSpaceWidth + bcSupplementWidth;
1354 BarCodeHeight := RectHeight(R);
1355 if BarCodeWidth < RectWidth(R) then
1356 X := R.Left + (RectWidth(R)-BarCodeWidth) div 2
1357 else
1358 X := R.Left;
1359 Y := R.Top;
1360
1361 {get text height}
1362 TH := Canvas.TextHeight('Yg0');
1363
1364 {guard bar adjustment}
1365 GA := (BarCodeHeight*10) div 100; {10% of bar height}
1366 {but, not more than 1/4 of the font height}
1367 if FShowCode and (GA > TH div 4) then
1368 GA := TH div 4;
1369
1370 {three quarter height bar adjustment}
1371 TQ := BarCodeHeight div 4;
1372
1373 {draw the text}
1374 if FShowCode and (Code > '') then begin
1375 C := Code;
1376 {fill out invalid codes}
1377 case FBarCodeType of
1378 bcUPC_A :
1379 begin
1380 C := Copy(C, 1, 12); {truncate}
1381 if Length(C) = 11 then begin
1382 GetCheckCharacters(C, CheckC, CheckK);
1383 C := C + IntToStr(CheckC);
1384 end;
1385 while Length(C) < 12 do
1386 C := C + '0';
1387 end;
1388 bcUPC_E :
1389 begin
1390 C := Copy(C, 1, 6); {truncate}
1391 while Length(C) < 6 do
1392 C := C + '0';
1393 end;
1394 bcEAN_8 :
1395 begin
1396 C := Copy(C, 1, 8); {truncate}
1397 if Length(C) = 7 then begin
1398 GetCheckCharacters(C, CheckC, CheckK);
1399 C := C + IntToStr(CheckC);
1400 end;
1401 while Length(C) < 8 do
1402 C := C + '0';
1403 end;
1404 bcEAN_13 :
1405 begin
1406 C := Copy(C, 1, 13); {truncate}
1407 if Length(C) = 12 then begin
1408 GetCheckCharacters(C, CheckC, CheckK);
1409 C := C + IntToStr(CheckC);
1410 end;
1411 while Length(C) < 13 do
1412 C := C + '0';
1413 end;
1414 bcInterleaved2of5 :
1415 begin
1416 if Odd(Length(C)) then
1417 C := '0' + C;
1418 end;
1419 bcCodabar :
1420 begin
1421 if not FShowGuardChars then
1422 {strip leading and trailing characters}
1423 C := Copy(C, 2, Length(C)-2);
1424 end;
1425 bcCode11 :
1426 begin
1427 end;
1428 bcCode39 :
1429 begin
1430 {add guard characters}
1431 if C[1] <> '*' then
1432 C := '*' + C;
1433 if C[Length(C)] <> '*' then
1434 C := C + '*';
1435 if not FShowGuardChars then
1436 {strip leading and trailing characters}
1437 C := Copy(C, 2, Length(C)-2);
1438 end;
1439 bcCode93 :
1440 begin
1441 {remove non-printable characters}
1442 for I := 1 to Length(C) do
1443 if C[I] < ' ' then
1444 C[I] := ' ';
1445 end;
1446 bcCode128 :
1447 begin
1448 {remove non-printable characters}
1449 I := 1;
1450 while I <= Length (C) do begin
1451 if C[I] < ' ' then
1452 C[I] := ' ';
1453 if (i < Length (C)) and (ExtendedSyntax) then begin
1454 if (C[I] = '\') and
1455 (C[I + 1] in ['A', 'B', 'C', 'a', 'b', 'c']) then begin
1456 C[I] := ' ';
1457 C[I + 1] := ' ';
1458 Inc (I);
1459 end else if (C[I] = '\') and (C[I+1] = '\') then begin
1460 C[I] := ' ';
1461 Inc (I);
1462 end;
1463 end;
1464 Inc (I);
1465 end;
1466 end;
1467 end;
1468
1469 Dec(BarCodeHeight, TH + (TH div 4));
1470 Canvas.Brush.Style := bsClear;
1471 {guard bar adjustment - again}
1472 GA := (BarCodeHeight*10) div 100; {10% of bar height}
1473 {but, not more than 1/4 of the font height}
1474 if FShowCode and (GA > TH div 4) then
1475 GA := TH div 4;
1476 {three quarter height bar adjustment}
1477 TQ := BarCodeHeight div 4;
1478
1479 if FBarCodeType = bcUPC_A then begin
1480 {print first and last character to sides of symbol}
1481 TR.Top := Y;
1482 TR.Bottom := TR.Top + BarCodeHeight;
1483 {left hand character}
1484 Buf[0] := C[1];
1485 TR.Right := X;
1486 TR.Left := X - 2 * Canvas.TextWidth(C[1]);
1487 DrawText(Canvas.Handle, @Buf, 1, TR, DT_BOTTOM or DT_CENTER or DT_SINGLELINE);
1488 {remove character from code to print}
1489 C := Copy(C, 2, Length(C)-1);
1490
1491 {right hand character - if no supplemental code}
1492 if FSupplementalCode = '' then begin
1493 Buf[0] := C[Length(C)];
1494 TR.Left := X + bcNormalWidth;
1495 TR.Right := X + bcNormalWidth + 2 * Canvas.TextWidth(C[Length(C)]);
1496 DrawText(Canvas.Handle, @Buf, 1, TR, DT_BOTTOM or DT_CENTER or DT_SINGLELINE);
1497 {remove character from code to print}
1498 C := Copy(C, 1, Length(C)-1);
1499 end;
1500 end;
1501
1502 if FSupplementalCode > '' then begin
1503 {draw supplemental code above the code}
1504 TR.Top := Y + TQ - TH;
1505 TR.Bottom := Y + BarCodeHeight;
1506 TR.Left := X + bcNormalWidth + bcSpaceWidth;
1507 TR.Right := TR.Left + bcSupplementWidth;
1508 StrPLCopy(Buf, FSupplementalCode, Length(Buf)-1);
1509 DrawText(Canvas.Handle, @Buf, StrLen(Buf), TR, DT_VCENTER or DT_CENTER);
1510 end;
1511
1512 TR := R;
1513 TR.Top := R.Top + BarCodeHeight + (TH div 4);
1514 TR.Left := X;
1515 TR.Right := TR.Left + bcNormalWidth;
1516 Canvas.Brush.Style := bsClear;
1517 StrPLCopy(Buf, C, Length(Buf)-1);
1518 DrawText(Canvas.Handle, @Buf, StrLen(Buf), TR, DT_VCENTER or DT_CENTER);
1519 Canvas.Brush.Style := bsSolid;
1520 Canvas.Brush.Color := FBarColor;
1521 end;
1522
1523 if (FBarCodeType = bcInterleaved2of5) and FBearerBars then begin
1524 BB := 3 * bcBarModWidth;
1525 {reduce height to allow for bearer bars}
1526 Dec(BarCodeHeight, BB * 2);
1527 {draw the bearer bars}
1528 Canvas.Rectangle(X-bcBarModWidth, Y,
1529 X+BarCodeWidth+bcBarModWidth, Y+BB);
1530 Canvas.Rectangle(X-bcBarModWidth, Y+BarCodeHeight+BB,
1531 X+BarCodeWidth+bcBarModWidth, Y+BarCodeHeight+BB*2);
1532 {adjust top of BarCode}
1533 Inc(Y, BB);
1534 end;
1535
1536 {draw the bar code}
1537 for I := 0 to bcBarInfo.Count-1 do begin
1538 if bkSpace in bcBarInfo[I].Kind then
1539 Inc(X, bcSpaceModWidth*bcBarInfo[I].Modules)
1540 else if (bkGuard in bcBarInfo[I].Kind) and FTallGuardBars then begin
1541 if bcGuardBarAbove and bcGuardBarBelow then
1542 X := DrawBar(X, Y-GA, bcBarModWidth*bcBarInfo[I].Modules, BarCodeHeight+2*GA)
1543 else if bcGuardBarAbove then
1544 X := DrawBar(X, Y-GA, bcBarModWidth*bcBarInfo[I].Modules, BarCodeHeight+GA)
1545 else if bcGuardBarBelow then
1546 X := DrawBar(X, Y, bcBarModWidth*bcBarInfo[I].Modules, BarCodeHeight+2*GA)
1547 end else if (bkBar in bcBarInfo[I].Kind) or (bkGuard in bcBarInfo[I].Kind) then
1548 X := DrawBar(X, Y, bcBarModWidth*bcBarInfo[I].Modules, BarCodeHeight)
1549 else if (bkThreeQuarterBar in bcBarInfo[I].Kind) then
1550 X := DrawBar(X, Y+TQ, bcBarModWidth*bcBarInfo[I].Modules, BarCodeHeight-TQ);
1551 end;
1552 end;
1553
1554 {added}
1555 function TStBarCode.GetBarCodeWidth(ACanvas : TCanvas) : Double;
1556 var
1557 PixelsPerInchX : Integer;
1558 SmallestWidth : Double;
1559 begin
1560 PixelsPerInchX := GetDeviceCaps(ACanvas.Handle, LOGPIXELSX);
1561
1562 {determine narrowest line width}
1563 SmallestWidth := SmallestLineWidth(PixelsPerInchX);
1564
1565 {find sizes for the BarCode elements}
1566 bcBarModWidth := Round(FBarWidth/1000 * PixelsPerInchX);
1567 if bcBarModWidth < FBarToSpaceRatio then
1568 bcBarModWidth := Round(BarToSpaceRatio);
1569 if bcBarModWidth < SmallestWidth then
1570 bcBarModWidth := Round(SmallestWidth);
1571 bcSpaceModWidth := Round(bcBarModWidth / FBarToSpaceRatio);
1572
1573 CalcBarcodeWidth;
1574
1575 {width in pixels (not counting text printed to left or right of code)}
1576 Result := bcNormalWidth + bcSpaceWidth + bcSupplementWidth;
1577 {return width of barcode in inches}
1578 Result := Result / PixelsPerInchX;
1579 end;
1580
1581 procedure TStBarCode.GetCheckCharacters(const S : string; var C, K : Integer);
1582 var
1583 I : Integer;
1584 C1 : Integer;
1585 C2 : Integer;
1586 St : string;
1587 begin
1588 C := -1;
1589 K := -1;
1590 St := S;
1591 case FBarCodeType of
1592 bcUPC_A :
1593 begin
1594 if Length(St) >= 11 then begin
1595 {get digits}
1596 GetDigits(St);
1597 {determine check character}
1598 C1 := (bcDigits[1] + bcDigits[3] + bcDigits[5] + bcDigits[7] +
1599 bcDigits[9] + bcDigits[11]) * 3;
1600 C2 := bcDigits[2] + bcDigits[4] + bcDigits[6] +
1601 bcDigits[8] + bcDigits[10];
1602 C := 10 - ((C1 + C2) mod 10);
1603 if C = 10 then
1604 C := 0;
1605 end;
1606 end;
1607 bcUPC_E :
1608 begin
1609 {get digits}
1610 GetDigits(St);
1611 {determine check character}
1612 C1 := (bcDigits[2] + bcDigits[4] + bcDigits[6]) * 3;
1613 C2 := bcDigits[1] + bcDigits[3] + bcDigits[5];
1614 C := 10 - ((C1 + C2) mod 10);
1615 if C = 10 then
1616 C := 0;
1617 end;
1618 bcEAN_8 :
1619 begin
1620 if Length(St) >= 7 then begin
1621 {get digits}
1622 GetDigits(St);
1623 {determine check character}
1624 C1 := (bcDigits[1] + bcDigits[3] + bcDigits[5] + bcDigits[7]) * 3;
1625 C2 := bcDigits[2] + bcDigits[4] + bcDigits[6];
1626 C := 10 - ((C1 + C2) mod 10);
1627 if C = 10 then
1628 C := 0;
1629 end;
1630 end;
1631 bcEAN_13 :
1632 begin
1633 if Length(St) >= 12 then begin
1634 {get digits}
1635 GetDigits(St);
1636 {determine check character}
1637 C1 := (bcDigits[2] + bcDigits[4] + bcDigits[6] + bcDigits[8] +
1638 bcDigits[10] + bcDigits[12]) * 3;
1639 C2 := bcDigits[1] + bcDigits[3] + bcDigits[5] + bcDigits[7] +
1640 bcDigits[9] + bcDigits[11];
1641 C := 10 - ((C1 + C2) mod 10);
1642 if C = 10 then
1643 C := 0;
1644 end;
1645 end;
1646 bcInterleaved2of5 :
1647 begin
1648 {get digits}
1649 bcDigitCount := GetDigits(St);
1650
1651 C1 := 0;
1652 C2 := 0;
1653 for I := 1 to bcDigitCount do
1654 if Odd(I) then
1655 C1 := C1 + bcDigits[I] {odd digits}
1656 else
1657 C2 := C2 + bcDigits[I]; {even digits}
1658 C2 := C2 * 3;
1659
1660 C := 10 - ((C1 + C2) mod 10);
1661 if C = 10 then
1662 C := 0;
1663 end;
1664 bcCodabar :
1665 begin
1666 {get digits}
1667 bcDigitCount := GetDigits(St);
1668
1669 C1 := 0;
1670 for I := 1 to bcDigitCount do
1671 C1 := C1 + bcDigits[I];
1672
1673 C := 16 - (C1 mod 16);
1674 if C = 16 then
1675 C := 0;
1676 end;
1677 bcCode11 :
1678 begin
1679 {get digits}
1680 bcDigitCount := GetDigits(St);
1681 C1 := 0;
1682 for I := bcDigitCount downto 1 do
1683 C1 := C1 + bcDigits[I]*(bcDigitCount-I+1);
1684 C1 := C1 mod 11; {the "C" check character}
1685 C2 := C1;
1686 for I := bcDigitCount downto 1 do
1687 C2 := C2 + bcDigits[I]*(bcDigitCount-I+2);
1688 C2 := C2 mod 11; {the "K" check character}
1689 K := C2;
1690 C := C1;
1691 end;
1692 bcCode39 :
1693 begin
1694 {get digits}
1695 bcDigitCount := GetDigits(St);
1696
1697 C1 := 0;
1698 for I := 1 to bcDigitCount do
1699 C1 := C1 + bcDigits[I];
1700
1701 C := 43 - (C1 mod 43);
1702 if C = 43 then
1703 C := 0;
1704 end;
1705 bcCode93 :
1706 begin
1707 {get digits}
1708 bcDigitCount := GetDigits(St);
1709 C1 := 0;
1710 for I := bcDigitCount downto 1 do
1711 C1 := C1 + bcDigits[I]*(bcDigitCount-I+1);
1712 C1 := C1 mod 47; {the "C" check character}
1713 C2 := C1;
1714 for I := bcDigitCount downto 1 do
1715 C2 := C2 + bcDigits[I]*(bcDigitCount-I+2);
1716 C2 := C2 mod 47; {the "K" check character}
1717 K := C2;
1718 C := C1;
1719 end;
1720 bcCode128 :
1721 begin
1722 {get digits}
1723 bcDigitCount := GetDigits(St);
1724
1725 C1 := bcDigits[1];
1726 for I := 2 to bcDigitCount do
1727 C1 := C1 + bcDigits[I]*(I-1);
1728
1729 C := C1 mod 103;
1730 if C = 103 then
1731 C := 0;
1732 end;
1733 end;
1734 end;
1735
1736 function TStBarCode.GetCode : string;
1737 begin
1738 Result := Text;
1739 end;
1740
1741 function TStBarCode.GetDigits(Characters : string) : Integer;
1742
1743 procedure GetACode128CDigit (c : Char; var Index : Integer;
1744 var bcDigitPos : Integer);
1745 var
1746 J : Integer;
1747
1748 begin
1749 case (c) of
1750 #130 : bcDigits[bcDigitPos + 1] := 98; {rest are manufactured characters}
1751 #131 : bcDigits[bcDigitPos + 1] := 97;
1752 #132 : bcDigits[bcDigitPos + 1] := 96;
1753 #133 : bcDigits[bcDigitPos + 1] := 98;
1754 #134 : bcDigits[bcDigitPos + 1] := 100;
1755 #135 : bcDigits[bcDigitPos + 1] := 99;
1756 #136 : bcDigits[bcDigitPos + 1] := 103;
1757 #137 : bcDigits[bcDigitPos + 1] := 104;
1758 #138 : bcDigits[bcDigitPos + 1] := 105;
1759 #139 : bcDigits[bcDigitPos + 1] := 106;
1760 else
1761 try
1762 J := StrToInt (Copy (Characters, Index, 2));
1763 bcDigits[bcDigitPos + 1] := J;
1764 Inc (Index);
1765 except
1766 RaiseStError(EStBarCodeError, stscInvalidCharacter);
1767 end;
1768 end;
1769 Inc (Index);
1770 Inc (bcDigitPos);
1771 end;
1772
1773 procedure GetACode128ABDigit (c : Char; var Index : Integer;
1774 var bcDigitPos : Integer);
1775 begin
1776 case c of
1777 ' ' : bcDigits[bcDigitPos + 1] := 0;
1778 '!' : bcDigits[bcDigitPos + 1] := 1;
1779 '"' : bcDigits[bcDigitPos + 1] := 2;
1780 '#' : bcDigits[bcDigitPos + 1] := 3;
1781 '$' : bcDigits[bcDigitPos + 1] := 4;
1782 '%' : bcDigits[bcDigitPos + 1] := 5;
1783 '&' : bcDigits[bcDigitPos + 1] := 6;
1784 '''' : bcDigits[bcDigitPos + 1] := 7;
1785 '(' : bcDigits[bcDigitPos + 1] := 8;
1786 ')' : bcDigits[bcDigitPos + 1] := 9;
1787 '*' : bcDigits[bcDigitPos + 1] := 10;
1788 '+' : bcDigits[bcDigitPos + 1] := 11;
1789 ',' : bcDigits[bcDigitPos + 1] := 12;
1790 '-' : bcDigits[bcDigitPos + 1] := 13;
1791 '.' : bcDigits[bcDigitPos + 1] := 14;
1792 '/' : bcDigits[bcDigitPos + 1] := 15;
1793 '0'..'9' : bcDigits[bcDigitPos + 1] := 16 + Ord(c)-Ord('0');
1794 ':' : bcDigits[bcDigitPos + 1] := 26;
1795 ';' : bcDigits[bcDigitPos + 1] := 27;
1796 '<' : bcDigits[bcDigitPos + 1] := 28;
1797 '=' : bcDigits[bcDigitPos + 1] := 29;
1798 '>' : bcDigits[bcDigitPos + 1] := 30;
1799 '?' : bcDigits[bcDigitPos + 1] := 31;
1800 '@' : bcDigits[bcDigitPos + 1] := 32;
1801 'A'..'Z' : bcDigits[bcDigitPos + 1] := 33 + Ord(c)-Ord('A');
1802 '[' : bcDigits[bcDigitPos + 1] := 59;
1803 '\' : bcDigits[bcDigitPos + 1] := 60;
1804 ']' : bcDigits[bcDigitPos + 1] := 61;
1805 '^' : bcDigits[bcDigitPos + 1] := 62;
1806 '_' : bcDigits[bcDigitPos + 1] := 63;
1807 #0, #31 : bcDigits[bcDigitPos + 1] := 64 + Ord(c); {control characters}
1808 '`' : bcDigits[bcDigitPos + 1] := 64;
1809 'a'..'z' : bcDigits[bcDigitPos + 1] := 65 + Ord(c)-Ord('a');
1810 '{' : bcDigits[bcDigitPos + 1] := 91;
1811 '|' : bcDigits[bcDigitPos + 1] := 92;
1812 '}' : bcDigits[bcDigitPos + 1] := 93;
1813 '~' : bcDigits[bcDigitPos + 1] := 94;
1814 #130 : bcDigits[bcDigitPos + 1] := 98; {rest are manufactured characters}
1815 #131 : bcDigits[bcDigitPos + 1] := 97;
1816 #132 : bcDigits[bcDigitPos + 1] := 96;
1817 #133 : bcDigits[bcDigitPos + 1] := 98;
1818 #134 : bcDigits[bcDigitPos + 1] := 100;
1819 #135 : bcDigits[bcDigitPos + 1] := 99;
1820 #136 : bcDigits[bcDigitPos + 1] := 103;
1821 #137 : bcDigits[bcDigitPos + 1] := 104;
1822 #138 : bcDigits[bcDigitPos + 1] := 105;
1823 #139 : bcDigits[bcDigitPos + 1] := 106;
1824 else
1825 RaiseStError(EStBarCodeError, stscInvalidCharacter);
1826 end;
1827 Inc (Index);
1828 Inc (bcDigitPos);
1829 end;
1830
1831 function CountCode128Digits (Index : Integer) : Integer;
1832 begin
1833 Result := 0;
1834 while (Index <= Length (Characters)) and
1835 (Characters[Index] >= '0') and (Characters[Index] <= '9') do begin
1836 Inc (Result);
1837 Inc (Index);
1838 end;
1839 end;
1840
1841 function CheckCode128Digits (Index : Integer; CharsLen : Integer) : Boolean;
1842 var
1843 NumDigits : Integer;
1844 begin
1845 Result := False;
1846 NumDigits := CountCode128Digits (Index);
1847 if NumDigits mod 2 <> 0 then begin
1848 Characters := Copy (Characters, 1, Index - 1) +
1849 '0' + Copy (Characters, Index, CharsLen - Index + 1);
1850 Result := True;
1851 end;
1852 end;
1853
1854 function GetCode128Digits : Integer;
1855 var
1856 I : Integer;
1857 RLen : Integer;
1858 CurMode : TStCode128CodeSubset;
1859 NeedCharCount : Boolean;
1860 Skip : Boolean;
1861
1862 begin
1863 I := 1;
1864 Result := Length (Characters);
1865 RLen := 0;
1866 CurMode := Self.Code128Subset;
1867 NeedCharCount := Self.Code128Subset = csCodeC;
1868
1869 while I <= Result do begin
1870 if (NeedCharCount) and
1871 (Characters[I] >= '0') and (Characters[I] <= '9') then begin
1872 NeedCharCount := False;
1873 if CheckCode128Digits (I, Result) then
1874 Inc (Result);
1875 end;
1876
1877 Skip := False;
1878 if (ExtendedSyntax) and (Characters[I] = '\') and
1879 (I < Result) then begin
1880 if ((Characters[I + 1] = 'A') or (Characters[I + 1] = 'a')) and
1881 (CurMode <> csCodeA) then begin
1882 Inc (RLen);
1883 bcDigits[RLen] := 101;
1884 CurMode := csCodeA;
1885 Skip := True;
1886 end else if ((Characters[I + 1] = 'B') or (Characters[I + 1] = 'b')) and
1887 (CurMode <> csCodeB) then begin
1888 Inc (RLen);
1889 bcDigits[RLen] := 100;
1890 CurMode :=csCodeB;
1891 Skip := True;
1892 end else if ((Characters[I + 1] = 'C') or (Characters[I + 1] = 'c')) and
1893 (CurMode <> csCodeC) then begin
1894 NeedCharCount := True;
1895 Inc (RLen);
1896 bcDigits[RLen] := 99;
1897 CurMode := csCodeC;
1898 Skip := True;
1899 end else if (Characters[I + 1] = '\') then begin
1900 GetACode128ABDigit ('\', I, RLen);
1901 Skip := True;
1902 end;
1903 Inc (I);
1904 end;
1905
1906 if not Skip then
1907 case CurMode of
1908 csCodeC :
1909 GetACode128CDigit (Characters[I], I, RLen);
1910 else
1911 GetACode128ABDigit (Characters[I], I, RLen);
1912 end
1913 else
1914 Inc (I);
1915 end;
1916 Result := RLen;
1917 end;
1918
1919 var
1920 I, J : Integer;
1921 S : string;
1922 begin
1923 FillChar(bcDigits, SizeOf(bcDigits), #0);
1924 Result := 0;
1925
1926 case FBarCodeType of
1927 bcUPC_A, bcUPC_E, bcEAN_8, bcEAN_13, bcInterleaved2of5 :
1928 begin
1929 Result := Length(Characters);
1930 for I := 1 to Result do
1931 bcDigits[I] := StrToInt(Characters[I]);
1932 end;
1933 bcCodabar :
1934 begin
1935 Result := Length(Characters);
1936 for I := 1 to Result do begin
1937 case Characters[I] of
1938 '0'..'9' : bcDigits[I] := StrToInt(Characters[I]);
1939 '-' : bcDigits[I] := 10;
1940 '$' : bcDigits[I] := 11;
1941 ':' : bcDigits[I] := 12;
1942 '/' : bcDigits[I] := 13;
1943 '.' : bcDigits[I] := 14;
1944 '+' : bcDigits[I] := 15;
1945 'A', 'a' : bcDigits[I] := 16;
1946 'B', 'b' : bcDigits[I] := 17;
1947 'C', 'c' : bcDigits[I] := 18;
1948 'D', 'd' : bcDigits[I] := 19;
1949 else
1950 RaiseStError(EStBarCodeError, stscInvalidCharacter);
1951 end;
1952 end;
1953 end;
1954 bcCode11 :
1955 begin
1956 Result := Length(Characters);
1957 for I := 1 to Result do begin
1958 case Characters[I] of
1959 '0'..'9' : bcDigits[I] := StrToInt(Characters[I]);
1960 '-' : bcDigits[I] := 10;
1961 else
1962 RaiseStError(EStBarCodeError, stscInvalidCharacter);
1963 end;
1964 end;
1965 end;
1966 bcCode39 :
1967 begin
1968 Result := Length(Characters);
1969 for I := 1 to Result do begin
1970 case Characters[I] of
1971 '0'..'9' : bcDigits[I] := StrToInt(Characters[I]);
1972 'A'..'Z' : bcDigits[I] := Ord(Characters[I]) - Ord('A') + 10;
1973 '-' : bcDigits[I] := 36;
1974 '.' : bcDigits[I] := 37;
1975 ' ' : bcDigits[I] := 38;
1976 '$' : bcDigits[I] := 39;
1977 '/' : bcDigits[I] := 40;
1978 '+' : bcDigits[I] := 41;
1979 '%' : bcDigits[I] := 42;
1980 '*' : bcDigits[I] := 43;
1981 else
1982 RaiseStError(EStBarCodeError, stscInvalidCharacter);
1983 end;
1984 end;
1985 end;
1986 bcCode93 :
1987 begin
1988 Result := Length(Characters);
1989 J := 1;
1990 I := 1;
1991 while I <= Result do begin
1992 S := Code93Map[Characters[I]];
1993 if Length(S) > 1 then begin
1994 case S[1] of
1995 '$' : bcDigits[J] := 43; {(+)}
1996 '%' : bcDigits[J] := 44; {(%)}
1997 '/' : bcDigits[J] := 45; {(/)}
1998 '+' : bcDigits[J] := 46; {(+)}
1999 else
2000 RaiseStError(EStBarCodeError, stscInvalidCharacter);
2001 end;
2002 Inc(J);
2003 S := S[2];
2004 end;
2005
2006 case S[1] of
2007 '0'..'9' : bcDigits[J] := Ord(S[1])-Ord('0');
2008 'A'..'Z' : bcDigits[J] := 10 + Ord(S[1])-Ord('A');
2009 '-' : bcDigits[J] := 36;
2010 '.' : bcDigits[J] := 37;
2011 ' ' : bcDigits[J] := 38;
2012 '$' : bcDigits[J] := 39;
2013 '/' : bcDigits[J] := 40;
2014 '+' : bcDigits[J] := 41;
2015 '%' : bcDigits[J] := 42;
2016 else
2017 RaiseStError(EStBarCodeError, stscInvalidCharacter);
2018 end;
2019 Inc(I);
2020 Inc(J);
2021 end;
2022 Result := J;
2023 end;
2024 bcCode128 :
2025 Result := GetCode128Digits;
2026 end;
2027 end;
2028
2029 function TStBarCode.GetVersion : string;
2030 begin
2031 Result := StVersionStr;
2032 end;
2033
2034 procedure TStBarCode.Loaded;
2035 begin
2036 inherited Loaded;
2037
2038 CalcBarCode;
2039 end;
2040
2041 procedure TStBarCode.Paint;
2042 var
2043 Margin : Integer;
2044 R : TRect;
2045 begin
2046 {use our font}
2047 Canvas.Font := Font;
2048
2049 {clear the canvas}
2050 Canvas.Brush.Color := Color;
2051 Canvas.Brush.Style := bsSolid;
2052 Canvas.FillRect(ClientRect);
2053
2054 {adjust height of rect to provide top and bottom margin}
2055 R := ClientRect;
2056 Margin := RectHeight(R)*10 div 100;
2057 InflateRect(R, 0, -Margin);
2058 PaintPrim(R);
2059 end;
2060
2061 procedure TStBarCode.PaintPrim(const R : TRect);
2062 begin
2063 Canvas.Brush.Style := bsClear;
2064 Canvas.Brush.Color := FBarColor;
2065 Canvas.Pen.Color := FBarColor;
2066 DrawBarCode(R);
2067 end;
2068
2069 procedure TStBarCode.PaintToCanvas(ACanvas : TCanvas; ARect : TRect);
2070 var
2071 Margin : Integer;
2072 SavedDC : LongInt;
2073 R : TRect;
2074 begin
2075 Canvas.Handle := ACanvas.Handle;
2076 SavedDC := SaveDC(ACanvas.Handle);
2077 try
2078 {use our font}
2079 Canvas.Font := Font;
2080
2081 {clear the specified area of the canvas}
2082 Canvas.Brush.Color := Color;
2083 Canvas.Brush.Style := bsSolid;
2084 Canvas.FillRect(ARect);
2085
2086 {adjust height of rect to provide top and bottom margin}
2087 R := ARect;
2088 Margin := RectHeight(R)*10 div 100;
2089 InflateRect(R, 0, -Margin);
2090 PaintPrim(R);
2091 finally
2092 Canvas.Handle := 0;
2093 RestoreDC(ACanvas.Handle, SavedDC);
2094 end;
2095 end;
2096
2097 procedure TStBarCode.PaintToCanvasSize(ACanvas : TCanvas; X, Y, H : Double);
2098 var
2099 TH : Integer;
2100 PixelsPerInchX : Integer;
2101 PixelsPerInchY : Integer;
2102 OldPPI : Integer;
2103 SavedDC : LongInt;
2104 R : TRect;
2105 SmallestWidth : Double;
2106 begin
2107 Canvas.Handle := ACanvas.Handle;
2108 SavedDC := SaveDC(ACanvas.Handle);
2109 try
2110 {get some information about this device context}
2111 PixelsPerInchX := GetDeviceCaps(Canvas.Handle, LOGPIXELSX);
2112 PixelsPerInchY := GetDeviceCaps(Canvas.Handle, LOGPIXELSY);
2113
2114 OldPPI := Canvas.Font.PixelsPerInch;
2115 {this is necessary because of a Delphi buglet}
2116 Canvas.Font.PixelsPerInch := PixelsPerInchY;
2117
2118 {use our font}
2119 Canvas.Font := Font;
2120
2121 {determine narrowest line width}
2122 SmallestWidth := SmallestLineWidth(PixelsPerInchX);
2123
2124 {find sizes for the BarCode elements}
2125 bcBarModWidth := Round(FBarWidth/1000 * PixelsPerInchX);
2126 if bcBarModWidth < FBarToSpaceRatio then
2127 bcBarModWidth := Round(FBarToSpaceRatio);
2128 if bcBarModWidth < SmallestWidth then
2129 bcBarModWidth := Round(SmallestWidth);
2130 bcSpaceModWidth := Round(bcBarModWidth / FBarToSpaceRatio);
2131 CalcBarCodeWidth;
2132
2133 {convert to a rect}
2134 R := Rect(Round(X * PixelsPerInchX),
2135 Round(Y * PixelsPerInchY),
2136 Round(X * PixelsPerInchX) + bcNormalWidth + bcSpaceWidth + bcSupplementWidth,
2137 Round((Y + H) * PixelsPerInchY));
2138
2139 {increase height of rect to allow for text}
2140 if FShowCode and (Code > '') then begin
2141 TH :=Canvas.TextHeight(Code);
2142 Inc(R.Bottom, TH + (TH div 4));
2143 end;
2144
2145 PaintPrim(R);
2146 Canvas.Font.PixelsPerInch := OldPPI;
2147 Invalidate;
2148 finally
2149 Canvas.Handle := 0;
2150 RestoreDC(ACanvas.Handle, SavedDC);
2151 end;
2152 end;
2153
2154 procedure TStBarCode.PaintToDC(DC : hDC; ARect : TRect);
2155 var
2156 Margin : Integer;
2157 SavedDC : LongInt;
2158 R : TRect;
2159 begin
2160 Canvas.Handle := DC;
2161 SavedDC := SaveDC(DC);
2162 try
2163 {use our font}
2164 Canvas.Font := Font;
2165
2166 {clear the specified area of the canvas}
2167 Canvas.Brush.Color := Color;
2168 Canvas.Brush.Style := bsSolid;
2169 Canvas.FillRect(ARect);
2170
2171 {adjust height of rect to provide top and bottom margin}
2172 R := ARect;
2173 Margin := RectHeight(R)*10 div 100;
2174 InflateRect(R, 0, -Margin);
2175 PaintPrim(R);
2176 finally
2177 Canvas.Handle := 0;
2178 RestoreDC(DC, SavedDC);
2179 end;
2180 end;
2181
2182 procedure TStBarCode.PaintToDCSize(DC : hDC; X, Y, W, H : Double);
2183 begin
2184 Canvas.Handle := DC;
2185 PaintToCanvasSize(Canvas, X, Y, H);
2186 end;
2187
2188 procedure TStBarCode.SaveToFile(const FileName : string);
2189 var
2190 Bitmap : TBitmap;
2191 begin
2192 Bitmap := TBitmap.Create;
2193 try
2194 Bitmap.Width := ClientWidth;
2195 Bitmap.Height := ClientHeight;
2196 PaintToDC(Bitmap.Canvas.Handle, ClientRect);
2197 Bitmap.SaveToFile(FileName);
2198 finally
2199 Bitmap.Free;
2200 end
2201 end;
2202
2203 procedure TStBarCode.SetAddCheckChar(Value : Boolean);
2204 begin
2205 if Value <> FAddCheckChar then begin
2206 FAddCheckChar := Value;
2207 CalcBarCode;
2208 Invalidate;
2209 end;
2210 end;
2211
2212 procedure TStBarCode.SetBarCodeType(Value : TStBarCodeType);
2213 begin
2214 if Value <> FBarCodeType then begin
2215 FBarCodeType := Value;
2216 CalcBarCode;
2217 Invalidate;
2218 end;
2219 end;
2220
2221 procedure TStBarCode.SetBarColor(Value : TColor);
2222 begin
2223 if Value <> FBarColor then begin
2224 FBarColor := Value;
2225 Invalidate;
2226 end;
2227 end;
2228
2229 procedure TStBarCode.SetBarToSpaceRatio(Value : Double);
2230 begin
2231 {always uses a bar to space ratio of 1}
2232 if FBarCodeType in [bcInterleaved2of5, bcCode11, bcCode39, bcCode93, bcCode128] then
2233 Value := 1;
2234
2235 if Value <> FBarToSpaceRatio then begin
2236 FBarToSpaceRatio := Value;
2237 CalcBarCode;
2238 Invalidate;
2239 end;
2240 end;
2241
2242 procedure TStBarCode.SetBarNarrowToWideRatio(Value : Integer);
2243 begin
2244 if Value <> FBarNarrowToWideRatio then begin
2245 FBarNarrowToWideRatio := Value;
2246 CalcBarCode;
2247 Invalidate;
2248 end;
2249 end;
2250
2251 procedure TStBarCode.SetBarWidth(Value : Double);
2252 begin
2253 if Value <> FBarWidth then begin
2254 FBarWidth := Value;
2255 Invalidate;
2256 end;
2257 end;
2258
2259 procedure TStBarCode.SetBearerBars(Value : Boolean);
2260 begin
2261 if Value <> FBearerBars then begin
2262 FBearerBars := Value;
2263 Invalidate;
2264 end;
2265 end;
2266
2267 procedure TStBarCode.SetCode(const Value : string);
2268 begin
2269 if FBarCodeType in [bcCode39] then
2270 Text := UpperCase(Value)
2271 else if FBarCodeType in [bcCodabar] then
2272 Text := LowerCase(Value)
2273 else
2274 Text := Value;
2275 end;
2276
2277 procedure TStBarCode.SetCode128Subset(Value : TStCode128CodeSubset);
2278 begin
2279 if Value <> FCode128Subset then begin
2280 FCode128Subset := Value;
2281 CalcBarCode;
2282 Invalidate;
2283 end;
2284 end;
2285
2286 procedure TStBarCode.SetExtendedSyntax (const v : Boolean);
2287 begin
2288 if v <> FExtendedSyntax then begin
2289 FExtendedSyntax := v;
2290 CalcBarCode;
2291 Invalidate;
2292 end;
2293 end;
2294
2295 procedure TStBarCode.SetShowCode(Value : Boolean);
2296 begin
2297 if Value <> FShowCode then begin
2298 FShowCode := Value;
2299 Invalidate;
2300 end;
2301 end;
2302
2303 procedure TStBarCode.SetShowGuardChars(Value : Boolean);
2304 begin
2305 if Value <> FShowGuardChars then begin
2306 FShowGuardChars := Value;
2307 Invalidate;
2308 end;
2309 end;
2310
2311 procedure TStBarCode.SetSupplementalCode(const Value : string);
2312 begin
2313 if Value <> FSupplementalCode then begin
2314 FSupplementalCode := Value;
2315 CalcBarCode;
2316 Invalidate;
2317 end;
2318 end;
2319
2320 procedure TStBarCode.SetTallGuardBars(Value : Boolean);
2321 begin
2322 if Value <> FTallGuardBars then begin
2323 FTallGuardBars := Value;
2324 Invalidate;
2325 end;
2326 end;
2327
2328 procedure TStBarCode.SetVersion(const Value : string);
2329 begin
2330 end;
2331
2332 function TStBarCode.SmallestLineWidth(PixelsPerInch : Integer) : Double;
2333 begin
2334 Result := PixelsPerInch * 0.010; {10 mils}
2335 if Result < 1 then
2336 Result := 1;
2337 end;
2338
2339 function TStBarCode.Validate(DisplayError : Boolean) : Boolean;
2340 var
2341 I : Integer;
2342 CheckC : Integer;
2343 CheckK : Integer;
2344 begin
2345 Result := True;
2346 try
2347 case FBarCodeType of
2348 bcUPC_A :
2349 begin
2350 {11 or 12 characters}
2351 if not (Length(Code) in [11, 12]) then
2352 RaiseStError(EStBarCodeError, stscInvalidUPCACodeLen);
2353 try
2354 GetDigits(Code);
2355 except
2356 RaiseStError(EStBarCodeError, stscInvalidCharacter);
2357 end;
2358
2359 GetCheckCharacters(Code, CheckC, CheckK);
2360 if (Length(Code) = 12) and (CheckC <> bcDigits[12]) then
2361 RaiseStError(EStBarCodeError, stscInvalidCheckCharacter);
2362 end;
2363 bcUPC_E :
2364 begin
2365 {6 characters}
2366 if not (Length(Code) = 6) then
2367 RaiseStError(EStBarCodeError, stscInvalidUPCACodeLen);
2368 try
2369 GetDigits(Code);
2370 except
2371 RaiseStError(EStBarCodeError, stscInvalidCharacter);
2372 end;
2373 end;
2374 bcEAN_8 :
2375 begin
2376 {7 or 8 characters}
2377 if not (Length(Code) in [7, 8]) then
2378 RaiseStError(EStBarCodeError, stscInvalidEAN8CodeLen);
2379 try
2380 GetDigits(Code);
2381 except
2382 RaiseStError(EStBarCodeError, stscInvalidCharacter);
2383 end;
2384
2385 GetCheckCharacters(Code, CheckC, CheckK);
2386 if (Length(Code) = 8) and (CheckC <> bcDigits[8]) then
2387 RaiseStError(EStBarCodeError, stscInvalidCheckCharacter);
2388 end;
2389 bcEAN_13 :
2390 begin
2391 {12 or 13 characters}
2392 if not (Length(Code) in [12, 13]) then
2393 RaiseStError(EStBarCodeError, stscInvalidEAN13CodeLen);
2394 try
2395 GetDigits(Code);
2396 except
2397 RaiseStError(EStBarCodeError, stscInvalidCharacter);
2398 end;
2399
2400 GetCheckCharacters(Code, CheckC, CheckK);
2401 if (Length(Code) = 13) and (CheckC <> bcDigits[13]) then
2402 RaiseStError(EStBarCodeError, stscInvalidCheckCharacter);
2403 end;
2404 bcInterleaved2of5 :
2405 begin
2406 try
2407 GetDigits(Code);
2408 except
2409 RaiseStError(EStBarCodeError, stscInvalidCharacter);
2410 end;
2411 end;
2412 bcCodabar :
2413 begin
2414 for I := 1 to Length(Code) do
2415 if not (Code[I] in ['0'..'9', '-', '$', ':', '/', '.', '+', 'a'..'d', 'A'..'D']) then
2416 RaiseStError(EStBarCodeError, stscInvalidCharacter);
2417 end;
2418 bcCode11 :
2419 begin
2420 for I := 1 to Length(Code) do
2421 if not (Code[I] in ['0'..'9', '-']) then
2422 RaiseStError(EStBarCodeError, stscInvalidCharacter);
2423 {test check characters}
2424 if not FAddCheckChar then begin
2425 GetCheckCharacters(Code, CheckC, CheckK);
2426 if (StrToInt(Code[Length(Code)-1]) <> CheckC) or
2427 (StrToInt(Code[Length(Code)]) <> CheckK) then
2428 RaiseStError(EStBarCodeError, stscInvalidCheckCharacter);
2429 end;
2430 end;
2431 bcCode39 :
2432 begin
2433 for I := 1 to Length(Code) do
2434 if not (Code[I] in ['0'..'9', 'A'..'Z', 'a'..'z',
2435 '-', '.', ' ', '$', '/', '+', '%', '*']) then
2436 RaiseStError(EStBarCodeError, stscInvalidCharacter);
2437 {check for embedded guard character}
2438 for I := 2 to Length(Code)-1 do
2439 if Code[I] = '*' then
2440 RaiseStError(EStBarCodeError, stscInvalidCharacter);
2441 end;
2442 bcCode93 :
2443 begin
2444 try
2445 GetCheckCharacters(Code, CheckC, CheckK);
2446 except
2447 RaiseStError(EStBarCodeError, stscInvalidCharacter);
2448 end;
2449 end;
2450 bcCode128 :
2451 begin
2452 try
2453 GetCheckCharacters(Code, CheckC, CheckK);
2454 except
2455 RaiseStError(EStBarCodeError, stscInvalidCharacter);
2456 end;
2457 end;
2458 end;
2459 {check supplemental code}
2460 if FSupplementalCode > '' then
2461 if not (Length(FSupplementalCode) in [2, 5]) then
2462 RaiseStError(EStBarCodeError, stscInvalidSupCodeLen);
2463 except
2464 Result := False;
2465 if DisplayError then
2466 raise;
2467 end;
2468 end;
2469
2470
2471 end.

  ViewVC Help
Powered by ViewVC 1.1.20