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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2671 - (hide annotations) (download)
Tue Aug 25 18:15:15 2015 UTC (8 years, 10 months ago) by torben
File size: 71915 byte(s)
Added tpsystools component
1 torben 2671 // 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