fccommon.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:78k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit fcCommon;
  2. {$T-}  { Disable Typed@ Operator}
  3. {
  4. //
  5. // Components : Common routines
  6. //
  7. // Copyright (c) 1995, 1996, 1997 by Woll2Woll Software
  8. //
  9. // 3/10/99 - PYW - Changed TStringList to TStrings.
  10. // 6/28/99 - Support any TCustomGrid for future support in IP 5
  11. // 3/30/2001 - PYW - Made StripPreceding accessible.
  12. // 3/1/2002-PYW-Modified to support E notation in fcstrtofloat2
  13. }
  14. interface
  15. {$i fcIfDef.pas}
  16. uses Classes, SysUtils, Dialogs, Forms, Controls, Printers, Buttons,
  17.   Windows, Graphics, Menus, StdCtrls, TypInfo, Math, Messages, ExtCtrls,{ JPEG,}
  18.   {$ifdef fcDelphi4Up}
  19.   ImgList,
  20.   {$endif}
  21.   Registry, CommCtrl, fcBitmap, ComCtrls;
  22. const
  23.   clNullColor = $0FFFFFFF;
  24. type
  25.   TfcPointSet = (psGlyph, psText, psOffset);
  26.   TfcPointSets = set of TfcPointSet;
  27.   TfcProcMeth = procedure of object;
  28.   TfcBoolFunc = function: Boolean of object;
  29.   TfcSetBoundsProc = procedure(Control: TWinControl; Rect: TRect) of object;
  30.   TfcLayout = (loVertical, loHorizontal);
  31.   TfcFontType = (ftPrinter, ftTrueType, ftOther);
  32.   PfcFontType = ^TfcFontType;
  33.   PfcPolyGonPoints = ^TFCPolyGonPoints;
  34.   TfcPolyGonPoints = array[0..20] of TPoint;
  35.   TwwDBGridOption = (dgEditing, dgAlwaysShowEditor, dgTitles, dgIndicator,
  36.     dgColumnResize, dgColLines, dgRowLines, dgRowFixedLines, dgTabs, dgRowSelect,
  37.     dgAlwaysShowSelection, dgConfirmDelete, dgCancelOnExit,
  38.     dgWordWrap, dgPerfectRowFit, dgMultiSelect);
  39.   TwwDBGridOptions = set of TwwDBGridOption;
  40.   TwwListSortCompare = function (Item1, Item2: String): Integer;
  41.   TwwGetCompareString = function (SList:TStrings; Index: Integer): String;
  42.   TfcOrientation = (fcTopLeft, fcTopRight, fcBottomLeft, fcBottomRight,
  43.     fcTop, fcRight, fcLeft, fcBottom);
  44.   TfcDiagonals = fcTopLeft..fcBottomRight;
  45.   TfcStraights = fcTop..fcBottom;
  46.   TfcGetWordOption = (fcgwSkipLeadingBlanks, fcgwQuotesAsWords, fcgwStripQuotes,
  47.                       fcgwSpacesInWords);
  48.   TfcGetWordOptions = set of TfcGetWordOption;
  49.   fcstrCharSet = Set of char;
  50. //const
  51. //  OFFSETCOORD: array[TfcOrientation] of TPoint = (
  52. //    (x: 1; y: 1) {TopLeft}, (x: -1; y: 1) {TopRight},
  53. //    (x: 1; y: -1) {BottomLeft}, (x: -1; y: -1) {BottomRight},
  54. //    (x: 0; y: 1) {Top}, (x: -1; y: 0) {Right},
  55. //    (x: 1; y: 0) {Left}, (x: 0; y: -1) {Bottom}
  56. //  );
  57. //}
  58. procedure fcHelp(Handle: HWND; HelpTopic: PChar);
  59. procedure fcCalcButtonLayout(TopLeft: TPoint; TextRect, GlyphRect: PRect;
  60.   TextSize, GlyphSize: TSize; Layout: TButtonLayout;
  61.   Spacing: Integer);
  62. function fcGetComCtlVersion: Integer;
  63. procedure fcStripWhiteSpace(var s: string);
  64. procedure fcStripTrailing(var s: string);
  65. procedure fcStripPreceding(var s: string); // 3/30/2001 - PYW - Made StripPreceding accessible.
  66. function fcComponentFromString(Root: TComponent; Value: string): TComponent;
  67. function fcStringFromComponent(Root: TComponent; Value: TComponent): string;
  68. function fcGetRegionData(Rgn: HRGN): string;
  69. // Color related functions
  70. procedure fcColorToByteValues(AColor: TColor; var Reserved, Blue, Green, Red: Byte);
  71. function fcRGBToHexString(R,G,B: Byte): string;
  72. function fcColorToRGBString(AColor: TColor): string;
  73. function fcGetColorFromList(AList: TStrings; Index: Integer): TColor;
  74. function fcSetColorDialogCustomColors(AList: TStrings): TStrings;
  75. function fcModifyColor(Color: TColor; Amount: Integer; Percent: Boolean): TColor;
  76. function fcRGBToBGR(Color: TColor): TColor;
  77. function fcHighestRGBVal(Color: TColor): BYTE;
  78. // Stringlist related functions
  79. function fcGetValuesFromStringList(AList: TStrings; Index: Integer): string;
  80. function fcGetNamesFromStringList(AList: TStrings; Index: Integer): string;
  81. function fcGetItemsFromStringList(SList:TStrings;Index:integer): String;
  82. function fcValueInList(Value: string; List: TStrings): integer;
  83. function fcNameInList(Name: string; List: TStrings): integer;
  84. // Runtime Type Info Functions (RTTI)
  85. function fcGetPropInfo(Component: TPersistent; PropName: string): PPropInfo;
  86. function fcIsClass(ClassType: TClass; const Name: string): Boolean;
  87. function fcGetStrProp(Component: TPersistent; PropName: string): string;
  88. function fcGetOrdProp(Component: TPersistent; PropName: string): Integer;
  89. procedure fcSetStrProp(Component: TPersistent; PropName: string; Value: string);
  90. procedure fcSetOrdProp(Component: TPersistent; PropName: string; Value: Integer);
  91. procedure fcGetBooleanProps(Component: TPersistent; List: TStrings);
  92. // InfoPower Grid Functions
  93. function fcIsInwwGrid(AControl:TControl):boolean;
  94. {$ifdef fcDelphi4Up}
  95. function fcIsInwwObjectView(control: TWinControl):boolean;
  96. function fcIsInwwObjectViewPaint(control: TWinControl):boolean;
  97. function fcIsInwwGridPaint(control: TWinControl):boolean;
  98. {$endif}
  99. function fcGetGridOptions(AControl:TControl): TwwDBGridOptions;
  100. function fcParentGridFocused(AControl:TControl): boolean;
  101. // Miscellaneous
  102. function fcStrToFloat(str:string; DisplayFormat: string = ''):extended;
  103. function fcStrToFloat2(const S: string; var FloatValue: Extended; DisplayFormat: string): boolean;
  104. //function fcStrToFloat(str:string):extended;
  105. function fcStrToRealDef(const S: string; Default: Extended): Real;
  106. procedure fcPatternFill(Pattern: Pointer; SizeOfPat: Integer; Dst: Pointer; SizeOfDst: Integer);
  107. function fcGetShiftState:TShiftState;
  108. procedure fcParentInvalidate(Control: TControl; Erase: Boolean);
  109. procedure fcPlayKeystroke(Handle: HWND; VKChar: word; VKShift: Word);
  110. procedure fcQuickSort(SList: TStrings; L, R: Integer;
  111.   SCompare: TwwListSortCompare; SGetString:TwwGetCompareString);
  112. function fcGetHintWindow: THintWindow;
  113. function fcGenerateName(Component: TComponent; const Base: string): string;
  114. procedure fcAdjustFlag(Condition: Boolean; var Flag: UINT; FlagVal: UINT);
  115. function fcGetCursorPos: TPoint;
  116. function fcCombineRect(r1, r2: TRect): TRect;
  117. procedure fcShowHint(Hint: string; Coord: TPoint);
  118. procedure fcInvalidateChildren(Control: HWND);
  119. procedure fcInvalidateOverlappedWindows(ParentHwnd: HWND; FirstChild: HWND);
  120. function fcProportionalRect(OrigRect: TRect; Width, Height: Integer): TRect;
  121. function fcProportionalCenterRect(OrigRect: TRect; Width, Height: Integer): TRect;
  122. function fcRectEmpty(r: TRect): Boolean;
  123. function fcLineHeight(Canvas: TCanvas; Flags: Integer; MaxWidth: Integer; Line: string): Integer;
  124. function fcUnionRect(R1, R2: TRect): TRect;
  125. function fcUpdatedComCtlVersion: boolean;
  126. procedure fcMakePagesResourceFriendly(PageControl: TPageControl);
  127. function fcRegionFromBitmap(ABitmap: TfcBitmap; TransColor: TColor): HRgn;
  128. procedure fcDrawEllipsis(Canvas: TCanvas; R: TRect; State: TButtonState;
  129.     Enabled: Boolean;
  130.     Transparent: boolean;
  131.     FlatButtonTransparent: boolean;
  132.     ControlState: TControlState);
  133. procedure fcDrawDropDownArrow(Canvas: TCanvas; R: TRect;
  134.     State: TButtonState; Enabled: Boolean; ControlState: TControlState);
  135. function fcExecuteColorDialog(AColor: TColor): TColor;
  136. procedure fcGetChildRegions(Control: TWinControl; Transparent: Boolean; Rgn: HRGN; Offset: TPoint; Flags: Integer);
  137. function fcFindGlobalComponent(const Name: string): TComponent;
  138. function fcIsDesigning(control: TControl): boolean;
  139. procedure fcDisableParentClipping(Parent: TWinControl);
  140. function fcIsInGrid(dtp:TWinControl):boolean;
  141. Function fcstrRemoveChar(str: string; removeChar: char): string;
  142. Function fcGetWord(s: string; var APos: integer; Options: TfcGetWordOptions;
  143.                    DelimSet: fcstrCharSet): string;
  144. Function fcMessageCodeToChar( code: Word ): Char;
  145. function fcUseThemes(Control: TControl): boolean;
  146. Function fcGetControlList(Controller: TComponent): TList;
  147. procedure fcUpdateController(
  148.    var FController: TComponent;
  149.    Value: TComponent;
  150.    Control: TControl);
  151. type
  152.   TfcInteger = record
  153.     Value: Integer;
  154.   end;
  155.   function fcWithInteger(Value: Integer): TfcInteger;
  156. // Animation
  157. type
  158.   TfcAnimateListItem = class
  159.     Control: TWinControl;
  160.     Bitmap: TBitmap;
  161.     OrigRect: TRect;
  162.     CurRect: TRect;
  163.     FinalRect: TRect;
  164.   end;
  165.   TfcGroupAnimateItem = class
  166.     MainItem: TfcAnimateListItem;
  167.     SecondItem: TfcAnimateListItem;
  168.   end;
  169. procedure fcAnimateControls(Control: TWinControl; ControlCanvas: TCanvas; AnimateList: TList; Interval: Integer; Steps: Integer; SetBoundsProc: TfcSetBoundsProc);
  170. procedure fcBufferredAnimation(ControlCanvas: TCanvas; AnimateList: TList; Interval: Integer; Steps: Integer);
  171. //Graphic Functions...
  172. procedure fcTileDraw(Source: TGraphic; Dest: TCanvas; DstRect: TRect);
  173. procedure fcDrawMask(Canvas: TCanvas; ARect: TRect; Bitmap, Mask: TBitmap; Buffer: Boolean);
  174. procedure fcPaintTo(Control: TWinControl; Canvas: TCanvas; X, Y: Integer);
  175. function fcBytesPerScanline(PixelsPerScanline, BitsPerPixel, Alignment: Longint): Longint;
  176. Function fcIsTrueColorBitmap(Bitmap: TBitmap): boolean;
  177. function fcCreateRegionFromBitmap(ABitmap:TBitmap;TransColor: TColor) : HRgn;
  178. function fcGetDIBBitsFromBitmap(aBitmap: TBITMAP; var BitmapInfo:TBitmapInfo; var pixbuf:Pointer; var bytespscanline:Integer; var Hb:HBitmap): Boolean;
  179. procedure fcSetDitherBitmap(DitherBitmap: TBitmap;
  180.   Color1, Color2: TColor);
  181. procedure fcDither(ACanvas: TCanvas; Rect: TRect; Color1, Color2: TColor);
  182. procedure fcOffsetBitmap(Bitmap: TfcBitmap; Transparent: TColor; Offset: TPoint);
  183. procedure fcDottedLine(Canvas: TCanvas; p1, p2: TPoint);
  184. procedure fcTransparentDraw(Canvas: TCanvas; ARect: TRect; Bitmap: TfcBitmap; TransparentColor: TColor);
  185. procedure fcImageListDraw(ImageList: TCustomImageList; Index: Integer; Canvas: TCanvas;
  186.   X, Y: Integer; Style: Cardinal; Enabled: Boolean);
  187. procedure fcImageListDrawFixBug(ImageList: TCustomImageList; Index: Integer; Canvas: TCanvas;
  188.   X, Y: Integer; Style: Cardinal; Enabled: Boolean);
  189. procedure fcPaintRegion(Rgn: HRGN; DoOffset: Boolean; ShowModal: Boolean);
  190. procedure fcPaintCanvas(ACanvas: TCanvas; Modal: Boolean);
  191. procedure fcPaintGraphic(AGraphic: TGraphic; Modal: Boolean);
  192. procedure fcPaintDC(DC: HDC; Modal: Boolean);
  193. procedure fcClipBitmapToRegion(Bitmap: TfcBitmap; Rgn: HRGN);
  194. function fcGetDitherBrush: HBRUSH;
  195. // Value Functions
  196. function fcMinFloat(Int1, Int2: Double): Double; overload;
  197. function fcMin(Int1, Int2: Integer): Integer; overload;
  198. function fcMax(Int1, Int2: Integer): Integer; overload;
  199. function fcMaxFloat(Int1, Int2: Double): Double; overload;
  200. function fcLimit(Val: integer; Int1, Int2: Integer): integer;
  201. function fcThisThat(const Clause: Boolean; TrueVal, FalseVal: Integer): Integer;
  202. // Windows Structure Functions
  203. function fcRectWidth(Rect: TRect): Integer;
  204. function fcRectHeight(Rect: TRect): Integer;
  205. function fcSize(cx, cy: Integer): TSize;
  206. function fcSizeEqual(Size1, Size2: TSize): Boolean;
  207. procedure fcIncSize(var Size: TSize; Amount: Integer);
  208. function fcMessage(Msg: Cardinal; wParam: WPARAM; lParam: LPARAM; MsgRslt: Cardinal): TMessage;
  209. // String Functions
  210. function fcSubstring(s: string; Start, Stop: integer): string;
  211. function fcReplace(s, Find, Replace: string): string;
  212. function fcIndexOf(Substr, s: string; Index: integer): integer;
  213. function fcLastIndexOf(Substr, s: string; Index: integer): integer;
  214. function fcNthIndexOf(Substr, s: string; Index: integer): integer;
  215. function fcCountTokens(s, Delimiter: string): integer;
  216. function fcGetToken(s, Delimiter: string; Index: integer): string;
  217. function fcSetToken(s, Delimiter, Token: string; Index: integer): string;
  218. function fcFindToken(s, Delimiter, Token: string): Integer;
  219. function fcMultiLineTextSize(Canvas: TCanvas; Text: string; LineSpacing: Integer;
  220.   MaxWidth: Integer; DrawFlags: Integer): TSize;
  221. function fcStripAmpersands(Value: string): string;
  222. // Integer Functions
  223. function fcSign(Value: Extended): Integer;
  224. procedure fcCreateDisabledBitmap(SrcBm, DstBm: TBitmap);
  225. // Font Functions
  226. function fcGetFontIcon(FaceName: string): TfcFontType;
  227. function fcGetFontType(AFontType: Integer): TfcFontType;
  228. function fcLogFont: TLogFont;
  229. var fcVersion1stClass: string;
  230. {$r-}
  231. const
  232.   BitMask: array[0..7] of byte = (128, 64, 32, 16, 8, 4, 2, 1);
  233.   fcComCtlVersionIE3 = $00040046;
  234.   fcComCtlVersionIE4 = $00040047;
  235.   fcComCtlVersionIE401 = $00040048;
  236.   fcComCtlDllName = 'comctl32.dll';
  237. implementation
  238.      {$ifdef fcDelphi7Up}
  239.      uses Themes;
  240.      {$endif}
  241.      {$ifdef ThemeManager}
  242.      uses thememgr, themesrv, uxtheme;
  243.      {$endif}
  244. var fcComCtlVersion: Integer;
  245. {$r fcBrushes.res}
  246. {$r fcCmbBtn.res}
  247. function fcGetComCtlVersion: Integer;
  248. var
  249.   FileName: string;
  250.   InfoSize, Wnd: DWORD;
  251.   VerBuf: Pointer;
  252.   FI: PVSFixedFileInfo;
  253.   VerSize: DWORD;
  254. begin
  255.   if fcComCtlVersion = 0 then
  256.   begin
  257.     FileName := fcComCtlDllName;
  258.     InfoSize := GetFileVersionInfoSize(PChar(FileName), Wnd);
  259.     if InfoSize <> 0 then
  260.     begin
  261.       GetMem(VerBuf, InfoSize);
  262.       try
  263.         if GetFileVersionInfo(PChar(FileName), Wnd, InfoSize, VerBuf) then
  264.           if VerQueryValue(VerBuf, '', Pointer(FI), VerSize) then
  265.             fcComCtlVersion := FI.dwFileVersionMS;
  266.       finally
  267.         FreeMem(VerBuf);
  268.       end;
  269.     end;
  270.   end;
  271.   Result := fcComCtlVersion;
  272. end;
  273. // Function for determining the current shiftstate
  274. function fcGetShiftState: TShiftState;
  275. begin
  276.   Result := [];
  277.   if GetKeyState(VK_SHIFT) < 0 then Include(Result, ssShift);
  278.   if GetKeyState(VK_CONTROL) < 0 then Include(Result, ssCtrl);
  279.   if GetKeyState(VK_MENU) < 0 then Include(Result, ssAlt);
  280. end;
  281. // 3/1/2002-PYW-Modified to support E notation.
  282. function fcStrToFloat2(const S: string; var FloatValue: Extended; DisplayFormat: string): boolean;
  283. //var Buffer: array[0..63] of char;
  284. //    Temp: Extended;
  285. var  i, startpos: integer;
  286.     FloatString, TempText: string;
  287.     Negative: boolean;
  288.     ValidSet: fcStrCharSet;
  289. begin
  290.    result:= True;
  291.    FloatString:= '';
  292.    if length(s)=0 then exit;
  293.    //StripLeading non digits
  294.    for i:= 1 to length(s) do
  295.       if s[i] in ['-', '0'..'9', DecimalSeparator, '('] then break;
  296.    startpos:= i;
  297.    Negative:= (s[i]='-');
  298.    //StripLeading non digits again if found negative.
  299.    if Negative then
  300.    begin
  301.      for i:= startpos to length(s) do
  302.         if s[i] in ['0'..'9', DecimalSeparator, '('] then break;
  303.       startpos:= i;
  304.    end;
  305.    //Remove commas and decimal point
  306.    for i:= startpos to length(s) do begin
  307.       if (i>startpos) then
  308.       begin
  309.          // 3/1/2002-PYW-Modified to support E notation.
  310.          ValidSet:= ['0'..'9', '(', ')', DecimalSeparator, ThousandSeparator, 'E'];
  311.          if length(CurrencyString)>0 then ValidSet:= ValidSet + [CurrencyString[1]];
  312.          if not (s[i] in ValidSet) then continue;  // 8/15/2001 - Keep scanning for other digits.
  313.       end;
  314.       if s[i]='(' then FloatString:= FloatString + '-';
  315.       if (s[i] in ['0'..'9', DecimalSeparator, 'E']) then
  316.       begin
  317.           // 3/1/2002-PYW-Modified to support E notation.
  318.          if (s[i]= 'E') then
  319.          begin
  320.            if (i>1) and (s[i-1] in ['0'..'9']) and
  321.               (i<length(s)) and (s[i+1] in ['+','-', '0'..'9']) then
  322.               FloatString:= FloatString + s[i]
  323.          end
  324.          else
  325.            FloatString:= FloatString + s[i]
  326.       end
  327.    end;
  328.    if Negative then FloatString:= '-' + FloatString;
  329.    result:= TextToFloat(pchar(FloatString), FloatValue, fvExtended);
  330.    if result and (FloatValue>0) and (DisplayFormat<>'') then begin
  331.      TempText:=  FormatFloat(DisplayFormat, FloatValue);
  332.      if (TempText<>s) then
  333.      begin
  334.         TempText:=  FormatFloat(DisplayFormat, -FloatValue);
  335.         if TempText=s then FloatValue:=-FloatValue;
  336.      end
  337.    end;
  338. end;
  339. function fcStrToFloat(str:string; DisplayFormat: string = ''):extended;
  340.    function Stripcomma(s:string):String;
  341.    var i:integer;
  342.        c:char;
  343.    begin
  344.      i:=1;
  345.      result :='';
  346.      while i<=length(s) do begin
  347.         c:=s[i];
  348.         if c <> thousandseparator then
  349.            result := result + Copy(s,i,1);
  350.         inc(i);
  351.      end;
  352.    end;
  353. begin
  354.   if not fcStrToFloat2(str, result, DisplayFormat) then
  355.      result:= 0;
  356. //  result:= fcStrToRealDef(stripcomma(str),0.00);
  357. end;
  358. function fcStrToRealDef(const S: string; Default: Extended): Real;
  359. var E: Integer;
  360. begin
  361.   Val(S, Result, E);
  362.   if E <> 0 then Result := Default
  363. end;
  364. { Return true if class is derived from 'Name' }
  365. { This code is more code efficient than InheritsFrom or 'Is'
  366.   as it does not require that the compiler link in the class }
  367. function fcIsClass(ClassType: TClass; const Name: string): Boolean;
  368. begin
  369.   Result := True;
  370.   while ClassType <> nil do
  371.   begin
  372. {    if ClassType.ClassNameIs(Name) then Exit;}
  373.     if uppercase(ClassType.ClassName)=uppercase(Name) then Exit;
  374.     ClassType := ClassType.ClassParent;
  375.   end;
  376.   Result := False;
  377. end;
  378. function fcParentGridFocused(AControl:TControl): boolean;
  379. begin
  380.    result:= False;
  381.    if fcIsClass(AControl.Parent.ClassType, 'TwwDBGrid') then
  382.       if AControl.Parent.Focused then result:= True
  383. end;
  384. function fcIsInwwGrid(AControl: TControl): Boolean;
  385. begin
  386.   result := False;
  387.   if AControl.Parent = nil then Exit;
  388.   if fcIsClass(AControl.Parent.ClassType, 'TCustomGrid') then { 6/28/99 - Support any TCustomGrid }
  389.     result := True;
  390. end;
  391. {$ifdef fcDelphi4Up}
  392. function fcIsInwwObjectView(control: TWinControl):boolean;
  393. begin
  394.   result := False;
  395.   if fcisClass(control.Parent.classType, 'TwwDataInspector') then
  396.      result := True;
  397. end;
  398. function fcIsInwwObjectViewPaint(control: TWinControl):boolean;
  399. begin
  400.   result := False;
  401.   if fcisClass(control.Parent.classType, 'TwwDataInspector') then
  402.      if csPaintCopy in control.ControlState then
  403.         result := True;
  404. end;
  405. function fcIsInwwGridPaint(control: TWinControl):boolean;
  406. begin
  407.   result := False;
  408.   if fcisClass(control.Parent.classType, 'TCustomGrid') then
  409.      if csPaintCopy in control.ControlState then
  410.         result := True;
  411. end;
  412. {$endif}
  413. function fcGetGridOptions(AControl:TControl): TwwDBGridOptions;
  414. begin
  415.   Result := [];
  416.   if fcIsClass(AControl.Parent.ClassType, 'TwwDBGrid') then
  417.     PChar(@result)^ := Char(fcGetOrdProp(AControl.Parent, 'Options'));
  418. end;
  419. // String Functions for stripping out spaces
  420. procedure fcStripPreceding(var s: string);
  421.   var i,len: integer;
  422. begin
  423.   i:= 1;
  424.   len:= length(s);
  425.   while (i<=length(s)) and (s[i] in [' ',#9]) do i:= i+1;
  426.   if ((len<>0) and (i<=len)) then
  427.      s:= copy(s,i,len-i+1)
  428.   else if (len<>0) then s:='';
  429. end;
  430. procedure fcStripTrailing(var s: string);
  431.   var len: integer;
  432. begin
  433.   len := length(s);
  434.   while (len > 0) and (s[len] in [' ', #9]) do len := len - 1;
  435.   SetLength(s, len);
  436. end;
  437. Procedure fcStripWhiteSpace(var s: string);
  438.   var tempstr: string;
  439. begin
  440.   tempstr := s;
  441.   fcStripPreceding(tempstr);
  442.   fcStripTrailing(tempstr);
  443.   s := tempstr;
  444. end;
  445. {Gets the Byte Values for a color independent of order of Color}
  446. procedure fcColorToByteValues(AColor: TColor; var Reserved, Blue, Green, Red: Byte);
  447. var WinColor: COLORREF;
  448. begin
  449.   WinColor := ColorToRGB(AColor);
  450.   Reserved := ($FF000000 and WinColor) Shr 24;
  451.   Blue := ($00FF0000 and WinColor) Shr 16;
  452.   Green := ($0000FF00 and WinColor) Shr 8;
  453.   Red := ($000000FF and WinColor);
  454. end;
  455. function fcRGBToHexString(R,G,B:Byte):String;
  456. begin
  457.   result := Format('%2.2x%2.2x%2.2x',[R,G,B]);
  458. end;
  459. function fcColorToRGBString(AColor: TColor): string;
  460. var red1,blue1,green1,reserved:byte;
  461. begin
  462.   fcColorToByteValues(AColor,reserved,blue1,green1,red1);
  463.   result := 'RGB: '+IntToStr(red1)+', '
  464.                    +IntToStr(green1) + ', '
  465.                    +IntToStr(blue1);
  466. end;
  467. function fcGetItemsFromStringList(SList:TStrings;Index:integer): String;
  468. begin
  469.    result := SList.Strings[Index];
  470. end;
  471. function fcGetNamesFromStringList(AList:TStrings;Index:integer): String;
  472. begin
  473.    result := '';
  474.    if (Index <> -1) then  result := AList.Names[Index];
  475. end;
  476. function fcGetValuesFromStringList(AList:TStrings;Index: Integer): string;
  477. var temps:string;
  478. begin
  479.   temps:=AList.Strings[Index];   //List is in RGB already...
  480.   temps := Copy(temps,pos('=',temps)+1,length(temps));
  481.   fcStripWhiteSpace(temps);
  482.   result :=Temps;
  483. end;
  484. function fcGetColorFromList(AList:TStrings;Index: Integer): TColor;
  485. var temps:string;
  486. begin
  487.    temps := fcGetValuesFromStringList(AList,Index);
  488.    result := StringToColor('$'+temps);
  489. end;
  490. {Returns -1 if ColorValue is not found in the list;
  491.  otherwise returns the index position in the list}
  492. function fcValueInList(Value: string; List: TStrings): integer;
  493. var i: integer;
  494. begin
  495.   result := -1;
  496.   for i := 0 to List.Count - 1 do
  497.     if fcGetValuesFromStringList(List,i) = Value then begin result := i; break; end;
  498. end;
  499. function fcNameInList(Name: string; List: TStrings): integer;
  500. var i: integer;
  501. begin
  502.   result := -1;
  503.   for i := 0 to List.Count - 1 do
  504.     if AnsiUppercase(List.Names[i]) = AnsiUppercase(Name) then { RSW }
  505.     begin
  506.       result := i;
  507.       break;
  508.     end;
  509. end;
  510. function fcSetColorDialogCustomColors(AList:TStrings):TStrings;
  511. var sList:TStringList;
  512.     i:Integer;
  513. begin
  514.   sList := TStringList.Create;
  515.   for i:= ord('A') to ord('P') do
  516.      sList.Add('Color'+Char(i)+'='+AList.Values[AList.Names[i-ord('A')]]);
  517.   result := sList;
  518. end;
  519. procedure fcQuickSort(SList: TStrings; L, R: Integer;
  520.   SCompare: TwwListSortCompare; SGetString:TwwGetCompareString);
  521.   var
  522.     I, J: Integer;
  523.     P, T: String;
  524. begin
  525.     repeat
  526.       I := L;
  527.       J := R;
  528.       P := SGetString(SList,((L + R) shr 1));
  529.       repeat
  530.         while (i<=SList.count-1) and(SCompare(SGetString(SList,I), P) < 0) do
  531.            Inc(I);
  532.         while (j>=0) and (SCompare(SGetString(SList,J), P) > 0) do Dec(J);
  533.         if I <= J then
  534.         begin
  535.           T := SList[I];
  536.           SList[I] := SList[J];
  537.           SList[J] := T;
  538.           Inc(I);
  539.           Dec(J);
  540.         end;
  541.       until I > J;
  542.       if L < J then fcQuickSort(SList, L, J, SCompare, SGetString);
  543.       L := I;
  544.     until I >= R;
  545. end;
  546. function fcIsTrueColorBitmap(Bitmap: TBitmap): boolean;
  547. begin
  548.   result:= Bitmap.PixelFormat = Graphics.pf24bit;
  549. end;
  550. function fcBytesPerScanline(PixelsPerScanline, BitsPerPixel, Alignment: Longint): Longint;
  551. begin
  552.   Dec(Alignment);
  553.   Result := ((PixelsPerScanline * BitsPerPixel) + Alignment) and not Alignment;
  554.   Result := Result div 8;
  555. end;
  556. // This function creates a HBitmap that must be deleted using DeleteObject by the caller
  557. function fcGetDIBBitsFromBitmap(aBitmap: TBITMAP; var BitmapInfo:TBitmapInfo; var pixbuf:Pointer; var bytespscanline:Integer; var Hb:HBitmap): Boolean;
  558. begin
  559.   FillChar(BitmapInfo, SizeOf(TBitmapInfo), 0);
  560.   with BitmapInfo.bmiheader do
  561.   begin
  562.     biSize := sizeof(TBitmapInfoHeader);
  563.     biWidth := ABitmap.Width;
  564.     biHeight := -ABitmap.Height;   //DIBs are Bottom up
  565.     biPlanes :=1;
  566.     biBitCount := 24;
  567.     biCompression := BI_RGB;
  568.     bytespscanline := fcBytesPerScanline(LongInt(biwidth),biBitCount, 32);
  569.   end;
  570.   hb := CreateDIBSection(ABitmap.Canvas.Handle, BitmapInfo, DIB_RGB_COLORS, pixbuf, 0, 0);
  571.   if (pixbuf = nil) or (hb = 0) then
  572.   begin
  573.     raise EInvalidOperation.Create('Could Not Create DIB Section');
  574.     Exit;
  575.   end;
  576.   GetDIBits(ABitmap.Canvas.Handle, aBitmap.handle, 0, ABitmap.height, pixbuf, BitmapInfo, DIB_RGB_COLORS);
  577.   result := True;
  578. end;
  579. type TNewImageList = class(TImageList);
  580. function fcCreateRegionFromBitmap(ABitmap: TBitmap; TransColor: TColor): HRgn;
  581. var
  582.   TempBitmap: TBitmap;
  583.   Rgn1, Rgn2: HRgn;
  584.   Col, StartCol, Row: integer;
  585.   Line: PByteArray;
  586.   function ColToColor(Col: integer): TColor;
  587.   begin
  588.     if fcIsTrueColorBitmap(TempBitmap) then
  589.       result:= Line[Col * 3] * 256 * 256 + Line[Col * 3 + 1] * 256 + Line[Col * 3 + 2]
  590.     else result := TColor(fcThisThat((Line[Col div 8] and BitMask[Col mod 8]) <> 0, clBlack, clWhite));
  591.   end;
  592. begin
  593.   result := 0;
  594.   if (ABitmap <> nil) and (ABitmap.Width = 0) or (ABitmap.Height = 0) then Exit;
  595.   Rgn1 := 0;
  596.   TempBitmap := TBitmap.Create;
  597.   TempBitmap.Assign(ABitmap);
  598.   if not fcIsTrueColorBitmap(TempBitmap) then
  599.   begin
  600.     TempBitmap.Mask(TransColor);
  601.     TransColor := clBlack;
  602.   end;
  603.   with TempBitmap do
  604.   begin
  605.     for Row := 0 to TempBitmap.height-1 do
  606.     begin
  607.       Line:= scanLine[row];
  608.       Col := 0;
  609.       while Col < TempBitmap.Width do
  610.       begin
  611.         while (Col < TempBitmap.Width) and (ColToColor(Col) = TransColor) do inc(Col);
  612.         if Col >= TempBitmap.Width then Continue;
  613.         StartCol := Col;
  614.         while (Col < TempBitmap.Width) and (ColToColor(Col) <> TransColor) do inc(Col);
  615.         if Col >= TempBitmap.Width then Col := TempBitmap.Width;
  616.         if Rgn1 = 0 then Rgn1 := CreateRectRgn(StartCol, Row, Col, Row + 1)
  617.         else begin
  618.           Rgn2 := CreateRectRgn(StartCol, Row, Col, Row + 1);
  619.           if (Rgn2 <> 0) then CombineRgn(Rgn1,Rgn1,Rgn2,RGN_OR);
  620.             Deleteobject(Rgn2);
  621.         end;
  622.       end;
  623.     end;
  624.   end;
  625.   result := Rgn1;
  626.   TempBitmap.Free;
  627. end;
  628. function fcRegionFromBitmap(ABitmap: TfcBitmap; TransColor: TColor): HRgn;
  629. type PCOLORREF = ^COLORREF;
  630. var
  631.   Rgn1, Rgn2: HRgn;
  632.   Col, StartCol, Row: integer;
  633. begin
  634.   result := 0;
  635.   if (ABitmap <> nil) and (ABitmap.Width = 0) or (ABitmap.Height = 0) then Exit;
  636.   Rgn1 := 0;
  637.   if TransColor = -1 then TransColor := fcGetStdColor(ABitmap.Pixels[0, 0]);
  638.   with ABitmap do
  639.   begin
  640.     for Row := 0 to Height - 1 do
  641.     begin
  642.       Col := 0;
  643.       while Col < Width do
  644.       begin
  645.         while (Col < Width) and (fcGetStdColor(Pixels[Row, Col]) = TransColor) do
  646.           inc(Col);
  647.         if Col >= Width then Continue;
  648.         StartCol := Col;
  649.         while (Col < Width) and (fcGetStdColor(Pixels[Row, Col]) <> TransColor) do inc(Col);
  650.         if Col >= Width then Col := Width;
  651.         if Rgn1 = 0 then Rgn1 := CreateRectRgn(StartCol, Row, Col, Row + 1)
  652.         else begin
  653.           Rgn2 := CreateRectRgn(StartCol, Row, Col, Row + 1);
  654.           if (Rgn2 <> 0) then CombineRgn(Rgn1,Rgn1,Rgn2,RGN_OR);
  655.             Deleteobject(Rgn2);
  656.         end;
  657.       end;
  658.     end;
  659.   end;
  660.   result := Rgn1;
  661. end;
  662. procedure fcSetDitherBitmap(DitherBitmap: TBitmap;
  663.   Color1, Color2: TColor);
  664. var i, j: Integer;
  665. begin
  666. {  if (Screen.ActiveForm<>nil) and (Screen.ActiveForm.Canvas.Handle<>0) then
  667.   begin
  668.      if GetDeviceCaps(Screen.ActiveForm.canvas.handle, BITSPIXEL)<=4 then
  669.         DitherBitmap.LoadFromResourceName(HINSTANCE, 'SELECTIONBRUSH')
  670.      else DitherBitmap.LoadFromResourceName(HINSTANCE, 'SELECTIONBRUSH256');
  671.   end
  672.   else}
  673.   DitherBitmap.LoadFromResourceName(HINSTANCE, 'SELECTIONBRUSH');
  674.   for i := 0 to DitherBitmap.Width - 1 do
  675.     for j := 0 to DitherBitmap.Height - 1 do
  676.       if (i + j) mod 2 = 0 then DitherBitmap.Canvas.Pixels[i, j] := clWhite
  677.       else DitherBitmap.Canvas.Pixels[i, j] := clBlack;
  678.   DitherBitmap.Monochrome := True;
  679. end;
  680. function fcMin(Int1, Int2: Integer): Integer;
  681. begin
  682.   if Int1 < Int2 then result := Int1 else result := Int2;
  683. end;
  684. function fcMinFloat(Int1, Int2: Double): Double;
  685. begin
  686.   if Int1 < Int2 then result := Int1 else result := Int2;
  687. end;
  688. function fcMax(Int1, Int2: Integer): Integer;
  689. begin
  690.   if Int1 > Int2 then result := Int1 else result := Int2;
  691. end;
  692. function fcMaxFloat(Int1, Int2: Double): Double;
  693. begin
  694.   if Int1 > Int2 then result := Int1 else result := Int2;
  695. end;
  696. function fcLimit(Val: integer; Int1, Int2: Integer): Integer;
  697. begin
  698.    val:= fcMax(val, int1);
  699.    val:= fcMin(val, int2);
  700.    result:= val;
  701. end;
  702. procedure fcPlayKeystroke(Handle: HWND; VKChar: word; VKShift: Word);
  703. var
  704.   KeyState: TKeyboardState;
  705.   NewKeyState: TKeyboardState;
  706. begin
  707.    GetKeyboardState(KeyState);
  708.    NewKeyState:= KeyState;
  709.    NewKeyState [VKShift] := $81;
  710.    NewKeyState [VKChar] := $81;
  711.    SetKeyboardState(NewKeyState);
  712.    PostMessage(Handle, WM_KEYDOWN, VKChar, 1);
  713.    PostMessage(Handle, WM_KEYUP, VKChar, 1);
  714.    SetKeyboardState(KeyState);
  715. end;
  716. function fcRectWidth(Rect: TRect): Integer;
  717. begin
  718.   result := Rect.Right - Rect.Left;
  719. end;
  720. function fcRectHeight(Rect: TRect): Integer;
  721. begin
  722.   result := Rect.Bottom - Rect.Top;
  723. end;
  724. function fcSubstring(s: string; Start, Stop: integer): string;
  725. begin
  726.   if Stop = 0 then result := Copy(s, Start, length(s) - Start + 1)
  727.   else result := Copy(s, Start, Stop - Start);
  728. end;
  729. function fcIndexOf(Substr, s: string; Index: integer): integer;
  730. begin
  731.   result := pos(Substr, fcSubstring(s, Index, 0));
  732.   if result <> 0 then result := result + Index - 1;
  733. end;
  734. function fcLastIndexOf(Substr, s: string; Index: integer): integer;
  735. begin
  736.   if Index = 0 then Index := Length(s);
  737.   for result := Index - Length(Substr) downto 1 do
  738.     if Copy(s, result, Length(Substr)) = Substr then break;
  739. end;
  740. // Returns the position of Index'th (zero-based) occurance of Substring
  741. function fcNthIndexOf(Substr, s: string; Index: integer): integer;
  742. var Counter: integer;
  743. begin
  744.   Counter := -1;
  745.   result := 0;
  746.   while Counter < Index do
  747.   begin
  748.     inc(Counter);
  749.     result := fcIndexOf(Substr, s, result + 1);
  750.   end;
  751. end;
  752. // Index is zero based.  eg.
  753. function fcCountTokens(s, Delimiter: string): integer;
  754. var i: integer;
  755. begin
  756.   result := 0;
  757.   if length(s) > 0 then result := 1;
  758.   for i := 1 to Length(s) do
  759.     if Copy(s, i, Length(Delimiter)) = Delimiter then inc(result);
  760. end;
  761. // fcGetToken('RichEdit's are great!', ' ', 1) will return 'are'
  762. function fcGetToken(s, Delimiter: string; Index: integer): string;
  763. var Temp: integer;
  764. begin
  765.   if (Index >= fcCountTokens(s, Delimiter)) then result := ''
  766.   else begin
  767.     Temp := fcNthIndexOf(Delimiter, s, Index - 1);
  768.     if Temp <> 0 then inc(Temp, Length(Delimiter))
  769.     else Temp := 1;
  770.     result := fcSubstring(s, Temp, fcNthIndexOf(Delimiter, s, Index));
  771.   end;
  772. end;
  773. // Set's a given token to the given value and returns the updated string.
  774. function fcSetToken(s, Delimiter, Token: string; Index: integer): string;
  775. var Temp: integer;
  776. begin
  777.   Temp := fcNthIndexOf(Delimiter, s, Index - 1);
  778.   if Temp <> 0 then inc(Temp, Length(Delimiter));
  779.   if Temp = 0 then
  780.   begin
  781.     Temp := Length(s) + Length(Delimiter) + 1;
  782.     s := s + Delimiter;
  783.   end;
  784.   if fcNthIndexOf(Delimiter, s, Index) <> 0 then
  785.     result :=
  786.       fcSubstring(s, 1, Temp) +
  787.       Token +
  788.       fcSubstring(s, fcNthIndexOf(Delimiter, s, Index), 0)
  789.   else
  790.     result :=
  791.       fcSubstring(s, 1, Temp) +
  792.       Token;
  793. end;
  794. function fcFindToken(s, Delimiter, Token: string): Integer;
  795. var i: Integer;
  796. begin
  797.   result := -1;
  798.   for i := 0 to fcCountTokens(s, Delimiter) - 1 do
  799.     if fcGetToken(s, Delimiter, i) = Token then
  800.     begin
  801.       result := i;
  802.       Break;
  803.     end;
  804. end;
  805. function fcGetPropInfo(Component: TPersistent; PropName: string): PPropInfo;
  806. begin
  807.   result := GetPropInfo(Component.ClassInfo, PropName);
  808.   if result = nil then raise EInvalidOperation.Create(Format('Property %s does not exist.', [Propname]));
  809. end;
  810. function fcGenerateName(Component: TComponent; const Base: string): string;
  811. var i, j: Integer;
  812.     Accept: Boolean;
  813. begin
  814.   i := 1;
  815.   while True do
  816.   begin
  817.     result := Base + InttoStr(i);
  818.     Accept := True;
  819.     for j := 0 to Component.ComponentCount - 1 do
  820.       if Component.Components[j].Name = result then
  821.       begin
  822.         Accept := False;
  823.         Break;
  824.       end;
  825.     if Accept then Break;
  826.     inc(i);
  827.   end;
  828. end;
  829. function fcGetCursorPos: TPoint;
  830. begin
  831.   GetCursorPos(result);
  832. end;
  833. function fcThisThat(const Clause: Boolean; TrueVal, FalseVal: Integer): Integer;
  834. begin
  835.   if Clause then result := TrueVal else Result := FalseVal;
  836. end;
  837. function fcSize(cx, cy: Integer): TSize;
  838. begin
  839.   result.cx := cx;
  840.   result.cy := cy;
  841. end;
  842. function fcSizeEqual(Size1, Size2: TSize): Boolean;
  843. begin
  844.   result := (Size1.cx = Size2.cx) and (Size1.cy = Size2.cy);
  845. end;
  846. function fcStripAmpersands(Value: string): string;
  847. begin
  848.   result := fcReplace(Value, '&&', #0);
  849.   result := fcReplace(result, '&', '');
  850.   result := fcReplace(result, #0, '&');
  851. end;
  852. function fcReplace(s, Find, Replace: string): string;
  853. var i: integer;
  854. begin
  855.   i := 1;
  856.   result := '';
  857.   while i <> 0 do
  858.   begin
  859.     result := result + fcSubstring(s, i, fcIndexOf(Find, s, i));
  860.     if fcIndexOf(Find, s, i) = 0 then Break;
  861.     result := result + Replace;
  862.     i := fcIndexOf(Find, s, i);
  863.     if i <> 0 then inc(i, Length(Find));
  864.   end;
  865. end;
  866. function fcLineHeight(Canvas: TCanvas; Flags: Integer; MaxWidth: Integer; Line: string): Integer;
  867. var r: TRect;
  868. begin
  869.   r := Rect(0, 0, MaxWidth, 0);
  870.   DrawTextEx(Canvas.Handle, PChar(Line), Length(Line), r, Flags or DT_CALCRECT, nil);
  871.   result := fcRectHeight(r);
  872. end;
  873. function fcMultiLineTextSize(Canvas: TCanvas; Text: string; LineSpacing: Integer;
  874.   MaxWidth: Integer; DrawFlags: Integer): TSize;
  875. var i: Integer;
  876.     s: string;
  877.     TokenCount: Integer;
  878.     r: TRect;
  879. begin
  880.   TokenCount := fcCountTokens(Text, #13#10);
  881.   result := fcSize(0, 0);
  882.   for i := 0 to TokenCount - 1 do
  883.   begin
  884.     s := fcGetToken(Text, #13#10, i);
  885.     if MaxWidth = 0 then
  886.     begin
  887.       inc(result.cy, Canvas.TextHeight(s));
  888.       if Canvas.TextWidth(s) > result.cx then result.cx := Canvas.TextWidth(s);
  889.     end else begin
  890.       r := Rect(0, 0, MaxWidth, 0);
  891.       DrawTextEx(Canvas.Handle, PChar(s), Length(s), r, DrawFlags or DT_CALCRECT, nil);
  892.       inc(result.cy, fcRectHeight(r));
  893.       if fcRectWidth(r) > result.cx then result.cx := fcRectWidth(r);
  894.     end;
  895.     if i < TokenCount - 1 then inc(result.cy, LineSpacing);
  896.   end;
  897. end;
  898. procedure fcAdjustFlag(Condition: Boolean; var Flag: UINT; FlagVal: UINT);
  899. begin
  900.   if Condition then Flag := Flag or FlagVal
  901.   else Flag := Flag and not FlagVal;
  902. end;
  903. function fcSign(Value: Extended): Integer;
  904. begin
  905.   if Value > 0 then result := 1 else if Value < 0 then result := -1 else result := 0;
  906. end;
  907. procedure fcOffsetBitmap(Bitmap: TfcBitmap; Transparent: TColor; Offset: TPoint);
  908. var TempBitmap: TBitmap;
  909. begin
  910.   TempBitmap := TBitmap.Create;
  911.   TempBitmap.Assign(Bitmap);
  912.   TempBitmap.Width := TempBitmap.Width + Abs(Offset.x) * 2;
  913.   TempBitmap.Height := TempBitmap.Height + Abs(Offset.y) * 2;
  914.   TempBitmap.Canvas.Brush.Color := Transparent;
  915.   TempBitmap.Canvas.FillRect(Rect(0, 0, TempBitmap.Width, TempBitmap.Height));
  916.   TempBitmap.Canvas.Draw(Offset.x, Offset.y, Bitmap);
  917.   Bitmap.Assign(TempBitmap);
  918.   TempBitmap.Free;
  919. end;
  920. procedure fcDottedLine(Canvas: TCanvas; p1, p2: TPoint);
  921. var i: integer;
  922.     x, y: integer;
  923.     tot: integer;
  924. begin
  925. {var ABrush: HBRUSH;
  926. begin
  927.   ABrush := fcGetDitherBrush;
  928.   SelectObject(Canvas.Handle, ABrush);
  929.   SetTextColor(Canvas.Handle, clBlack);
  930.   SetBkColor(Canvas.Handle, clWhite);
  931.   SetBkMode(Canvas.Handle, TRANSPARENT);
  932.   PatBlt(Canvas.Handle, 0, 0, 1, 20, $A000C9);
  933.   DeleteObject(ABrush);}
  934.   Canvas.Refresh;
  935.   x := p1.x;
  936.   y := p1.y;
  937.   tot := fcMax(Abs(p2.y - p1.y), Abs(p2.x - p1.x));
  938.   for i := 0 to tot do if i mod 2 = 0 then
  939.   begin
  940.     Canvas.Polyline([Point(x,y), Point(x+1,y+1)]);
  941.     inc(x, (p2.x - p1.x) div fcMax(1, (tot div 2)));
  942.     inc(y, (p2.y - p1.y) div fcMax(1, (tot div 2)));
  943.   end;
  944. end;
  945. procedure fcTransparentDraw(Canvas: TCanvas; ARect: TRect; Bitmap: TfcBitmap; TransparentColor: TColor);
  946. var MaskBm: TfcBitmap;
  947.     Mask: TBitmap;
  948.     TmpBitmap: TBitmap;
  949. begin
  950.   if TransparentColor = -1 then TransparentColor := fcGetStdColor(Bitmap.Pixels[0, 0]);
  951.   MaskBm := TfcBitmap.Create;
  952.   MaskBm.Assign(Bitmap);
  953.   MaskBm.Mask(fcGetColor(TransparentColor));
  954.   Mask := TBitmap.Create;
  955.   Mask.Assign(MaskBm);
  956.   Mask.Monochrome := True;
  957.   MaskBm.Free;
  958.   TmpBitmap := TBitmap.Create;
  959.   TmpBitmap.Assign(Bitmap);
  960.   fcDrawMask(Canvas, ARect, TmpBitmap, Mask, True);
  961.   TmpBitmap.Free;
  962.   Mask.Free;
  963. end;
  964. function fcModifyColor(Color: TColor; Amount: Integer; Percent: Boolean): TColor;
  965. var Colors: TRGBQuad;
  966.   function HighestOthers(Value: PByte): Byte;
  967.   begin
  968.     with Colors do
  969.     begin
  970.       result := 0;
  971.       if Value = @rgbBlue then result := fcMax(rgbRed, rgbGreen)
  972.       else if Value = @rgbRed then result := fcMax(rgbBlue, rgbGreen)
  973.       else if Value = @rgbGreen then result := fcMax(rgbRed, rgbBlue);
  974.     end;
  975.   end;
  976.   function Check(Value: Integer): Byte;
  977.   begin
  978.     result := Value;
  979.     if Value < 0 then result := 0;
  980.     if Value > 255 then result := 255;
  981.   end;
  982.   procedure DoChange(Value: PByte);
  983.   begin
  984.     if (Value^ = 0) and (HighestOthers(Value) = 255) and (Amount > 0) then
  985.     begin
  986.       if Percent then Value^ := Check(255 * Amount div 100)
  987.       else Value^ := Check(Amount);
  988.     end else begin
  989.       if Percent then
  990.       begin
  991.         if Amount > 0 then Value^ := Check(Value^ + (255 - Value^) * Amount div 100)
  992.         else Value^ := Check(Value^ + Value^ * Amount div 100);
  993.       end else Value^ := Check(Value^ + Amount);
  994.     end;
  995.   end;
  996. begin
  997.   with Colors do
  998.   begin
  999.     fcColorToByteValues(Color, rgbReserved, rgbBlue, rgbGreen, rgbRed);
  1000.     DoChange(@rgbRed);
  1001.     DoChange(@rgbBlue);
  1002.     DoChange(@rgbGreen);
  1003.     result := RGB(rgbRed, rgbGreen, rgbBlue);
  1004.   end;
  1005. end;
  1006. procedure fcImageListDraw(ImageList: TCustomImageList; Index: Integer; Canvas: TCanvas;
  1007.   X, Y: Integer; Style: Cardinal; Enabled: Boolean);
  1008. const
  1009.   ROP_DSPDxax = $00E20746;
  1010. var
  1011.   R: TRect;
  1012.   DestDC, SrcDC: HDC;
  1013.   function GetRGBColor(Value: TColor): DWORD;
  1014.   begin
  1015.     Result := ColorToRGB(Value);
  1016.     case Result of
  1017.       clNone: Result := CLR_NONE;
  1018.       clDefault: Result := CLR_DEFAULT;
  1019.     end;
  1020.   end;
  1021. var AMonoBitmap: TBitmap;
  1022. begin
  1023.   with ImageList do
  1024.   begin
  1025.     if HandleAllocated then
  1026.     begin
  1027.       if Enabled then
  1028.          ImageList_DrawEx(Handle, Index, Canvas.Handle, X, Y, 0, 0,
  1029.             GetRGBColor(TImageList(ImageList).BkColor), GetRGBColor(TImageList(ImageList).BlendColor), Style)
  1030.       else
  1031.       begin
  1032.         AMonoBitmap := TBitmap.Create;
  1033.         with AMonoBitmap do
  1034.         begin
  1035.           Monochrome := True;
  1036.           Width := TImageList(ImageList).Width;
  1037.           Height := TImageList(ImageList).Height;
  1038.         end;
  1039.         { Store masked version of image temporarily in FBitmap }
  1040.         ImageList_DrawEx(Handle, Index, AMonoBitmap.Canvas.Handle, 0,0,0,0, 0,0,
  1041.           ILD_MASK);
  1042.         R := Rect(X, Y, X+TImageList(ImageList).Width, Y+TImageList(ImageList).Height);
  1043.         SrcDC := AMonoBitmap.Canvas.Handle;
  1044.         { Convert Black to clBtnHighlight }
  1045.         Canvas.Brush.Color := clBtnHighlight;
  1046.         DestDC := Canvas.Handle;
  1047.         Windows.SetTextColor(DestDC, clWhite);
  1048.         Windows.SetBkColor(DestDC, clBlack);
  1049.         BitBlt(DestDC, X+1, Y+1, TImageList(ImageList).Width, TImageList(ImageList).Height, SrcDC, 0, 0, ROP_DSPDxax);
  1050.         { Convert Black to clBtnShadow }
  1051.         Canvas.Brush.Color := clBtnShadow;
  1052.         DestDC := Canvas.Handle;
  1053.         Windows.SetTextColor(DestDC, clWhite);
  1054.         Windows.SetBkColor(DestDC, clBlack);
  1055.         BitBlt(DestDC, X, Y, TImageList(ImageList).Width, TImageList(ImageList).Height, SrcDC, 0, 0, ROP_DSPDxax);
  1056.         AMonoBitmap.Free;
  1057.       end;
  1058.     end;
  1059.   end;
  1060. end;
  1061. procedure fcImageListDrawFixBug(ImageList: TCustomImageList; Index: Integer; Canvas: TCanvas;
  1062.   X, Y: Integer; Style: Cardinal; Enabled: Boolean);
  1063. const
  1064.   ROP_DSPDxax = $00E20746;
  1065. var
  1066.   R: TRect;
  1067.   DestDC, SrcDC: HDC;
  1068.   function GetRGBColor(Value: TColor): DWORD;
  1069.   begin
  1070.     Result := ColorToRGB(Value);
  1071.     case Result of
  1072.       clNone: Result := CLR_NONE;
  1073.       clDefault: Result := CLR_DEFAULT;
  1074.     end;
  1075.   end;
  1076. var AMonoBitmap: TBitmap;
  1077. begin
  1078.   with ImageList do
  1079.   begin
  1080.     if HandleAllocated then
  1081.     begin
  1082.       if Enabled then
  1083.         if odd(x) then
  1084.           ImageList_DrawEx(Handle, Index, Canvas.Handle, X-1, Y, 0, 0, //ImageList.Width, ImageList.Height,
  1085.           GetRGBColor(TImageList(ImageList).BkColor), GetRGBColor(TImageList(ImageList).BlendColor), Style)
  1086.         else
  1087.           ImageList_DrawEx(Handle, Index, Canvas.Handle, X, Y, 0, 0,
  1088.           GetRGBColor(TImageList(ImageList).BkColor), GetRGBColor(TImageList(ImageList).BlendColor), Style)
  1089.       else
  1090.       begin
  1091.         AMonoBitmap := TBitmap.Create;
  1092.         with AMonoBitmap do
  1093.         begin
  1094.           Monochrome := True;
  1095.           Width := TImageList(ImageList).Width;
  1096.           Height := TImageList(ImageList).Height;
  1097.         end;
  1098.         { Store masked version of image temporarily in FBitmap }
  1099.         ImageList_DrawEx(Handle, Index, AMonoBitmap.Canvas.Handle, 0,0,0,0, 0,0,
  1100.           ILD_MASK);
  1101.         R := Rect(X, Y, X+TImageList(ImageList).Width, Y+TImageList(ImageList).Height);
  1102.         SrcDC := AMonoBitmap.Canvas.Handle;
  1103.         { Convert Black to clBtnHighlight }
  1104.         Canvas.Brush.Color := clBtnHighlight;
  1105.         DestDC := Canvas.Handle;
  1106.         Windows.SetTextColor(DestDC, clWhite);
  1107.         Windows.SetBkColor(DestDC, clBlack);
  1108.         BitBlt(DestDC, X+1, Y+1, TImageList(ImageList).Width, TImageList(ImageList).Height, SrcDC, 0, 0, ROP_DSPDxax);
  1109.         { Convert Black to clBtnShadow }
  1110.         Canvas.Brush.Color := clBtnShadow;
  1111.         DestDC := Canvas.Handle;
  1112.         Windows.SetTextColor(DestDC, clWhite);
  1113.         Windows.SetBkColor(DestDC, clBlack);
  1114.         BitBlt(DestDC, X, Y, TImageList(ImageList).Width, TImageList(ImageList).Height, SrcDC, 0, 0, ROP_DSPDxax);
  1115.         AMonoBitmap.Free;
  1116.       end;
  1117.     end;
  1118.   end;
  1119. end;
  1120. procedure fcIncSize(var Size: TSize; Amount: Integer);
  1121. begin
  1122.   inc(Size.cx, Amount);
  1123.   inc(Size.cy, Amount); 
  1124. end;
  1125. function fcGetHintWindow: THintWindow;
  1126. var i: Integer;
  1127. begin
  1128.   result := nil;
  1129.   for i := 0 to Application.ComponentCount - 1 do
  1130.     if Application.Components[i] is THintWindow then
  1131.     begin
  1132.       result := Application.Components[i] as THintWindow;
  1133.       Break;
  1134.     end;
  1135. end;
  1136. function fcMessage(Msg: Cardinal; wParam: WPARAM; lParam: LPARAM; MsgRslt: Cardinal): TMessage;
  1137. begin
  1138.   result.Msg := Msg;
  1139.   result.wParam := wParam;
  1140.   result.lParam := lParam;
  1141.   result.Result := MsgRslt;
  1142. end;
  1143. function fcGetFontType(AFontType: Integer): TfcFontType;
  1144. begin
  1145.   if AFontType = DEVICE_FONTTYPE then result := ftPrinter
  1146.   else if AFontType and TRUETYPE_FONTTYPE <> 0 then result := ftTrueType
  1147.   else result := ftOther;
  1148. end;
  1149. function fcFontCallBack(lpelf: PEnumLogFontEx; lpntm: PNewTextMetricEx; FontType: Integer;
  1150.   FontIcon: PfcFontType): Integer; stdcall;
  1151. begin
  1152.   result := 0;
  1153.   FontIcon^ := fcGetFontType(FontType);
  1154. end;
  1155. function fcGetFontIcon(FaceName: string): TfcFontType;
  1156. var lf: TLogFont;
  1157. begin
  1158.   FillChar(lf, SizeOf(lf), 0);
  1159.   StrLCopy(lf.lfFaceName, PChar(FaceName), 32);
  1160.   EnumFontFamiliesEx(Printers.Printer.Handle, lf, @fcFontCallback, Integer(@result), 0);
  1161. end;
  1162. function fcGetStrProp(Component: TPersistent; PropName: string): string;
  1163. var PropInfo: PPropInfo;
  1164. begin
  1165.   result := '';
  1166.   PropInfo := GetPropInfo(Component.ClassInfo, PropName);
  1167.   if PropInfo <> nil then result := GetStrProp(Component, PropInfo);
  1168. end;
  1169. function fcGetOrdProp(Component: TPersistent; PropName: string): Integer;
  1170. var PropInfo: PPropInfo;
  1171. begin
  1172.   result := 0;
  1173.   PropInfo := GetPropInfo(Component.ClassInfo, PropName);
  1174.   if PropInfo <> nil then result := GetOrdProp(Component, PropInfo);
  1175. end;
  1176. procedure fcSetStrProp(Component: TPersistent; PropName: string; Value: string);
  1177. var PropInfo: PPropInfo;
  1178. begin
  1179.   PropInfo := GetPropInfo(Component.ClassInfo, PropName);
  1180.   if PropInfo <> nil then SetStrProp(Component, PropInfo, Value);
  1181. end;
  1182. procedure fcSetOrdProp(Component: TPersistent; PropName: string; Value: Integer);
  1183. var PropInfo: PPropInfo;
  1184. begin
  1185.   PropInfo := GetPropInfo(Component.ClassInfo, PropName);
  1186.   if PropInfo <> nil then SetOrdProp(Component, PropInfo, Value);
  1187. end;
  1188. procedure fcGetBooleanProps(Component: TPersistent; List: TStrings);
  1189. var PropList: PPropList;
  1190.     i: Integer;
  1191.     PropCount: Integer;
  1192. begin
  1193.   PropCount := GetTypeData(Component.ClassInfo).PropCount;
  1194.   GetMem(PropList, PropCount * Sizeof(Pointer));
  1195.   try
  1196.     GetPropInfos(Component.ClassInfo, PropList);
  1197.     for i := 0 to PropCount - 1 do
  1198.       if (PropList[i]^.PropType^.Kind = tkEnumeration) and
  1199.          (PropList[i]^.PropType^.Name = 'Boolean') then
  1200.         List.Add(PropList[i].Name);
  1201.   finally
  1202.     FreeMem(PropList);
  1203.   end;
  1204. end;
  1205. function fcLogFont: TLogFont;
  1206. begin
  1207.   with result do
  1208.   begin
  1209.     FillChar(result, SizeOf(result), 0);
  1210.     lfCharSet := DEFAULT_CHARSET;
  1211.     lfFaceName := '';
  1212.     lfPitchAndFamily := 0;
  1213.   end;
  1214. end;
  1215. procedure fcShowHint(Hint: string; Coord: TPoint);
  1216. var r: TRect;
  1217. begin
  1218.   with fcGetHintWindow do
  1219.   begin
  1220.     r := CalcHintRect(Screen.Width - Coord.x, Hint, nil);
  1221.     OffsetRect(r, Coord.x, Coord.y + 20);
  1222.     ActivateHint(r, Hint);
  1223.   end;
  1224. end;
  1225. procedure fcPaintGraphic(AGraphic: TGraphic; Modal: Boolean);
  1226. var ASize: TSize;
  1227.     Form: TForm;
  1228. begin
  1229.   ASize := fcSize(AGraphic.Width, AGraphic.Height);
  1230.   Form := TForm.Create(Application);
  1231.   with Form do
  1232.   begin
  1233.     Width := ASize.cx;
  1234.     Height := ASize.cy;
  1235.     Left := (Screen.Width - Width) div 2;
  1236.     Top := (Screen.Height - Height) div 2;
  1237.     with TImage.Create(Form) do
  1238.     begin
  1239.       Parent := Form;
  1240.       Align := alClient;
  1241.       Picture.Bitmap.Width := Width;
  1242.       Picture.Bitmap.Height := Height;
  1243.       Picture.Bitmap.Canvas.Draw(0, 0, AGraphic);
  1244.     end;
  1245.     if Modal then ShowModal else Show;
  1246.   end;
  1247. end;
  1248. // The following three functions are handy debugging functions to
  1249. // display a Canvas or Region.  Great for bitmaps and stuff. -ksw
  1250. procedure fcPaintCanvas(ACanvas: TCanvas; Modal: Boolean);
  1251. const SCALE = 2;
  1252. var ASize: TSize;
  1253.     Form: TForm;
  1254. begin
  1255.   ASize := fcSize(fcRectWidth(ACanvas.ClipRect), fcRectHeight(ACanvas.ClipRect));
  1256.   Form := TForm.Create(Application);
  1257.   with Form do
  1258.   begin
  1259.     Width := ASize.cx * SCALE;
  1260.     Height := ASize.cy * SCALE;
  1261.     Left := (Screen.Width - Width) div 2;
  1262.     Top := (Screen.Height - Height) div 2;
  1263.     with TImage.Create(Form) do
  1264.     begin
  1265.       Parent := Form;
  1266.       Align := alClient;
  1267.       Picture.Bitmap.Width := Width;
  1268.       Picture.Bitmap.Height := Height;
  1269.       Picture.Bitmap.Canvas.CopyRect(Rect(0, 0, ASize.cx, ASize.cy),
  1270.         ACanvas, Rect(0, 0, ASize.cx, ASize.cy));
  1271.     end;
  1272.     if Modal then ShowModal else Show;
  1273.   end;
  1274. end;
  1275. procedure fcPaintDC(DC: HDC; Modal: Boolean);
  1276. var ACanvas: TCanvas;
  1277. begin
  1278.   ACanvas := TCanvas.Create;
  1279.   ACanvas.Handle := DC;
  1280.   fcPaintCanvas(ACanvas, Modal);
  1281.   ACanvas.Handle := 0;
  1282.   ACanvas.Free;
  1283. end;
  1284. procedure fcPaintRegion(Rgn: HRGN; DoOffset: Boolean; ShowModal: Boolean);
  1285. const SCALE = 2;
  1286. var RgnData: PRgnData;
  1287.     Size: Integer;
  1288.     Offset: TPoint;
  1289.     RgnSize: TSize;
  1290.     i: Integer;
  1291.     ACanvas: TCanvas;
  1292.     r: TRect;
  1293.     Form: TForm;
  1294. begin
  1295.   Size := GetRegionData(Rgn, 0, nil);
  1296.   if Size = 0 then Exit;
  1297.   GetMem(RgnData, Size);
  1298.   try
  1299.     GetRegionData(Rgn, Size, RgnData);
  1300.     Offset := Point(0, 0);
  1301.     if DoOffset then Offset := RgnData^.rdh.rcBound.TopLeft;
  1302.     with RgnData^.rdh.rcBound.BottomRight do
  1303.     RgnSize := fcSize(x - Offset.x, y - Offset.y);
  1304.     Form := TForm.Create(Application);
  1305.     with Form do
  1306.     begin
  1307.       Width := RgnSize.cx * SCALE;
  1308.       Height := RgnSize.cy * SCALE;
  1309.       Left := (Screen.Width - Width) div 2;
  1310.       Top := (Screen.Height - Height) div 2;
  1311.       with TImage.Create(Form) do
  1312.       begin
  1313.         Parent := Form;
  1314.         Align := alClient;
  1315.         Picture.Bitmap.Width := Width;
  1316.         Picture.Bitmap.Height := Height;
  1317.         ACanvas := Picture.Bitmap.Canvas;
  1318.         ACanvas.Brush.Color := clRed;
  1319.       end;
  1320.     end;
  1321.     for i := 0 to RgnData^.rdh.nCount - 1 do
  1322.     begin
  1323.       r := PRect(Integer(@RgnData^.Buffer) + i * SizeOf(TRect))^;
  1324.       OffsetRect(r, -Offset.x, -Offset.y);
  1325.       ACanvas.FillRect(r);
  1326.     end;
  1327.     Form.ShowModal;
  1328.     Form.Free;
  1329.   finally
  1330.     FreeMem(RgnData);
  1331.   end;
  1332. end;
  1333. procedure fcGetChildRegions(Control: TWinControl; Transparent: Boolean; Rgn: HRGN; Offset: TPoint;
  1334.   Flags: Integer);
  1335. var TmpRgn: HRGN;
  1336.     i: Integer;
  1337.     r: TRect;
  1338. begin
  1339.   for i := 0 to Control.ControlCount - 1 do
  1340.   begin
  1341.     if Boolean(fcGetOrdProp(Control.Controls[i], 'Transparent')) then Continue;
  1342. //    RgnFlag := RGN_OR;
  1343.     if (Control.Controls[i] is TWinControl) then
  1344.     begin
  1345.       GetWindowRect(TWinControl(Control.Controls[i]).Handle, r);
  1346.       with Control.ClientToScreen(Point(0, 0)) do OffsetRect(r, -x, -y);
  1347.     end else begin
  1348.        r := Control.Controls[i].BoundsRect;
  1349.        if r.Right>Control.Width then r.Right:= Control.Width; { 5/2/99 - Limit to parent's boundaries }
  1350.        if r.Bottom>Control.Height then r.Bottom:= Control.Height
  1351.     end;
  1352.     OffsetRect(r, Offset.x, Offset.y);
  1353.     with r do TmpRgn := CreateRectRgn(Left, Top, Right, Bottom);
  1354.     CombineRgn(Rgn, Rgn, TmpRgn, Flags);
  1355.     DeleteObject(TmpRgn);
  1356. //    fcGetChildRegions(TWinControl(Control.Controls[i]), True, Rgn);
  1357.   end;
  1358. end;
  1359. // Changes the size and position of an array of controls from a
  1360. // beginning rect to an ending rect and animates the resizing/positioning.
  1361. //
  1362. // AnimateList - A TList of TAnimateListItem of each control to be
  1363. //               resized.  Each item contains an item consisting of
  1364. //               Control, OrigRect, and FinalRect; all of which must
  1365. //               be initialized to proper values.
  1366. //
  1367. // Interval    - The amount of time (in milliseconds) to pause between
  1368. //               each step of the resizing (length of each frame).
  1369. //
  1370. // Steps:      - The number of individual frames that the animation
  1371. //               will take.
  1372. //
  1373. // - ksw (12/10/98)
  1374. procedure fcAnimateControls(Control: TWinControl; ControlCanvas: TCanvas; AnimateList: TList; Interval: Integer; Steps: Integer; SetBoundsProc: TfcSetBoundsProc);
  1375. var FStep: Integer;
  1376.     Percent: Double;
  1377. {  procedure UpdateControls;
  1378.   var i: Integer;
  1379.       Rgn, TmpRgn: HRGN;
  1380.   begin
  1381.     Rgn := CreateRectRgn(0,0,0,0);
  1382.     for i := 0 to AnimateList.Count - 1 do with TfcGroupAnimateItem(AnimateList[i]), MainItem do
  1383.       begin
  1384.         Control.Update;
  1385.         with fcUnionRect(CurRect, Control.BoundsRect) do TmpRgn := CreateRectRgn(Left, Top, Right, Bottom);
  1386.         CombineRgn(Rgn, Rgn, TmpRgn, RGN_OR);
  1387.         DeleteObject(TmpRgn);
  1388.       end;
  1389.     for i := 0 to AnimateList.Count - 1 do with TfcGroupAnimateItem(AnimateList[i]), MainItem do
  1390.     begin
  1391.       with Control.BoundsRect do TmpRgn := CreateRectRgn(Left, Top, Right, Bottom);
  1392.       CombineRgn(Rgn, Rgn, TmpRgn, RGN_DIFF);
  1393.       DeleteObject(TmpRgn);
  1394.     end;
  1395.     ValidateRect(Control.Handle, nil);
  1396.     InvalidateRgn(Control.Handle, Rgn, True);
  1397.     Control.Update;
  1398.     DeleteObject(Rgn);
  1399.     for i := 0 to AnimateList.Count - 1 do with TfcGroupAnimateItem(AnimateList[i]) do if SecondItem <> nil then with SecondItem do
  1400.       Control.Update;
  1401.   end;}
  1402.   procedure UpdateControls;
  1403.   var i: Integer;
  1404.       r: TRect;
  1405.   begin
  1406.     for i := 0 to AnimateList.Count - 1 do with TfcGroupAnimateItem(AnimateList[i]) do
  1407.       if SecondItem <> nil then
  1408.       begin
  1409.         r := SecondItem.Control.BoundsRect;
  1410.         ValidateRect(SecondItem.Control.Parent.Handle, @r);
  1411.       end;
  1412.     for i := 0 to AnimateList.Count - 1 do with TfcGroupAnimateItem(AnimateList[i]) do
  1413.     begin
  1414.       MainItem.Control.Invalidate;
  1415.       MainItem.Control.Update;
  1416.       if SecondItem <> nil then
  1417.       begin
  1418.         InvalidateRect(SecondItem.Control.Handle, nil, True);
  1419.         { RSW - 4/15/99 - Only invalidate portion of rectangle }
  1420.         if (SecondItem.Control.Top = SecondItem.CurRect.Top) and
  1421.            (SecondItem.Control.Left = SecondItem.CurRect.Left) {and
  1422.            ((SecondItem.Control.Height <= SecondItem.Currect.Bottom-SecondItem.Currect.Top) or
  1423.             (SecondItem.Control.Width <= SecondItem.Currect.Right-SecondItem.Currect.Left))}
  1424.            then
  1425.         begin
  1426.            r:= SecondItem.Currect;
  1427.            ValidateRect(SecondItem.Control.Parent.Handle, @r);
  1428.            SecondItem.Control.Update;
  1429.         end;
  1430.       end;
  1431.     end;
  1432.   end;
  1433.   procedure SetBounds(Item: TfcAnimateListItem);
  1434.   var R: TRect;
  1435.   begin
  1436.     with Item do
  1437.     begin
  1438.       CurRect := Control.BoundsRect;
  1439.       R := Rect(
  1440.         OrigRect.Left + Trunc((FinalRect.Left - OrigRect.Left) * Percent),
  1441.         OrigRect.Top + Trunc((FinalRect.Top - OrigRect.Top) * Percent),
  1442.         OrigRect.Right + Trunc((FinalRect.Right - OrigRect.Right) * Percent),
  1443.         OrigRect.Bottom + Trunc((FinalRect.Bottom - OrigRect.Bottom) * Percent)
  1444.       );
  1445.       if Assigned(SetBoundsProc) then SetBoundsProc(Control, R) else Control.BoundsRect := R;
  1446.     end;
  1447.   end;
  1448.   procedure Animate;
  1449.   var i: Integer;
  1450.   begin
  1451.     Percent := FStep / Steps;
  1452.     for i := 0 to AnimateList.Count - 1 do with TfcGroupAnimateItem(AnimateList[i]) do
  1453.     begin
  1454.       SetBounds(MainItem);
  1455.       if SecondItem <> nil then SetBounds(SecondItem);
  1456.     end;
  1457.   end;
  1458. begin
  1459.   if AnimateList.Count > 0 then for FStep := 1 to Steps do
  1460.   begin
  1461.     Animate;
  1462. //    if FStep=Steps then break; { 4/10/99 - RSW, let caller invalidate last time }
  1463. //                           { to take care of problem with non-rectangular regions being painted correctly }
  1464.     UpdateControls;
  1465.     // 4/3/03 - ProcessMessages causes problems with themes so we do not call in this case
  1466.     if not fcUseThemes(Control) then Application.ProcessMessages;
  1467.     Sleep(Interval);
  1468.     if not fcUseThemes(Control) then Application.ProcessMessages;
  1469.   end;
  1470. end;
  1471. {
  1472. procedure fcAnimateControls(Control: TWinControl; ControlCanvas: TCanvas; AnimateList: TList; Interval: Integer; Steps: Integer; SetBoundsProc: TfcSetBoundsProc);
  1473. var FStep: Integer;
  1474.     Percent: Double;
  1475.   procedure UpdateControls;
  1476.   var i: Integer;
  1477.       Rgn, TmpRgn: HRGN;
  1478.       FirstRect, LastRect: TRect;
  1479.   begin
  1480.     with TfcGroupAnimateItem(AnimateList[0]).MainItem do FirstRect := fcUnionRect(CurRect, Control.BoundsRect);
  1481.     with TfcGroupAnimateItem(AnimateList[AnimateList.Count - 1]).MainItem do LastRect := fcUnionRect(CurRect, Control.BoundsRect);
  1482.     with fcUnionRect(FirstRect, LastRect) do Rgn := CreateRectRgn(Left, Top, Right, Bottom);
  1483.     for i := 0 to AnimateList.Count - 1 do with TfcGroupAnimateItem(AnimateList[i]), MainItem do
  1484.       begin
  1485.         Control.Update;
  1486.         with Control.BoundsRect do TmpRgn := CreateRectRgn(Left, Top, Right, Bottom);
  1487.         CombineRgn(Rgn, Rgn, TmpRgn, RGN_DIFF);
  1488.         DeleteObject(TmpRgn);
  1489.       end;
  1490.     ValidateRect(Control.Handle, nil);
  1491.     InvalidateRgn(Control.Handle, Rgn, True);
  1492.     Control.Update;
  1493.     DeleteObject(Rgn);
  1494.     for i := 0 to AnimateList.Count - 1 do with TfcGroupAnimateItem(AnimateList[i]) do if SecondItem <> nil then with SecondItem do
  1495.       Control.Update;
  1496.   end;
  1497.   procedure SetBounds(Item: TfcAnimateListItem);
  1498.   var R: TRect;
  1499.   begin
  1500.     with Item do
  1501.     begin
  1502.       CurRect := Control.BoundsRect;
  1503.       R := Rect(
  1504.         OrigRect.Left + Trunc((FinalRect.Left - OrigRect.Left) * Percent),
  1505.         OrigRect.Top + Trunc((FinalRect.Top - OrigRect.Top) * Percent),
  1506.         OrigRect.Right + Trunc((FinalRect.Right - OrigRect.Right) * Percent),
  1507.         OrigRect.Bottom + Trunc((FinalRect.Bottom - OrigRect.Bottom) * Percent)
  1508.       );
  1509.       if Assigned(SetBoundsProc) then SetBoundsProc(Control, R) else Control.BoundsRect := R;
  1510.     end;
  1511.   end;
  1512.   procedure Animate;
  1513.   var i: Integer;
  1514.   begin
  1515.     Percent := FStep / Steps;
  1516.     for i := 0 to AnimateList.Count - 1 do with TfcGroupAnimateItem(AnimateList[i]) do
  1517.     begin
  1518.       SetBounds(MainItem);
  1519.       if SecondItem <> nil then SetBounds(SecondItem);
  1520.     end;
  1521.   end;
  1522. begin
  1523.   if AnimateList.Count > 0 then for FStep := 1 to Steps do
  1524.   begin
  1525.     Animate;
  1526.     UpdateControls;
  1527.     Application.ProcessMessages;
  1528.     Sleep(Interval);
  1529.     Application.ProcessMessages;
  1530.   end;
  1531. end;
  1532. }
  1533. function fcWithInteger(Value: Integer): TfcInteger;
  1534. begin
  1535.   result.Value := Value;
  1536. end;
  1537. function fcCombineRect(r1, r2: TRect): TRect;
  1538. begin
  1539.   result := Rect(
  1540.     fcMin(r1.Left, r2.Left),
  1541.     fcMin(r1.Top, r2.Top),
  1542.     fcMax(r1.Right, r2.Right),
  1543.     fcMax(r1.Bottom, r2.Bottom)
  1544.   );
  1545. end;
  1546. procedure fcClipBitmapToRegion(Bitmap: TfcBitmap; Rgn: HRGN);
  1547. var RectRgn: HRGN;
  1548. begin
  1549.   RectRgn := CreateRectRgn(0, 0, Bitmap.Width, Bitmap.Height);
  1550.   try
  1551.     if CombineRgn(RectRgn, RectRgn, Rgn, RGN_DIFF) <> ERROR then
  1552.     begin
  1553.       Bitmap.Canvas.Brush.Color := Bitmap.TransparentColor;
  1554.       FillRgn(Bitmap.Canvas.Handle, RectRgn, Bitmap.Canvas.Brush.Handle);
  1555.     end;
  1556.   finally
  1557.     DeleteObject(RectRgn);
  1558.   end;
  1559. end;
  1560. function fcRGBToBGR(Color: TColor): TColor;
  1561. begin
  1562.   result := 0;
  1563.   result := result or ((Color and $00FF0000) shr 16);
  1564.   result := result or (Color and $0000FF00);
  1565.   result := result or ((Color and $000000FF) shl 16);
  1566. end;
  1567. function EnumChildProc(hwnd: HWND; lParam: LPARAM): Boolean; stdcall;
  1568. begin
  1569.   fcInvalidateChildren(hwnd);
  1570.   result := True;
  1571. end;
  1572. procedure fcInvalidateChildren(Control: HWND);
  1573. begin
  1574.   InvalidateRect(Control, nil, False);
  1575.   EnumChildWindows(Control, @EnumChildProc, 0);
  1576. end;
  1577. function fcGetWindowRect(Wnd: HWND): TRect;
  1578. begin
  1579.   GetWindowRect(Wnd, result);
  1580. end;
  1581. function fcUnionRect(R1, R2: TRect): TRect;
  1582. begin
  1583.   UnionRect(result, R1, R2);
  1584. end;
  1585. function fcIntersectRect(R1, R2: TRect): TRect;
  1586. begin
  1587.   IntersectRect(result, r1, r2);
  1588. end;
  1589. function fcRectEmpty(r: TRect): Boolean;
  1590. begin
  1591.   result := EqualRect(r, Rect(0, 0, 0, 0));
  1592. end;
  1593. function InvalidateOverlappedProc(Child: HWND; ARect: PRect): Boolean; stdcall;
  1594. begin
  1595.   if not fcRectEmpty(fcIntersectRect(ARect^, fcGetWindowRect(Child))) then
  1596.     fcInvalidateChildren(Child);
  1597.   result := True;
  1598. end;
  1599. procedure fcInvalidateOverlappedWindows(ParentHwnd: HWND; FirstChild: HWND);
  1600. var ControlRect: TRect;
  1601. begin
  1602.   GetWindowRect(FirstChild, ControlRect);
  1603.   EnumChildWindows(ParentHWND, @InvalidateOverlappedProc, Integer(@ControlRect));
  1604. end;
  1605. procedure fcParentInvalidate(Control: TControl; Erase: Boolean);
  1606. var r: TRect;
  1607. begin
  1608.   r := Control.BoundsRect;
  1609.   if Control.Parent <> nil then
  1610.     InvalidateRect(Control.Parent.Handle, @r, Erase);
  1611. end;
  1612. procedure fcPaintTo(Control: TWinControl; Canvas: TCanvas; X, Y: Integer);
  1613. {var OldTop: UINT;
  1614.     DC: HDC;}
  1615. var i: Integer;
  1616. begin
  1617.   SendMessage(Control.Handle, WM_ERASEBKGND, Canvas.Handle, 0);
  1618.   SendMessage(Control.Handle, WM_PAINT, Canvas.Handle, 0);
  1619.   for i := 0 to Control.ControlCount - 1 do if Control.Controls[i] is TWinControl then
  1620.     fcPaintTo(Control.Controls[i] as TWinControl, Canvas, Control.Controls[i].Left, Control.Controls[i].Top);  
  1621. {  OldTop := $FFFFFFFF;
  1622.   if not Control.Visible then
  1623.   begin
  1624.     OldTop := Control.Top;
  1625.     Control.Top := -Control.Height;
  1626.     Control.Visible := True;
  1627.   end;
  1628.   DC := GetWindowDC(Control.Handle);
  1629.   BitBlt(Canvas.Handle, 0, 0, Control.Width, Control.Height,
  1630.     DC, 0, 0, SRCCOPY);
  1631.   ReleaseDC(Control.Handle, DC);
  1632.   if OldTop <> $FFFFFFFF then
  1633.   begin
  1634.     Control.Top := OldTop;
  1635.     Control.Visible := False;
  1636.   end;}
  1637. end;
  1638. procedure fcBufferredAnimation(ControlCanvas: TCanvas; AnimateList: TList; Interval: Integer; Steps: Integer);
  1639. var FStep: Integer;
  1640.   procedure Animate;
  1641.   var i: Integer;
  1642.       Percent: Double;
  1643.   begin
  1644.     Percent := FStep / Steps;
  1645.     for i := 0 to AnimateList.Count - 1 do with TfcAnimateListItem(AnimateList[i]) do
  1646.     begin
  1647.       CurRect := Rect(
  1648.         OrigRect.Left + Trunc((FinalRect.Left - OrigRect.Left) * Percent),
  1649.         OrigRect.Top + Trunc((FinalRect.Top - OrigRect.Top) * Percent),
  1650.         OrigRect.Right + Trunc((FinalRect.Right - OrigRect.Right) * Percent),
  1651.         OrigRect.Bottom + Trunc((FinalRect.Bottom - OrigRect.Bottom) * Percent)
  1652.       );
  1653.       ControlCanvas.StretchDraw(CurRect, Bitmap);
  1654.     end;
  1655.   end;
  1656. var i: Integer;
  1657. begin
  1658.   for i := 0 to AnimateList.Count - 1 do
  1659.     with TfcAnimateListItem(AnimateList[i]) do
  1660.     begin
  1661.       Bitmap := TBitmap.Create;
  1662.       Bitmap.Width := Control.Width;
  1663.       Bitmap.Height := Control.Height;
  1664.       fcPaintTo(Control, Bitmap.Canvas, 0, 0);
  1665. //      SendMessage(Control.Handle, WM_PAINT, Bitmap.Canvas.Handle, 0);
  1666. //      fcPaintCanvas(Bitmap.Canvas, True);
  1667.     end;
  1668.   if AnimateList.Count > 0 then for FStep := 1 to Steps do
  1669.   begin
  1670.     Animate;
  1671.     Application.ProcessMessages;
  1672.     Sleep(Interval);
  1673.     Application.ProcessMessages;
  1674.   end;
  1675.   for i := 0 to AnimateList.Count - 1 do
  1676.     with TfcAnimateListItem(AnimateList[i]) do
  1677.       Bitmap.Free;
  1678. end;
  1679. function fcHighestRGBVal(Color: TColor): BYTE;
  1680. var Colors: TRGBQuad;
  1681. begin
  1682.   with Colors do
  1683.   begin
  1684.     fcColorToByteValues(Color, rgbReserved, rgbBlue, rgbGreen, rgbRed);
  1685.     result := rgbRed;
  1686.     if rgbBlue > result then result := rgbBlue;
  1687.     if rgbGreen > result then result := rgbGreen;
  1688.   end;
  1689. end;
  1690. const
  1691.   DSx =     $00660046;
  1692.   DSna =    $00220326;
  1693. procedure fcDrawMask(Canvas: TCanvas; ARect: TRect; Bitmap, Mask: TBitmap;
  1694.   Buffer: Boolean);
  1695. var oldBkColor, oldTextColor: COLORREF;
  1696.     dcCompat: HDC;
  1697.     pbmpSave: HBITMAP;
  1698.     ABitmap: TBitmap;
  1699.     UseCanvas: TCanvas;
  1700.     Offset: TPoint;
  1701. begin
  1702.   oldBkColor := SetBkColor(Canvas.Handle, RGB(255, 255, 255));
  1703.   oldTextColor := SetTextColor(Canvas.Handle, RGB(0, 0, 0));
  1704.   ABitmap := nil;
  1705.   if Buffer then
  1706.   begin
  1707.     ABitmap := TBitmap.Create;
  1708.     ABitmap.Width := fcRectWidth(ARect);
  1709.     ABitmap.Height := fcRectHeight(ARect);
  1710.     ABitmap.Canvas.CopyRect(Rect(0, 0, ABitmap.Width, ABitmap.Height), Canvas, ARect);
  1711.     UseCanvas := ABitmap.Canvas;
  1712.     Offset := Point(0, 0);
  1713.   end else begin
  1714.     UseCanvas := Canvas;
  1715.     Offset := ARect.TopLeft;
  1716.   end;
  1717.   dcCompat := CreateCompatibleDC(Canvas.Handle);
  1718.   pbmpSave := SelectObject(dcCompat, Bitmap.Handle);
  1719.   BitBlt(UseCanvas.Handle, Offset.x, Offset.y, fcRectWidth(ARect), fcRectHeight(ARect), dcCompat, 0, 0, DSx);
  1720.   SelectObject(dcCompat, Mask.Handle);
  1721.   BitBlt(UseCanvas.Handle, Offset.x, Offset.y, fcRectWidth(ARect), fcRectHeight(ARect), dcCompat, 0, 0, DSna);
  1722.   SelectObject(dcCompat, Bitmap.Handle);
  1723.   BitBlt(UseCanvas.Handle, Offset.x, Offset.y, fcRectWidth(ARect), fcRectHeight(ARect), dcCompat, 0, 0, DSx);
  1724.   SelectObject(dcCompat, pbmpSave);
  1725.   DeleteDC(dcCompat);
  1726.   if Buffer then
  1727.   begin
  1728.     Canvas.CopyRect(ARect, ABitmap.Canvas, Rect(0, 0, ABitmap.Width, ABitmap.Height));
  1729.     ABitmap.Free;
  1730.   end;
  1731.   SetBkColor(Canvas.Handle, oldBkColor);
  1732.   SetTextColor(Canvas.Handle, oldTextColor);
  1733. end;
  1734. function fcProportionalRect(OrigRect: TRect; Width, Height: Integer): TRect;
  1735. begin
  1736.   with OrigRect do
  1737.     if (Width / (Right - Left)) > (Height / (Bottom - Top)) then
  1738.       result := Rect(Left, Top, Left + fcRectWidth(OrigRect),
  1739.         Top + (Height * fcRectWidth(OrigRect) div Width))
  1740.     else result := Rect(Left, Top, Left + (Width *
  1741.       fcRectHeight(OrigRect) div Height), fcRectHeight(OrigRect));
  1742. end;
  1743. function fcProportionalCenterRect(OrigRect: TRect; Width, Height: Integer): TRect;
  1744. var aheightpad,awidthpad:extended;
  1745. begin
  1746.   with OrigRect do
  1747.     if (Width / (Right - Left)) > (Height / (Bottom - Top)) then begin
  1748.       aheightpad := (fcRectHeight(OrigRect)-(Height * (fcRectWidth(OrigRect) / Width))) / 2;
  1749.       result := Rect(Left, Top+Trunc(aheightpad), Left + fcRectWidth(OrigRect),
  1750.                 Top + (Height * fcRectWidth(OrigRect) div Width)+Trunc(aheightpad));
  1751.     end
  1752.     else begin
  1753.       awidthpad := (fcRectWidth(OrigRect) - (Width * (fcRectHeight(OrigRect) / Height))) / 2;
  1754.       result := Rect(Left+Trunc(awidthpad), Top, Left + (Width *
  1755.                 fcRectHeight(OrigRect) div Height)+Trunc(awidthpad), fcRectHeight(OrigRect));
  1756.     end;
  1757. end;
  1758. { Return true if ComCtl is later than 4.70 }
  1759. function fcUpdatedComCtlVersion: boolean;
  1760. var dummy: DWORD;
  1761.     verInfoSize, verValueSize: DWORD;
  1762.     verInfo: Pointer;
  1763.     verValue: PVSFixedFileInfo;
  1764.     V1,V2: WORD;
  1765. begin
  1766.    verInfoSize:= GetFileVersionInfoSize('comctl32.dll', Dummy);
  1767.    if VerInfoSize = 0 then
  1768.    begin
  1769.       Dummy:= GetLastError;
  1770.       result:= True;
  1771.       exit;
  1772.    end;
  1773.    GetMem(VerInfo, VerInfoSize);
  1774.    GetFileVersionInfo('comctl32.dll', 0, VerInfoSize, VerInfo);
  1775.    VerQueryValue(VerInfo, '', Pointer(VerValue), VerValueSize);
  1776.    with VerValue^ do begin
  1777.       V1:= dwFileVersionMS shr 16;
  1778.       V2:= dwFileVersionMS and $FFFF;
  1779.    end;
  1780.    result:= (v1>=4) and (v2>70);
  1781.    FreeMem(VerInfo, VerInfoSize);
  1782. end;
  1783. procedure fcPatternFill(Pattern: Pointer; SizeOfPat: Integer; Dst: Pointer; SizeOfDst: Integer);
  1784. var i: Integer;
  1785. begin
  1786.   for i := 0 to SizeOfDst div SizeOfPat do
  1787.     CopyMemory(Dst, Pattern, SizeOfPat);
  1788.   if SizeOfDst mod SizeOfPat > 0 then
  1789.     CopyMemory(Dst, Pattern, SizeOfDst mod SizeOfPat);
  1790. end;
  1791. type TMyControl = class(TWinControl);
  1792. procedure fcMakePagesResourceFriendly(PageControl: TPageControl);
  1793. var i, j: Integer;
  1794. begin
  1795.   with PageControl do
  1796.     for i := 0 to PageCount - 1 do
  1797.     begin
  1798.       if not Pages[i].Visible then
  1799.       begin
  1800.         for j := 0 to Pages[i].ControlCount - 1 do
  1801.           if Pages[i].Controls[j] is TWinControl then
  1802.             TMyControl(Pages[i].Controls[j]).DestroyHandle;
  1803.       end;
  1804.     end;
  1805. end;
  1806. procedure fcCreateDisabledBitmap(SrcBm, DstBm: TBitmap);
  1807. const ROP_DSPDxax = $00E20746;
  1808. var AMonoBitmap: TBitmap;
  1809.     ARect: TRect;
  1810.     AWidth, AHeight: Integer;
  1811. begin
  1812.   AMonoBitmap := TBitmap.Create;
  1813.   with AMonoBitmap do
  1814.   begin
  1815.     Monochrome := True;
  1816.     Width := SrcBm.Width;
  1817.     Height := SrcBm.Height;
  1818.   end;
  1819.   AWidth := SrcBm.Width;
  1820.   AHeight := SrcBm.Height;
  1821.   ARect := Rect(0, 0, AWidth, AHeight);
  1822.   if DstBm.Width <> SrcBm.Width then DstBm.Width := SrcBm.Width;
  1823.   if DstBm.Height <> SrcBm.Height then DstBm.Height := SrcBm.Height;
  1824.   try
  1825.     with AMonoBitmap do
  1826.     begin
  1827.       Assign(SrcBm);
  1828.       HandleType := bmDDB;
  1829.       Canvas.Brush.Color := clBlack;
  1830.       Width := SrcBm.Width;
  1831.       if Monochrome then
  1832.       begin
  1833.         Canvas.Font.Color := clWhite;
  1834.         Monochrome := False;
  1835.         Canvas.Brush.Color := clWhite;
  1836.       end;
  1837.       Monochrome := True;
  1838.     end;
  1839.     with DstBm.Canvas do
  1840.     begin
  1841.       Brush.Color := clBtnFace;
  1842.       FillRect(ARect);
  1843.       Brush.Color := clBtnHighlight;
  1844.       SetTextColor(Handle, clBlack);
  1845.       SetBkColor(Handle, clWhite);
  1846.       BitBlt(Handle, 1, 1, AWidth, AHeight, AMonoBitmap.Canvas.Handle, 0, 0, ROP_DSPDxax);
  1847.       Brush.Color := clBtnShadow;
  1848.       SetTextColor(Handle, clBlack);
  1849.       SetBkColor(Handle, clWhite);
  1850.       BitBlt(Handle, 0, 0, AWidth, AHeight, AMonoBitmap.Canvas.Handle, 0, 0, ROP_DSPDxax);
  1851.     end;
  1852.   finally
  1853.     AMonoBitmap.Free;
  1854.   end;
  1855. end;
  1856. procedure fcDrawEllipsis(Canvas: TCanvas; R: TRect; State: TButtonState;
  1857.     Enabled: Boolean;
  1858.     Transparent: boolean;
  1859.     FlatButtonTransparent: boolean;
  1860.     ControlState: TControlState);
  1861. var Flags: Integer;
  1862.     DC: HDC;
  1863.     w: integer;
  1864.     LeftIndent, TopIndent: integer;
  1865. begin
  1866.   Flags:= 0;
  1867.   if (State = bsDown) and not (csPaintCopy in ControlState) then
  1868.     Flags := BF_FLAT;
  1869.   if not FlatButtonTransparent then Flags:= Flags or BF_MIDDLE;
  1870.   DC:= Canvas.Handle;
  1871.   if not Transparent then
  1872.       DrawEdge(DC, R, EDGE_RAISED, BF_RECT or Flags);
  1873. //  DrawEdge(DC, R, EDGE_RAISED, BF_RECT or BF_MIDDLE or Flags);
  1874.   LeftIndent:= ((R.Right - R.Left) shr 1) - 1 + Ord(State=bsDown);
  1875.   TopIndent:= ((R.Bottom+1-R.Top) shr 1) - 1 + Ord(State=bsDown);
  1876.   W := (R.Right+1 - R.Left) shr 3;
  1877.   if W = 0 then W := 1;
  1878.   PatBlt(DC, R.Left + LeftIndent, R.Top + TopIndent, W, W, BLACKNESS);
  1879.   PatBlt(DC, R.Left + LeftIndent - (W * 2), R.Top + TopIndent, W, W, BLACKNESS);
  1880.   PatBlt(DC, R.Left + LeftIndent + (W * 2), R.Top + TopIndent, W, W, BLACKNESS);
  1881. end;
  1882. procedure fcDrawDropDownArrow(Canvas: TCanvas; R: TRect;
  1883.     State: TButtonState; Enabled: Boolean; ControlState: TControlState);
  1884. var Flags: Integer;
  1885. begin
  1886.   if not Enabled then Flags := DFCS_SCROLLCOMBOBOX or DFCS_INACTIVE
  1887.   else if (State=bsUp) or (csPaintCopy in ControlState) then
  1888.     Flags := DFCS_SCROLLCOMBOBOX
  1889.   else Flags := DFCS_SCROLLCOMBOBOX or DFCS_FLAT or DFCS_PUSHED;
  1890.   DrawFrameControl(Canvas.Handle, R, DFC_SCROLL, Flags);
  1891. end;
  1892. function fcExecuteColorDialog(AColor: TColor): TColor;
  1893. begin
  1894.   with TColorDialog.Create(Application) do
  1895.   begin
  1896.     Color := AColor;
  1897.     Execute;
  1898.     result := Color;
  1899.     Free;
  1900.   end;
  1901. end;
  1902. function fcComponentFromString(Root: TComponent; Value: string): TComponent;
  1903. var i: Integer;
  1904. begin
  1905.   result := Root;
  1906.   for i := 0 to fcCountTokens(Value, '.') - 1 do
  1907.   begin
  1908.     result := result.FindComponent(fcGetToken(Value, '.', i));
  1909.     if result = nil then Break;
  1910.   end;
  1911.   if result = Root then result := nil;
  1912. end;
  1913. function fcStringFromComponent(Root: TComponent; Value: TComponent): string;
  1914. begin
  1915.   result := '';
  1916.   while not (Value = Root) do
  1917.   begin
  1918.     if result <> '' then result := '.' + result;
  1919.     result := Value.Name + result;
  1920.     Value := Value.Owner;
  1921.   end;
  1922. end;
  1923. procedure fcCalcButtonLayout(TopLeft: TPoint; TextRect, GlyphRect: PRect;
  1924.   TextSize, GlyphSize: TSize; Layout: TButtonLayout;
  1925.   Spacing: Integer);
  1926.   function GetPoint(OffsetX: TfcPointSets; OffsetY: TfcPointSets;
  1927.     OffsetSize: TSize): TPoint;
  1928.   begin
  1929.     result := Point(
  1930.       TopLeft.x - (GlyphSize.cx * ord(psGlyph in OffsetX) +
  1931.         TextSize.cx * ord(psText in OffsetX) +
  1932.         Spacing * ord([psGlyph, psText] * OffsetX = [psGlyph, psText])) div 2 +
  1933.         ord(psOffset in OffsetX) * (OffsetSize.cx + Spacing),
  1934.       TopLeft.y - ((GlyphSize.cy + 1) * ord(psGlyph in OffsetY) +
  1935.         TextSize.cy * ord(psText in OffsetY) +
  1936.         Spacing * ord([psGlyph, psText] * OffsetY = [psGlyph, psText])) div 2 +
  1937.         ord(psOffset in OffsetY) * (OffsetSize.cy + Spacing)
  1938.     );
  1939.   end;
  1940.   procedure SetPoints(OffsetTX: TfcPointSets; OffsetTY: TfcPointSets;
  1941.     OffsetGX: TfcPointSets; OffsetGY: TfcPointSets);
  1942.   begin
  1943.     if TextRect <> nil then with GetPoint(OffsetTX, OffsetTY, GlyphSize) do
  1944.       TextRect^ := Rect(x, y, x + TextSize.cx, y + TextSize.cy);
  1945.     if GlyphRect <> nil then with GetPoint(OffsetGX, OffsetGY, TextSize) do
  1946.       GlyphRect^ := Rect(x, y, x + GlyphSize.cx, y + GlyphSize.cy);
  1947.   end;
  1948. begin
  1949.   if (GlyphSize.cy=0) or (GlyphSize.cx=0) then Spacing := (Spacing-6) div 2; { 4/14/99 - RSW - Center text if no image } {??? why "6"? -ksw}
  1950.   case Layout of
  1951.     blGlyphLeft: SetPoints([psGlyph, psText, psOffset], [psText], [psGlyph, psText], [psGlyph]);
  1952.     blGlyphTop: SetPoints([psText], [psGlyph, psText, psOffset], [psGlyph], [psGlyph, psText]);
  1953.     blGlyphRight: SetPoints([psGlyph, psText], [psText], [psGlyph, psText, psOffset], [psGlyph]);
  1954.     blGlyphBottom: SetPoints([psText], [psGlyph, psText], [psGlyph], [psGlyph, psText, psOffset]);
  1955.   end;
  1956. end;
  1957. function fcGetRegionData(Rgn: HRGN): string;
  1958. var RgnData: PRgnData;
  1959.     Size: Integer;
  1960.     i: Integer;
  1961. begin
  1962.   result := '';
  1963.   Size := GetRegionData(Rgn, 0, nil);
  1964.   if Size = 0 then Exit;
  1965.   GetMem(RgnData, Size);
  1966.   try
  1967.     GetRegionData(Rgn, Size, RgnData);
  1968.     for i := 0 to RgnData^.rdh.nCount - 1 do
  1969.       with PRect(Integer(@RgnData^.Buffer) + i * SizeOf(TRect))^ do
  1970.         result := result + InttoStr(i + 1) + ': (' + InttoStr(Left) + ', ' + InttoStr(Top) + ', ' + InttoStr(Right) + ', ' + InttoStr(Bottom) + '), ';
  1971.   finally
  1972.     FreeMem(RgnData);
  1973.   end;
  1974. end;
  1975. function fcGetDitherBrush: HBRUSH;
  1976. var hatchPattern: array[0..7] of WORD;
  1977.     i: Integer;
  1978.     hatchBitmap: HBITMAP;
  1979. begin
  1980.   for i := 0 to 7 do if i mod 2 = 0 then hatchPattern[i] := $AAAA else hatchPattern[i] := $5555;
  1981.   hatchBitmap := CreateBitmap(8, 8, 1, 1, @hatchPattern);
  1982.   result := CreatePatternBrush(hatchBitmap);
  1983.   DeleteObject(hatchBitmap);
  1984. end;
  1985. procedure fcDither(ACanvas: TCanvas; Rect: TRect; Color1, Color2: TColor);
  1986. var TempBitmap: TfcBitmap;
  1987.     ABrush, OldBrush: HBRUSH;
  1988. begin
  1989.   if Color2 = clNone then raise EInvalidOperation.Create('Color2 cannot be clNone');
  1990.   if (Color1 <> clNone) then
  1991.   begin
  1992.     ABrush := fcGetDitherBrush;
  1993.     SetTextColor(ACanvas.Handle, ColorToRGB(Color2));
  1994.     SetBkColor(ACanvas.Handle, ColorToRGB(Color1));
  1995.     OldBrush := SelectObject(ACanvas.Handle, ABrush);
  1996.     FillRect(ACanvas.Handle, Rect, ABrush);
  1997.     SelectObject(ACanvas.Handle, OldBrush);
  1998.     DeleteObject(ABrush);
  1999.   end else begin
  2000.     TempBitmap := TfcBitmap.Create;
  2001.     try
  2002.       TempBitmap.SetSize(fcRectWidth(Rect), fcRectHeight(Rect));
  2003.       Color1 := GetNearestColor(TempBitmap.Canvas.Handle, $00FFFFFF and (not Color2));
  2004.       fcDither(TempBitmap.Canvas, Rect, Color1, Color2);
  2005.       fcTransparentDraw(ACanvas, Rect, TempBitmap, TempBitmap.Canvas.Pixels[0, 0]);
  2006.     finally
  2007.       TempBitmap.Free;
  2008.     end;
  2009.   end;
  2010. end;
  2011. procedure fcTileDraw(Source: TGraphic; Dest: TCanvas; DstRect: TRect);
  2012. var x, y: Integer;
  2013. begin
  2014.   x := 0; 
  2015.   while x < fcRectWidth(DstRect) do
  2016.   begin
  2017.     y := 0;
  2018.     while y < fcRectHeight(dstRect) do
  2019.     begin
  2020.       Dest.Draw(x, y, Source);
  2021.       inc(y, Source.Height);
  2022.     end;
  2023.     inc(x, Source.Width);
  2024.   end;
  2025. end;
  2026. function fcFindGlobalComponent(const Name: string): TComponent;
  2027. var
  2028.   I: Integer;
  2029. begin
  2030.   for I := 0 to Screen.FormCount - 1 do
  2031.   begin
  2032.     Result := Screen.Forms[I];
  2033.     if CompareText(Name, Result.Name) = 0 then Exit;
  2034.   end;
  2035.   for I := 0 to Screen.DataModuleCount - 1 do
  2036.   begin
  2037.     Result := Screen.DataModules[I];
  2038.     if CompareText(Name, Result.Name) = 0 then Exit;
  2039.   end;
  2040.   Result := nil;
  2041. end;
  2042. procedure fcHelp(Handle: HWND; HelpTopic: PChar);
  2043. var HelpFile: string;
  2044.     Context: array[0..127] of Char;
  2045. begin
  2046.   HelpFile := 'fc3000.hlp';
  2047. (*
  2048.   {$ifdef ver100}HelpFile := '1stClass_D3.hlp';{$endif}
  2049.   {$ifdef ver110}HelpFile := '1stClass_C3.hlp';{$endif}
  2050.   {$ifdef ver120}HelpFile := '1stClass_D4.hlp';{$endif}
  2051.   {$ifdef ver125}HelpFile := '1stClass_C4.hlp';{$endif}
  2052. *)
  2053.   StrCopy(Context, HelpTopic);
  2054.   WinHelp(Handle, PChar(HelpFile), HELP_KEY, LPARAM(@Context));
  2055. end;
  2056. function fcIsDesigning(control: TControl): boolean;
  2057. var form: TCustomForm;
  2058. begin
  2059.    form:= GetParentForm(control);
  2060.    if form<>nil then
  2061.       result:= (csDesigning in form.ComponentState)
  2062.    else
  2063.       result:=  (csDesigning in control.ComponentState)
  2064. end;
  2065. { Parent clipping is required in order to ensure that the background is painted in all cases }
  2066. { For instance, flat transparent buttons do not paint in certain cases if clipchildren is true }
  2067. procedure fcDisableParentClipping(Parent: TWinControl);
  2068. begin
  2069.    SetWindowLong(Parent.Handle, GWL_STYLE,
  2070.     GetWindowLong(Parent.Handle, GWL_STYLE) and not WS_CLIPCHILDREN);
  2071. end;
  2072. function fcIsInGrid(dtp:TWinControl):boolean;
  2073. begin
  2074.   result := False;
  2075.   if fcisClass(dtp.Parent.classType, 'TCustomGrid') then
  2076.      result := True;
  2077. end;
  2078. Function fcstrRemoveChar(str: string; removeChar: char): string;
  2079. var i,j: integer;
  2080.     s: string;
  2081. begin
  2082.    j:= 0;
  2083.    setLength(s, length(str));
  2084.    for i:= 1 to length(str) do begin
  2085.       if (str[i] <> removeChar) then
  2086.       begin
  2087.          j:= j + 1;
  2088.          s[j]:= str[i]
  2089.       end
  2090.    end;
  2091.    setLength(s, j);
  2092.    result:= s;
  2093. end;
  2094. Function fcGetWord(s: string; var APos: integer;
  2095.                    Options: TfcGetWordOptions; DelimSet: fcstrCharSet): string;
  2096. var i: integer;
  2097.    Function max(x,y: integer): integer;
  2098.    begin
  2099.      if x>y then result:= x
  2100.      else result:= y;
  2101.    end;
  2102.    Procedure StripQuotes;
  2103.    begin
  2104.       if not (fcgwStripQuotes in Options) then exit;
  2105.       if (Result[1]='"') or (Result[1]='''') then
  2106.          if (Result[length(Result)] = '"') or
  2107.             (Result[length(Result)] = '''') then
  2108.             Result:= copy(Result, 2, length(Result)-2)
  2109.          else
  2110.             Result:= copy(Result, 2, length(Result)-1);
  2111.    end;
  2112. begin
  2113.    result:= '';
  2114.    if APos<=0 then exit;
  2115.    if APos>length(s) then exit;
  2116.    i:= APos;
  2117.    if (fcgwSkipLeadingBlanks in Options) then
  2118.    begin
  2119.       while (i<=length(s)) and ((s[i]=' ') or (s[i]=#9)) do inc(i);
  2120.       APos:= i;
  2121.    end;
  2122.    if (fcgwQuotesAsWords in Options) then
  2123.    begin
  2124.       if s[i]='"' then begin
  2125.          inc(i);
  2126.          while (i<=length(s)) and (s[i]<>'"') do inc(i);
  2127.          if s[i]='"' then begin
  2128.             result:= copy(s, APos, i+1-APos);
  2129.             APos:= i+1;
  2130.          end
  2131.          else if (i>length(s)) then begin
  2132.             result:= copy(s, APos, length(s));
  2133.             APos:= length(s)+1;
  2134.          end;
  2135.          StripQuotes;
  2136.          exit;
  2137.       end
  2138.    end;
  2139.    if fcgwSpacesInWords in Options then
  2140.    begin
  2141.       while (i<=length(s)) and (s[i] in [#32..#255]) do begin
  2142.          if (s[i] in DelimSet) then break
  2143.          else inc(i);
  2144.       end
  2145.    end
  2146.    else begin
  2147.       while (i<=length(s)) and (s[i] in [#33..#255]) do begin
  2148.          if (s[i] in DelimSet) then break
  2149.          else inc(i);
  2150.       end
  2151.    end;
  2152.    result:= copy(s, APos, max(i-APos, 1));
  2153.    if length(result)>1 then APos:= i
  2154.    else APos:= i+1;
  2155. end;
  2156. Function fcMessageCodeToChar( code: Word ): Char;
  2157.   var mapcode:word;
  2158. Begin
  2159.   if code In [VK_NUMPAD0..VK_NUMPAD9] Then
  2160.      Result := Chr( code - VK_NUMPAD0 + Ord('0'))
  2161.   else begin
  2162.      mapcode := MapVirtualKey(code, 2);
  2163.      Result := chr(mapcode);
  2164.   end;
  2165. end;
  2166. function fcUseThemes(Control: TControl): boolean;
  2167. {$ifdef fcUseThemeManager}
  2168. var DisableThemes: boolean;
  2169.     PropInfo: PPropInfo;
  2170. {$endif}
  2171. begin
  2172.    {$ifdef fcUseThemeManager}
  2173.    result:= ThemeServices.ThemesEnabled;
  2174.    if Control=nil then exit;
  2175.    DisableThemes:= False;
  2176.    PropInfo:= Typinfo.GetPropInfo(control.ClassInfo,'DisableThemes');
  2177.    if PropInfo<>Nil then DisableThemes:= Boolean(GetOrdProp(Control, PropInfo))
  2178.    else begin
  2179.       if Control.parent=nil then exit;
  2180.       PropInfo:= Typinfo.GetPropInfo(Control.parent.ClassInfo,'DisableThemes');
  2181.       if PropInfo<>Nil then DisableThemes:= Boolean(GetOrdProp(Control, PropInfo));
  2182.    end;
  2183.    if DisableThemes then result:= False;
  2184.    {$else}
  2185.    result:=false;
  2186.    {$endif}
  2187. end;
  2188. procedure fcUpdateController(
  2189.    var FController: TComponent;
  2190.    Value: TComponent;
  2191.    Control: TControl);
  2192. var OrigController: TComponent;
  2193. begin
  2194.    OrigController:= FController;
  2195.    if Value <> nil then begin
  2196.      Value.FreeNotification(Control); // Notify us when controller destroyed
  2197.    end;
  2198.    if FController<>Value then
  2199.    begin
  2200.       FController:= Value;
  2201.       if FController<>nil then
  2202.       begin
  2203.          fcGetControlList(FController).Add(Control);
  2204.       end
  2205.       else begin
  2206.          fcGetControlList(OrigController).Remove(Control);
  2207.          FController:= nil;
  2208.       end
  2209.    end
  2210. end;
  2211. Function fcGetControlList(Controller: TComponent): TList;
  2212. var PropInfo: PPropInfo;
  2213. begin
  2214.    Result:= Nil;
  2215.    if Controller=nil then exit;
  2216.    PropInfo:= Typinfo.GetPropInfo(Controller.ClassInfo,'ControlList');
  2217.    if PropInfo<>Nil then Result:= TList(GetOrdProp(Controller, PropInfo));
  2218. end;
  2219. {$r+}
  2220. begin
  2221.   fcVersion1stClass:= '4000.01';
  2222. end.