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

Delphi控件源码

开发平台:

Delphi

  1. {*******************************************************************}
  2. {                                                                   }
  3. {       Almediadev Visual Component Library                         }
  4. {       BusinessSkinForm                                            }
  5. {       Version 1.98                                                }
  6. {                                                                   }
  7. {       Copyright (c) 2000-2003 Almediadev                          }
  8. {       ALL RIGHTS RESERVED                                         }
  9. {                                                                   }
  10. {       Home:  http://www.almdev.com                                }
  11. {       Support: support@almdev.com                                 }
  12. {                                                                   }
  13. {*******************************************************************}
  14. unit bsUtils;
  15. {$P+,S-,W-,R-}
  16. {$WARNINGS OFF}
  17. {$HINTS OFF}
  18. interface
  19. {$R-}
  20. uses
  21.   Windows, Controls, Messages, SysUtils, Classes, Graphics, IniFiles;
  22. const
  23.   maxi = 10000;
  24.   // xp office color consts
  25.   BS_XP_BTNFRAMECOLOR = 8388608;
  26.   BS_XP_BTNACTIVECOLOR = 13811126;
  27.   BS_XP_BTNDOWNCOLOR = 11899781;
  28. type
  29.   TCharSet = set of char;
  30. { TbsFBitmap }
  31.   TFBColor  = record b,g,r:Byte end;
  32.   PFBColor  =^TFBColor;
  33.   TBLine    = array[0..0]of TFBColor;
  34.   PBLine    =^TBLine;
  35.   TPLines  = array[0..0]of PBLine;
  36.   PPLines  =^TPLines;
  37.   TbsFBitmap = class
  38.   private
  39.     Bits:   Pointer;
  40.     procedure   Initialize;
  41.   public
  42.     Pixels: PPLines;
  43.     Gap,
  44.     RowInc,
  45.     Size,
  46.     Width,
  47.     Height: Integer;
  48.     Handle,
  49.     hDC:        Integer;
  50.     bmInfo:     TBitmapInfo;
  51.     bmHeader:   TBitmapInfoHeader;
  52.     constructor Create(HBmp:Integer);
  53.     destructor  Destroy; override;
  54.   end;
  55.   TRectArray = array[0..maxi] of TRect;
  56.   
  57. //
  58. function EqRects(R1, R2: TRect): Boolean;
  59. function NullRect: TRect;
  60. function IsNullRect(R: TRect): Boolean;
  61. function IsNullPoint(P: TPoint): Boolean;
  62. function RectInRect(R1, R2: TRect): Boolean;
  63. //
  64. function RectWidth(R: TRect): Integer;
  65. function RectHeight(R: TRect): Integer;
  66. // Region functions
  67. function CreateRgnFromBmp(B: TBitmap; XO, YO: Integer; var RgnData: PRgnData): integer;
  68. // Stream functions
  69. procedure WriteStringToStream(Str: String; S: TStream);
  70. procedure ReadStringFromStream(var Str: String; S: TStream);
  71. // Skin functions
  72. function GetRect(S: String): TRect;
  73. function GetPoint(S: String): TPoint;
  74. function SetRect(R: TRect): String;
  75. procedure CreateSkinBorderImages(LtPt, RTPt, LBPt, RBPt: TPoint; ClRect: TRect;
  76.   NewLTPt, NewRTPt, NewLBPt, NewRBPt: TPoint; NewClRect: TRect;
  77.   LeftB, TopB, RightB, BottomB, SB: TBitMap; R: TRect; AW, AH: Integer);
  78. procedure CreateSkinImage(LtPt, RTPt, LBPt, RBPt: TPoint; ClRect: TRect;
  79.   NewLTPt, NewRTPt, NewLBPt, NewRBPt: TPoint; NewClRect: TRect;
  80.   B, SB: TBitMap; R: TRect; AW, AH: Integer; DrawClient: Boolean);
  81. procedure CreateSkinImage2(LtPt, RTPt, LBPt, RBPt: TPoint; ClRect: TRect;
  82.   NewLTPt, NewRTPt, NewLBPt, NewRBPt: TPoint; NewClRect: TRect;
  83.   B, SB: TBitMap; R: TRect; AW, AH: Integer; DrawClient: Boolean);
  84. procedure CreateHSkinImage(LO, RO: Integer;
  85.   B, SB: TBitMap; R: TRect; AW, AH: Integer);
  86. procedure CreateHSkinImage2(LO, RO: Integer;
  87.   B, SB: TBitMap; R: TRect; AW, AH: Integer);
  88. procedure CreateVSkinImage(TpO, BO: Integer;
  89.   B, SB: TBitMap; R: TRect; AW, AH: Integer);
  90.   
  91. procedure CreateSkinMask(LtPt, RTPt, LBPt, RBPt: TPoint; ClRect: TRect;
  92.   NewLTPt, NewRTPt, NewLBPt, NewRBPt: TPoint; NewClRect: TRect;
  93.   FMask, RMTop, RMLeft, RMRight, RMBottom: TBitMap; AW, AH: Integer);
  94. procedure CreateSkinSimplyRegion(var FRgn: HRgn; FMask: TBitMap);
  95. procedure CreateSkinRegion(var FRgn: HRgn;
  96.   LtPt, RTPt, LBPt, RBPt: TPoint; ClRect: TRect;
  97.   NewLTPt, NewRTPt, NewLBPt, NewRBPt: TPoint; NewClRect: TRect;
  98.   FMask: TBitMap; AW, AH: Integer);
  99. procedure DrawGlyph(Cnvs: TCanvas; X, Y: Integer; FGlyph: TBitMap;
  100.                     FNumGlyphs, FGlyphNum: Integer);
  101. // IniFile funcitons
  102. function ReadRect(IniFile: TCustomIniFile; Section: String; Ident: String): TRect;
  103. function ReadPoint(IniFile: TCustomIniFile; Section: String; Ident: String): TPoint;
  104. function ReadBoolean(IniFile: TCustomIniFile; Section: String; Ident: String): Boolean;
  105. function ReadFontStyles(IniFile: TCustomIniFile;
  106.                         Section: String; Ident: String): TFontStyles;
  107. procedure ReadStrings(IniFile: TCustomIniFile;
  108.                       Section: String; Ident: String; S: TStrings);
  109. procedure ReadStrings1(IniFile: TCustomIniFile;
  110.                        Section: String; Ident: String; S: TStrings);
  111. function ReadAlignment(IniFile: TCustomIniFile;
  112.                        Section: String; Ident: String): TAlignment;
  113. procedure WriteAlignment(IniFile: TCustomIniFile;
  114.                          Section: String; Ident: String; A: TAlignment);
  115. procedure WriteRect(IniFile: TCustomIniFile; Section: String; Ident: String; R: TRect);
  116. procedure WritePoint(IniFile: TCustomIniFile; Section: String; Ident: String; P: TPoint);
  117. procedure WriteBoolean(IniFile: TCustomIniFile; Section: String; Ident: String; B: Boolean);
  118. procedure WriteFontStyles(IniFile: TCustomIniFile;
  119.                           Section: String; Ident: String; FS: TFontStyles);
  120. procedure WriteStrings(IniFile: TCustomIniFile;
  121.                        Section: String; Ident: String; S: TStrings);
  122. procedure WriteStrings1(IniFile: TCustomIniFile;
  123.                         Section: String; Ident: String; S: TStrings);
  124. procedure GetScreenImage(X, Y: Integer; B: TBitMap);
  125. procedure GetWindowsVersion(var Major, Minor: Integer);
  126. function CheckW2KWXP: Boolean;
  127. function CheckWXP: Boolean;
  128. procedure SetAlphaBlendTransparent(WHandle: HWnd; Value: Byte);
  129. procedure Frm3D(Canvas: TCanvas; Rect: TRect; TopColor, BottomColor: TColor);
  130. procedure DrawRadioImage(Cnvs: TCanvas; X, Y: Integer; Color: TColor);
  131. procedure DrawCheckImage(Cnvs: TCanvas; X, Y: Integer; Color: TColor);
  132. procedure DrawArrowImage(Cnvs: TCanvas; R: TRect; Color: TColor; Code: Integer);
  133. procedure DrawTrackArrowImage(Cnvs: TCanvas; R: TRect; Color: TColor);
  134. function PointInRect(R: TRect; P: TPoint): Boolean;
  135. procedure SPDrawText(Cnvs: TCanvas; S: String; R: TRect);
  136. procedure SPDrawText2(Cnvs: TCanvas; S: String; R: TRect);
  137. procedure SPDrawText3(Cnvs: TCanvas; S: String; R: TRect; HorOffset: Integer);
  138. procedure DrawCloseImage(C: TCanvas; X, Y: Integer; Color: TColor);
  139. procedure DrawRCloseImage(C: TCanvas; R: TRect; Color: TColor);
  140. procedure DrawMinimizeImage(C: TCanvas; X, Y: Integer; Color: TColor);
  141. procedure DrawMaximizeImage(C: TCanvas; X, Y: Integer; Color: TColor);
  142. procedure DrawRollUpImage(C: TCanvas; X, Y: Integer; Color: TColor);
  143. procedure DrawRestoreRollUpImage(C: TCanvas; X, Y: Integer; Color: TColor);
  144. procedure DrawRestoreImage(C: TCanvas; X, Y: Integer; Color: TColor);
  145. procedure DrawSysMenuImage(C: TCanvas; X, Y: Integer; Color: TColor);
  146. procedure DrawMTImage(C: TCanvas; X, Y: Integer; Color: TColor);
  147. function ExtractDay(ADate: TDateTime): Word;
  148. function ExtractMonth(ADate: TDateTime): Word;
  149. function ExtractYear(ADate: TDateTime): Word;
  150. function IsLeapYear(AYear: Integer): Boolean;
  151. function DaysPerMonth(AYear, AMonth: Integer): Integer;
  152. function ReplaceStr(const S, Srch, Replace: string): string;
  153. function Max(A, B: Longint): Longint;
  154. function Min(A, B: Longint): Longint;
  155. procedure CorrectTextbyWidth(C: TCanvas; var S: String; W: Integer);
  156. procedure GetParentImage(Control: TControl; Dest: TCanvas);
  157. implementation
  158. uses Forms, Consts;
  159. const
  160.   LWA_ALPHA = $2;
  161. type
  162.   TParentControl = class(TWinControl);
  163. procedure GetParentImage(Control: TControl; Dest: TCanvas);
  164. var
  165.   I, Count, X, Y, SaveIndex: Integer;
  166.   DC: HDC;
  167.   R, SelfR, CtlR: TRect;
  168.   Ctrl: TControl;
  169. begin
  170.   if Control.Parent = nil then Exit;
  171.   Count := Control.Parent.ControlCount;
  172.   DC := Dest.Handle;
  173.   SelfR := Bounds(Control.Left, Control.Top, Control.Width, Control.Height);
  174.   X := -Control.Left; Y := -Control.Top;
  175.   // Copy parent control image
  176.   if Control.Parent is TForm
  177.   then
  178.     begin
  179.       SaveIndex := SaveDC(DC);
  180.       SetViewportOrgEx(DC, X, Y, nil);
  181.       IntersectClipRect(DC, 0, 0, Control.Parent.ClientWidth,
  182.          Control.Parent.ClientHeight);
  183.       SendMessage(Control.Parent.Handle, WM_ERASEBKGND, DC, 0);
  184.       RestoreDC(DC, SaveIndex);
  185.     end
  186.   else
  187.     begin
  188.       SaveIndex := SaveDC(DC);
  189.       SetViewportOrgEx(DC, X, Y, nil);
  190.       IntersectClipRect(DC, 0, 0, Control.Parent.ClientWidth,
  191.       Control.Parent.ClientHeight);
  192.       TParentControl(Control.Parent).PaintWindow(DC);
  193.       SendMessage(Control.Parent.Handle, WM_ERASEBKGND, DC, 0);
  194.       RestoreDC(DC, SaveIndex);
  195.     end;
  196. end;
  197. procedure CorrectTextbyWidth(C: TCanvas; var S: String; W: Integer);
  198. var
  199.   j: Integer;
  200. begin
  201.   j := Length(S);
  202.   with C do
  203.   begin
  204.     if TextWidth(S) > w
  205.     then
  206.       begin
  207.         repeat
  208.           Delete(S, j, 1);
  209.           Dec(j);
  210.         until (TextWidth(S + '...') <= w) or (S = '');
  211.         S := S + '...';
  212.       end;
  213.   end;
  214. end;
  215. function Max(A, B: Longint): Longint;
  216. begin
  217.   if A > B then Result := A
  218.   else Result := B;
  219. end;
  220. function Min(A, B: Longint): Longint;
  221. begin
  222.   if A < B then Result := A
  223.   else Result := B;
  224. end;
  225. function ReplaceStr(const S, Srch, Replace: string): string;
  226. var
  227.   I: Integer;
  228.   Source: string;
  229. begin
  230.   Source := S;
  231.   Result := '';
  232.   repeat
  233.     I := Pos(Srch, Source);
  234.     if I > 0 then begin
  235.       Result := Result + Copy(Source, 1, I - 1) + Replace;
  236.       Source := Copy(Source, I + Length(Srch), MaxInt);
  237.     end
  238.     else Result := Result + Source;
  239.   until I <= 0;
  240. end;
  241. procedure SPDrawText(Cnvs: TCanvas; S: String; R: TRect);
  242. begin
  243.   DrawText(Cnvs.Handle, PChar(S), Length(S), R,
  244.     DT_VCENTER or DT_SINGLELINE or DT_LEFT);
  245. end;
  246. procedure SPDrawText2(Cnvs: TCanvas; S: String; R: TRect);
  247. var
  248.   TX, TY: Integer;
  249. begin
  250.   TX := R.Left + 2;
  251.   TY := R.Top + RectHeight(R) div 2 - Cnvs.TextHeight(S) div 2;
  252.   Cnvs.TextRect(R, TX, TY, S);
  253. end;
  254. procedure SPDrawText3(Cnvs: TCanvas; S: String; R: TRect; HorOffset: Integer);
  255. var
  256.   TX, TY: Integer;
  257. begin
  258.   TX := R.Left + 2 + HorOffset;
  259.   TY := R.Top + RectHeight(R) div 2 - Cnvs.TextHeight(S) div 2;
  260.   Cnvs.TextRect(R, TX, TY, S);
  261. end;
  262. procedure DrawTrackArrowImage(Cnvs: TCanvas; R: TRect; Color: TColor);
  263. var
  264.   X, Y, i: Integer;
  265. begin
  266.   X := R.Left + RectWidth(R) div 2;
  267.   Y := R.Top + RectHeight(R) div 2 + 2;
  268.   for i := 2 downto 0 do
  269.   with Cnvs do
  270.   begin
  271.     Pen.Color := Color;
  272.     MoveTo(X - i, Y - i);
  273.     LineTo(X + i + 1, Y - i);
  274.   end;
  275. end;
  276. procedure DrawArrowImage(Cnvs: TCanvas; R: TRect; Color: TColor; Code: Integer);
  277. var
  278.   i: Integer;
  279.   X, Y: Integer;
  280. begin
  281.   with Cnvs do
  282.   begin
  283.     Pen.Color := Color;
  284.     case Code of
  285.       1:
  286.         begin
  287.           X := R.Left + RectWidth(R) div 2 - 2;
  288.           Y := R.Top + RectHeight(R) div 2;
  289.           for i := 0 to 3 do
  290.           begin
  291.             MoveTo(X + i, Y - i);
  292.             LineTo(X + i, Y + i + 1);
  293.           end;
  294.         end;
  295.       2:
  296.         begin
  297.           X := R.Left + RectWidth(R) div 2 + 2;
  298.           Y := R.Top + RectHeight(R) div 2;
  299.           for i := 3 downto 0 do
  300.            begin
  301.              MoveTo(X - i, Y + i);
  302.              LineTo(X - i, Y - i - 1);
  303.            end;
  304.         end;
  305.       3:
  306.         begin
  307.           X := R.Left + RectWidth(R) div 2;
  308.           Y := R.Top + RectHeight(R) div 2 - 2;
  309.           for i := 0 to 3 do
  310.           begin
  311.             MoveTo(X - i, Y + i);
  312.             LineTo(X + i + 1, Y + i);
  313.           end;
  314.         end;
  315.       4:
  316.         begin
  317.           X := R.Left + RectWidth(R) div 2;
  318.           Y := R.Top + RectHeight(R) div 2 + 2;
  319.           for i := 3 downto 0 do
  320.           begin
  321.             MoveTo(X - i, Y - i);
  322.             LineTo(X + i + 1, Y - i);
  323.           end;  
  324.         end;
  325.     end;
  326.   end;
  327. end;
  328. procedure DrawRadioImage(Cnvs: TCanvas; X, Y: Integer; Color: TColor);
  329. begin
  330.   with Cnvs do
  331.   begin
  332.     Pen.Color := Color;
  333.     Brush.Color := Color;
  334.     Rectangle(X, Y, X + 6, Y + 6);
  335.   end;
  336. end;
  337. procedure DrawCheckImage(Cnvs: TCanvas; X, Y: Integer; Color: TColor);
  338. var
  339.   i: Integer;
  340. begin
  341.   with Cnvs do
  342.   begin
  343.     Pen.Color := Color;
  344.     for i := 0 to 2 do
  345.     begin
  346.       MoveTo(X, Y + 5 - i);
  347.       LineTo(X + 2, Y + 7 - i);
  348.       LineTo(X + 7, Y + 2 - i);
  349.     end;
  350.   end;
  351. end;
  352. procedure Frm3D;
  353.   procedure DoRect;
  354.   var
  355.     TopRight, BottomLeft: TPoint;
  356.   begin
  357.     with Canvas, Rect do
  358.     begin
  359.       TopRight.X := Right;
  360.       TopRight.Y := Top;
  361.       BottomLeft.X := Left;
  362.       BottomLeft.Y := Bottom;
  363.       Pen.Color := TopColor;
  364.       PolyLine([BottomLeft, TopLeft, TopRight]);
  365.       Pen.Color := BottomColor;
  366.       Dec(BottomLeft.X);
  367.       PolyLine([TopRight, BottomRight, BottomLeft]);
  368.     end;
  369.   end;
  370. begin
  371.   Canvas.Pen.Width := 1;
  372.   Dec(Rect.Bottom); Dec(Rect.Right);
  373.   DoRect;
  374. end;
  375. procedure GetWindowsVersion(var Major, Minor: Integer);
  376. var
  377.   Ver : Longint;
  378. begin
  379.   Ver := GetVersion;
  380.   Major := LoByte(LoWord(Ver));
  381.   Minor := HiByte(LoWord(Ver));
  382. end;
  383. function CheckWXP: Boolean;
  384. var
  385.   Major, Minor : Integer;
  386. begin
  387.   GetWindowsVersion(major, minor);
  388.   Result := (major = 5) and (minor = 1);
  389. end;
  390. function CheckW2kWXP: Boolean;
  391. var
  392.   Major, Minor : Integer;
  393. begin
  394.   GetWindowsVersion(major, minor);
  395.   Result := (major = 5) and ((minor = 0) or (minor = 1))
  396. end;
  397. procedure SetAlphaBlendTransparent;
  398. var
  399.   User32: Cardinal;
  400.   SetLayeredWindowAttributes: function (hwnd: LongInt; crKey: byte; bAlpha: byte; dwFlags: LongInt): LongInt; stdcall;
  401. begin
  402.   User32 := LoadLibrary('USER32');
  403.   if User32 <> 0
  404.   then
  405.     try
  406.      SetLayeredWindowAttributes := GetProcAddress(User32, 'SetLayeredWindowAttributes');
  407.      if @SetLayeredWindowAttributes <> nil
  408.      then
  409.        SetLayeredWindowAttributes(WHandle, 0, Value, LWA_ALPHA);
  410.      finally
  411.         FreeLibrary(User32);
  412.      end;
  413. end;
  414. procedure GetScreenImage(X, Y: Integer; B: TBitMap);
  415. var
  416.   DC: HDC;
  417. begin
  418.   DC := GetDC(0);
  419.   BitBlt(B.Canvas.Handle, 0, 0,
  420.          B.Width, B.Height, DC, X, Y, SrcCopy);
  421.   ReleaseDC(0, DC);
  422. end;
  423. function EqRects(R1, R2: TRect): Boolean;
  424. begin
  425.   Result := (R1.Left = R2.Left) and (R1.Top = R2.Top) and
  426.             (R1.Right = R2.Right) and (R1.Bottom = R2.Bottom);
  427. end;
  428. function NullRect: TRect;
  429. begin
  430.   Result := Rect(0, 0, 0, 0);
  431. end;
  432. function IsNullRect(R: TRect): Boolean;
  433. begin
  434.   Result := (R.Right - R.Left <= 0) or (R.Bottom - R.Top <= 0)
  435. end;
  436. function IsNullPoint(P: TPoint): Boolean;
  437. begin
  438.   Result := (P.X = 0) or (P.Y = 0);
  439. end;
  440. function PointInRect(R: TRect; P: TPoint): Boolean;
  441. begin
  442.   Result := (P.X >= R.Left) and (P.Y >= R.Top) and
  443.             (P.X <= R.Right) and (P.Y <= R.Bottom);
  444. end;
  445. function RectInRect(R1, R2: TRect): Boolean;
  446. begin
  447.   Result := PtInRect(R2, R1.TopLeft) and PtInRect(R2, R1.BottomRight)
  448. end;
  449. function RectWidth;
  450. begin
  451.   Result := R.Right - R.Left;
  452. end;
  453. function RectHeight;
  454. begin
  455.   Result := R.Bottom - R.Top;
  456. end;
  457. const
  458.     nums = '1234567890';
  459.     symbols = ', ';
  460. function GetPoint(S: String): TPoint;
  461. var
  462.   i, j: Integer;
  463.   S1: String;
  464.   SA: array[1..2] of String;
  465. begin
  466.   S1 := '';
  467.   j := 1;
  468.   for i := 1 to Length(S) do
  469.   begin
  470.     if S[i] = ','
  471.     then
  472.       begin
  473.         SA[j] := S1;
  474.         S1 := '';
  475.         Inc(j);
  476.       end
  477.     else
  478.       if Pos(S[i], nums) <> 0 then S1 := S1 + S[i];
  479.   end;
  480.   SA[j] := S1;
  481.   Result := Point(StrToInt(SA[1]), StrToInt(SA[2]));;
  482. end;
  483. function GetRect(S: String): TRect;
  484. var
  485.   i, j: Integer;
  486.   S1: String;
  487.   SA: array[1..4] of String;
  488. begin
  489.   S1 := '';
  490.   j := 1;
  491.   for i := 1 to Length(S) do
  492.   begin
  493.     if S[i] = ','
  494.     then
  495.       begin
  496.         SA[j] := S1;
  497.         S1 := '';
  498.         Inc(j);
  499.       end
  500.     else
  501.       if Pos(S[i], nums) <> 0 then S1 := S1 + S[i];
  502.   end;
  503.   SA[j] := S1;
  504.   Result := Rect(StrToInt(SA[1]), StrToInt(SA[2]),
  505.                  StrToInt(SA[3]), StrToInt(SA[4]));
  506. end;
  507. function SetRect(R: TRect): String;
  508. begin
  509.   Result := IntToStr(R.Left) + ',' +
  510.     IntToStr(R.Top) + ',' + IntToStr(R.Right) + ',' +
  511.     IntToStr(R.Bottom);
  512. end;
  513. function ReadRect;
  514. var
  515.   S: String;
  516. begin
  517.   S := IniFile.ReadString(Section, Ident, '0,0,0,0');
  518.   Result := GetRect(S);
  519. end;
  520. function ReadPoint;
  521. var
  522.   S: String;
  523. begin
  524.   S := IniFile.ReadString(Section, Ident, '0,0');
  525.   Result := GetPoint(S);
  526. end;
  527. function ReadBoolean;
  528. var
  529.   I: Integer;
  530. begin
  531.   I := IniFile.ReadInteger(Section, Ident, 0);
  532.   Result := I = 1;
  533. end;
  534. function ReadFontStyles;
  535. var
  536.   FS: TFontStyles;
  537.   S: String;
  538. begin
  539.   S := IniFile.ReadString(Section, Ident, '');
  540.   FS := [];
  541.   if Pos('fsbold', S) <> 0 then FS := FS + [fsBold];
  542.   if Pos('fsitalic', S) <> 0 then FS := FS + [fsItalic];
  543.   if Pos('fsunderline', S) <> 0 then FS := FS + [fsUnderline];
  544.   if Pos('fsstrikeout', S) <> 0 then FS := FS + [fsStrikeOut];
  545.   Result := FS;
  546. end;
  547. procedure ReadStrings;
  548. var
  549.   Count, i: Integer;
  550. begin
  551.   Count := IniFile.ReadInteger(Section, Ident + 'linecount', 0);
  552.   for i := 0 to Count - 1 do
  553.     S.Add(IniFile.ReadString(Section, Ident + 'line' + IntToStr(i), ''));
  554. end;
  555. procedure ReadStrings1;
  556. var
  557.   Count, i: Integer;
  558. begin
  559.   Count := IniFile.ReadInteger(Section, Ident + 'count', 0);
  560.   for i := 0 to Count - 1 do
  561.     S.Add(IniFile.ReadString(Section, IntToStr(i), ''));
  562. end;
  563. procedure WriteRect;
  564. var
  565.   S: String;
  566. begin
  567.   S := IntToStr(R.Left) + ',' + IntToStr(R.Top) + ',' +
  568.        IntToStr(R.Right) + ',' + IntToStr(R.Bottom);
  569.   IniFile.WriteString(Section, Ident, S);
  570. end;
  571. procedure WritePoint;
  572. var
  573.   S: String;
  574. begin
  575.   S := IntToStr(P.X) + ',' + IntToStr(P.Y);
  576.   IniFile.WriteString(Section, Ident, S);
  577. end;
  578. procedure WriteBoolean;
  579. var
  580.   I: Integer;
  581. begin
  582.   if B then I := 1 else I := 0;
  583.   IniFile.WriteInteger(Section, Ident, I);
  584. end;
  585. procedure WriteFontStyles;
  586. var
  587.   S: String;
  588. begin
  589.   S := '';
  590.   if fsBold in FS then S := S + 'fsbold';
  591.   if fsItalic in FS
  592.   then
  593.     begin
  594.       if Length(S) > 0 then S := S + ',';
  595.       S := S + 'fsitalic';
  596.     end;
  597.   if fsUnderline in FS
  598.   then
  599.     begin
  600.       if Length(S) > 0 then S := S + ',';
  601.       S := S + 'fsunderline';
  602.     end;
  603.   if fsStrikeOut in FS
  604.   then
  605.     begin
  606.       if Length(S) > 0 then S := S + ',';
  607.       S := S + 'fsstrikeout';
  608.     end;
  609.   IniFile.WriteString(Section, Ident, S);
  610. end;
  611. procedure WriteStrings;
  612. var
  613.   i: Integer;
  614. begin
  615.   IniFile.WriteInteger(Section, Ident + 'linecount', S.Count);
  616.   for i := 0 to S.Count - 1 do
  617.     IniFile.WriteString(Section, Ident + 'line' + IntToStr(i), S[i]);
  618. end;
  619. procedure WriteStrings1;
  620. var
  621.   i: Integer;
  622. begin
  623.   IniFile.WriteInteger(Section, Ident + 'count', S.Count);
  624.   for i := 0 to S.Count - 1 do
  625.     IniFile.WriteString(Section, IntToStr(i), S[i]);
  626. end;
  627. function ReadAlignment;
  628. var
  629.   S: String;
  630. begin
  631.   S := IniFile.ReadString(Section, Ident, 'tacenter');
  632.   if S = 'tacenter' then Result := taCenter else
  633.   if S = 'taleftjustify' then Result := taLeftJustify else
  634.   Result := taRightJustify;
  635. end;
  636. procedure WriteAlignment;
  637. var
  638.   S: String;
  639. begin
  640.   if A = taCenter then S := 'tacenter' else
  641.   if A = taLeftJustify then S := 'taleftjustify' else
  642.   S := 'tarightjustify';
  643.   IniFile.WriteString(Section, Ident, S);
  644. end;
  645. { TbsFBitmap }
  646. constructor TbsFBitmap.Create(HBmp:Integer);
  647. var
  648.   Bmp:   Windows.TBITMAP;
  649.   memDC: Integer;
  650. begin
  651.   GetObject(hBmp,SizeOf(Bmp),@Bmp);
  652.   Width:=Bmp.bmWidth;
  653.   Height:=Bmp.bmHeight;
  654.   Size:=((Width*3)+(Width mod 4))*Height;
  655.   with bmHeader do
  656.   begin
  657.     biSize:=SizeOf(bmHeader);
  658.     biWidth:=Width;
  659.     biHeight:=-Height;
  660.     biPlanes:=1;
  661.     biBitCount:=24;
  662.     biCompression:=BI_RGB;
  663.   end;
  664.   bmInfo.bmiHeader:=bmHeader;
  665.   Handle:=CreateDIBSection(0,
  666.                  bmInfo,
  667.                  DIB_RGB_COLORS,
  668.                  Bits, 0, 0);
  669.   memDC:=GetDC(0);
  670.   GetDIBits(memDC,hBmp,0,Height,Bits,bmInfo,DIB_RGB_COLORS);
  671.   ReleaseDC(0,memDC);
  672.   Initialize;
  673. end;
  674. destructor TbsFBitmap.Destroy;
  675. begin
  676.   DeleteDC(hDC);
  677.   DeleteObject(Handle);
  678.   FreeMem(Pixels);
  679.   inherited;
  680. end;
  681. procedure TbsFBitmap.Initialize;
  682. var
  683.   x,i: Integer;
  684. begin
  685.   GetMem(Pixels,Height*SizeOf(PBLine));
  686.   RowInc:=(Width*3)+Width mod 4;
  687.   Gap:=Width mod 4;
  688.   Size:=RowInc*Height;
  689.   x:=Integer(Bits);
  690.   for i:=0 to Height-1 do
  691.   begin
  692.     Pixels[i]:=Pointer(x);
  693.     Inc(x,RowInc);
  694.   end;
  695.   hDC:=CreateCompatibleDC(0);
  696.   SelectObject(hDC,Handle);
  697. end;
  698. // Region convert
  699. function CreateRgnFromBmp(B: TBitmap; XO, YO: Integer; var RgnData: PRgnData): integer;
  700. const
  701.   max = 10000;
  702. var
  703.   j, i, i1: integer;
  704.   C: TFBColor;
  705.   FB: TbsFBitmap;
  706.   Rts: array [0..max] of TRect;
  707.   Count: integer;
  708. begin
  709.   Result := 0;
  710.   If B.Empty Then Exit;
  711.   Count := 0;
  712.   FB := TbsFBitmap.Create(B.Handle);
  713.   for j := 0 to FB.Height - 1 do
  714.   begin
  715.     i := 0;
  716.     while i < FB.Width do
  717.     begin
  718.       C := FB.Pixels[j, i];
  719.       If C.R + C.G + C.B = 0 Then
  720.       begin
  721.         i1 := i;
  722.         C := FB.Pixels[j, i1];
  723.         while C.R + C.G + C.B = 0 do
  724.         begin
  725.           Inc(i1);
  726.           If i1 > FB.Width - 1 Then Break else C := FB.Pixels[j, i1];
  727.         end;
  728.         Rts[Count] := Rect(i + XO, j + YO, i1 + XO, j + 1 + YO);
  729.         Inc(Count);
  730.         i := i1;
  731.         Continue;
  732.       end;
  733.       Inc(i);
  734.     end;
  735.   end;
  736.   FB.Free;
  737.   // Make Region data
  738.   Result := Count*SizeOf(TRect);
  739.   GetMem(Rgndata, SizeOf(TRgnDataHeader)+Result);
  740.   FillChar(Rgndata^, SizeOf(TRgnDataHeader)+Result, 0);
  741.   RgnData^.rdh.dwSize := SizeOf(TRgnDataHeader);
  742.   RgnData^.rdh.iType := RDH_RECTANGLES;
  743.   RgnData^.rdh.nCount := Count;
  744.   RgnData^.rdh.nRgnSize := 0;
  745.   RgnData^.rdh.rcBound := Rect(0 + XO, 0 + YO, B.Width + XO, B.Height + YO);
  746.   // Update New Region
  747.   Move(Rts, RgnData^.Buffer, Result);
  748.   Result := SizeOf(TRgnDataHeader)+Count*SizeOf(TRect);
  749. end;
  750. procedure WriteStringToStream(Str: String; S: TStream);
  751. var
  752.   L: Integer;
  753. begin
  754.   L := Length(Str);
  755.   S.Write(L, SizeOf(Integer));
  756.   S.Write(Pointer(Str)^, L);
  757. end;
  758. procedure ReadStringFromStream(var Str: String; S: TStream);
  759. var
  760.   L: Integer;
  761. begin
  762.   L := 0;
  763.   S.Read(L, SizeOf(Integer));
  764.   SetLength(Str, L);
  765.   S.Read(Pointer(Str)^, L);
  766. end;
  767. procedure CreateHSkinImage;
  768. var
  769.   X, XCnt, w, XO: Integer;
  770. begin
  771.   B.Width := AW;
  772.   B.Height := RectHeight(R);
  773.   with B.Canvas do
  774.   begin
  775.     if LO <> 0 then
  776.        CopyRect(Rect(0, 0, LO, B.Height), SB.Canvas,
  777.                 Rect(R.Left, R.Top, R.Left + LO, R.Bottom));
  778.     if RO <> 0 then
  779.        CopyRect(Rect(B.Width - RO, 0, B.Width, B.Height),
  780.                 SB.Canvas,
  781.                 Rect(R.Right - RO, R.Top, R.Right, R.Bottom));
  782.     Inc(R.Left, LO);
  783.     Dec(R.Right, RO);
  784.     w := RectWidth(R);
  785.     if w = 0 then w := 1;
  786.     XCnt := (B.Width - LO - RO) div w;
  787.     for X := 0 to XCnt do
  788.     begin
  789.       if LO + X * w + w > B.Width - RO
  790.       then XO := LO + X * w + w - (B.Width - RO)
  791.       else XO := 0;
  792.       B.Canvas.CopyRect(Rect(LO + X * w, 0, LO + X * w + w - XO,
  793.                         B.Height),
  794.                         SB.Canvas,
  795.                         Rect(R.Left, R.Top, R.Right - XO, R.Bottom));
  796.     end;
  797.   end;
  798. end;
  799. procedure CreateHSkinImage2;
  800. var
  801.   X, XCnt, w, XO: Integer;
  802. begin
  803.   B.Width := AW;
  804.   B.Height := RectHeight(R);
  805.   with B.Canvas do
  806.   begin
  807.     if LO <> 0 then
  808.        CopyRect(Rect(0, 0, LO, B.Height), SB.Canvas,
  809.                 Rect(R.Left, R.Top, R.Left + LO, R.Bottom));
  810.     Inc(R.Left, LO);
  811.     Dec(R.Right, RO);
  812.     w := RectWidth(R);
  813.     if w = 0 then w := 1;
  814.     XCnt := (B.Width - LO) div w;
  815.     for X := 0 to XCnt do
  816.     begin
  817.       if LO + X * w + w > B.Width
  818.       then XO := LO + X * w + w - B.Width
  819.       else XO := 0;
  820.       B.Canvas.CopyRect(Rect(LO + X * w, 0, LO + X * w + w - XO,
  821.                         B.Height),
  822.                         SB.Canvas,
  823.                         Rect(R.Left, R.Top, R.Right - XO, R.Bottom));
  824.     end;
  825.   end;
  826. end;
  827. procedure CreateVSkinImage;
  828. var
  829.   Y, YCnt, h, YO: Integer;
  830. begin
  831.   B.Width := RectWidth(R);
  832.   B.Height := AH;
  833.   with B.Canvas do
  834.   begin
  835.     if TpO <> 0 then
  836.        CopyRect(Rect(0, 0, B.Width, TpO), SB.Canvas,
  837.                 Rect(R.Left, R.Top, R.Right, R.Top + TpO));
  838.     if BO <> 0 then
  839.        CopyRect(Rect(0, B.Height - BO, B.Width, B.Height),
  840.                 SB.Canvas,
  841.                 Rect(R.Left, R.Bottom - BO, R.Right, R.Bottom));
  842.     Inc(R.Top, TpO);
  843.     Dec(R.Bottom, BO);
  844.     h := RectHeight(R);
  845.     if H <> 0 
  846.     then 
  847.       YCnt := (B.Height - TpO - BO) div h
  848.     else
  849.       YCnt := 0;
  850.     for Y := 0 to YCnt do
  851.     begin
  852.       if TpO + Y * h + h > B.Height - BO
  853.       then YO := TpO + Y * h + h - (B.Height - BO)
  854.       else YO := 0;
  855.       B.Canvas.CopyRect(
  856.         Rect(0, TpO + Y * h, B.Width, TpO + Y * h + h - YO),
  857.         SB.Canvas,
  858.         Rect(R.Left, R.Top, R.Right, R.Bottom - YO));
  859.     end;
  860.   end;
  861. end;
  862. procedure CreateSkinImage;
  863. var
  864.   w, h, rw, rh: Integer;
  865.   X, Y, XCnt, YCnt: Integer;
  866.   XO, YO: Integer;
  867. begin
  868.   B.Width := AW;
  869.   B.Height := AH;
  870.   if (RBPt.X - LTPt.X  = 0) or
  871.      (RBPt.Y - LTPt.Y = 0) or SB.Empty then  Exit;
  872.   with B.Canvas do
  873.   begin
  874.     // Draw lines
  875.     // top
  876.     w := RTPt.X - LTPt.X;
  877.     XCnt := (NewRTPt.X - NewLTPt.X) div (RTPt.X - LTPt.X);
  878.     for X := 0 to XCnt do
  879.     begin
  880.       if NewLTPt.X + X * w + w > NewRTPt.X
  881.       then XO := NewLTPt.X + X * w + w - NewRTPt.X else XO := 0;
  882.       CopyRect(Rect(NewLTPt.X + X * w, 0, NewLTPt.X + X * w + w - XO, NewClRect.Top),
  883.                SB.Canvas, Rect(R.Left + LTPt.X, R.Top,
  884.                  R.Left + RTPt.X - XO, R.Top + ClRect.Top));
  885.     end;
  886.     // bottom
  887.     w := RBPt.X - LBPt.X;
  888.     XCnt := (NewRBPt.X - NewLBPt.X) div (RBPt.X - LBPt.X);
  889.     for X := 0 to XCnt do
  890.     begin
  891.       if NewLBPt.X + X * w + w > NewRBPt.X
  892.       then XO := NewLBPt.X + X * w + w - NewRBPt.X else XO := 0;
  893.       CopyRect(Rect(NewLBPt.X + X * w, NewClRect.Bottom, NewLBPt.X + X * w + w - XO, AH),
  894.                SB.Canvas, Rect(R.Left + LBPt.X, R.Top + ClRect.Bottom,
  895.                  R.Left + RBPt.X - XO, R.Bottom));
  896.     end;
  897.     // left
  898.     w := NewClRect.Left;
  899.     h := LBPt.Y - LTPt.Y;
  900.     YCnt := (NewLBPt.Y - NewLTPt.Y) div h;
  901.     for Y := 0 to YCnt do
  902.     begin
  903.       if NewLTPt.Y + Y * h + h > NewLBPt.Y
  904.       then YO := NewLTPt.Y + Y * h + h - NewLBPt.Y else YO := 0;
  905.       CopyRect(Rect(0, NewLTPt.Y + Y * h, w, NewLTPt.Y + Y * h + h - YO),
  906.                SB.Canvas,
  907.                Rect(R.Left, R.Top + LTPt.Y, R.Left + w, R.Top + LBPt.Y - YO));
  908.     end;
  909.     // right
  910.     h := RBPt.Y - RTPt.Y;
  911.     YCnt := (NewRBPt.Y - NewRTPt.Y) div h;
  912.     for Y := 0 to YCnt do
  913.     begin
  914.       if NewRTPt.Y + Y * h + h > NewRBPt.Y
  915.       then YO := NewRTPt.Y + Y * h + h - NewRBPt.Y else YO := 0;
  916.       CopyRect(Rect(NewClRect.Right, NewRTPt.Y + Y * h,
  917.                     AW, NewRTPt.Y + Y * h + h - YO),
  918.                SB.Canvas,
  919.                Rect(R.Left + ClRect.Right, R.Top + RTPt.Y,
  920.                  R.Right, R.Top + RBPt.Y - YO));
  921.     end;
  922.     // Draw corners
  923.     // lefttop
  924.     CopyRect(Rect(0, 0, NewLTPt.X, NewClRect.Top),
  925.              SB.Canvas, Rect(R.Left, R.Top,
  926.                              R.Left + LTPt.X, R.Top + ClRect.Top));
  927.     CopyRect(Rect(0, NewClRect.Top, NewClRect.Left, NewLTPt.Y),
  928.              SB.Canvas, Rect(R.Left, R.Top + ClRect.Top,
  929.                              R.Left + ClRect.left, R.Top + LTPT.Y));
  930.     //topright
  931.     CopyRect(Rect(NewRTPt.X, 0, AW, NewClRect.Top), SB.Canvas,
  932.              Rect(R.Left + RTPt.X, R.Top,  R.Right, R.Top + ClRect.Top));
  933.     CopyRect(Rect(NewClRect.Right, NewClRect.Top, AW, NewRTPt.Y), SB.Canvas,
  934.              Rect(R.Left + ClRect.Right, R.Top + ClRect.Top,
  935.              R.Right, R.Top + RTPt.Y));
  936.     //leftbottom
  937.     CopyRect(Rect(0, NewLBPt.Y, NewClRect.Left, AH), SB.Canvas,
  938.              Rect(R.Left, R.Top + LBPt.Y, R.Left + ClRect.Left, R.Bottom));
  939.     CopyRect(Rect(NewClRect.Left, NewClRect.Bottom, NewLBPt.X, AH), SB.Canvas,
  940.              Rect(R.Left + ClRect.Left, R.Top + ClRect.Bottom, R.Left + LBPt.X, R.Bottom));
  941.     //rightbottom
  942.     CopyRect(Rect(NewRBPt.X, NewClRect.Bottom, AW, AH), SB.Canvas,
  943.              Rect(R.Left + RBPt.X, R.Top + ClRect.Bottom, R.Right, R.Bottom));
  944.     CopyRect(Rect(NewClRect.Right, NewRBPt.Y, AW, NewClRect.Bottom), SB.Canvas,
  945.              Rect(R.Left + ClRect.Right, R.Top + RBPt.Y,
  946.                   R.Right, R.Top + ClRect.Bottom));
  947.     //Draw client
  948.     w := RectWidth(ClRect);
  949.     h := RectHeight(ClRect);
  950.     rw := RectWidth(NewClRect);
  951.     rh := RectHeight(NewClRect);
  952.     if DrawClient
  953.     then
  954.       begin
  955.         // Draw client area
  956.         XCnt := rw div w;
  957.         YCnt := rh div h;
  958.         for X := 0 to XCnt do
  959.         for Y := 0 to YCnt do
  960.         begin
  961.           if X * w + w > rw then XO := X * W + W - rw else XO := 0;
  962.           if Y * h + h > rh then YO := Y * h + h - rh else YO := 0;
  963.           CopyRect(Rect(NewClRect.Left + X * w, NewClRect.Top + Y * h,
  964.              NewClRect.Left + X * w + w - XO,
  965.              NewClRect.Top + Y * h + h - YO),
  966.              SB.Canvas,
  967.              Rect(R.Left + ClRect.Left, R.Top + ClRect.Top,
  968.              R.Left + ClRect.Right - XO,
  969.              R.Top + ClRect.Bottom - YO));
  970.          end;
  971.     end;
  972.   end;
  973. end;
  974. procedure CreateSkinImage2;
  975. var
  976.   w, h, rw, rh: Integer;
  977.   X, Y, XCnt, YCnt: Integer;
  978.   XO, YO: Integer;
  979.   NCLRect: TRect;
  980. begin
  981.   B.Width := AW;
  982.   B.Height := AH;
  983.   if (RBPt.X - LTPt.X  = 0) or
  984.      (RBPt.Y - LTPt.Y = 0) or SB.Empty then  Exit;
  985.   with B.Canvas do
  986.   begin
  987.     // Draw lines
  988.     // top
  989.     w := RBPt.X - LTPt.X;
  990.     XCnt := (AW - NewLTPt.X) div (RBPt.X - LTPt.X);
  991.     for X := 0 to XCnt do
  992.     begin
  993.       if NewLTPt.X + X * w + w > AW
  994.       then XO := NewLTPt.X + X * w + w - AW else XO := 0;
  995.       CopyRect(Rect(NewLTPt.X + X * w, 0, NewLTPt.X + X * w + w - XO, NewClRect.Top),
  996.                SB.Canvas, Rect(R.Left + LTPt.X, R.Top,
  997.                  R.Left + RTPt.X - XO, R.Top + ClRect.Top));
  998.     end;
  999.     // bottom
  1000.     w := RBPt.X - LBPt.X;
  1001.     XCnt := (AW - NewLBPt.X) div (RBPt.X - LBPt.X);
  1002.     for X := 0 to XCnt do
  1003.     begin
  1004.       if NewLBPt.X + X * w + w > AW
  1005.       then XO := NewLBPt.X + X * w + w - AW else XO := 0;
  1006.       CopyRect(Rect(NewLBPt.X + X * w, NewClRect.Bottom, NewLBPt.X + X * w + w - XO, AH),
  1007.                SB.Canvas, Rect(R.Left + LBPt.X, R.Top + ClRect.Bottom,
  1008.                  R.Left + RBPt.X - XO, R.Bottom));
  1009.     end;
  1010.     // left
  1011.     w := NewClRect.Left;
  1012.     h := LBPt.Y - LTPt.Y;
  1013.     YCnt := (NewLBPt.Y - NewLTPt.Y) div h;
  1014.     for Y := 0 to YCnt do
  1015.     begin
  1016.       if NewLTPt.Y + Y * h + h > NewLBPt.Y
  1017.       then YO := NewLTPt.Y + Y * h + h - NewLBPt.Y else YO := 0;
  1018.       CopyRect(Rect(0, NewLTPt.Y + Y * h, w, NewLTPt.Y + Y * h + h - YO),
  1019.                SB.Canvas,
  1020.                Rect(R.Left, R.Top + LTPt.Y, R.Left + w, R.Top + LBPt.Y - YO));
  1021.     end;
  1022.     // lefttop
  1023.     CopyRect(Rect(0, 0, NewLTPt.X, NewClRect.Top),
  1024.              SB.Canvas, Rect(R.Left, R.Top,
  1025.                              R.Left + LTPt.X, R.Top + ClRect.Top));
  1026.     CopyRect(Rect(0, NewClRect.Top, NewClRect.Left, NewLTPt.Y),
  1027.              SB.Canvas, Rect(R.Left, R.Top + ClRect.Top,
  1028.                              R.Left + ClRect.left, R.Top + LTPT.Y));
  1029.     //leftbottom
  1030.     CopyRect(Rect(0, NewLBPt.Y, NewClRect.Left, AH), SB.Canvas,
  1031.              Rect(R.Left, R.Top + LBPt.Y, R.Left + ClRect.Left, R.Bottom));
  1032.     CopyRect(Rect(NewClRect.Left, NewClRect.Bottom, NewLBPt.X, AH), SB.Canvas,
  1033.              Rect(R.Left + ClRect.Left, R.Top + ClRect.Bottom, R.Left + LBPt.X, R.Bottom));
  1034.     //Draw client
  1035.     NCLRect := NewClRect;
  1036.     NCLRect.Right := AW;
  1037.     w := RectWidth(ClRect);
  1038.     h := RectHeight(ClRect);
  1039.     rw := RectWidth(NCLRect);
  1040.     rh := RectHeight(NCLRect);
  1041.     if DrawClient
  1042.     then
  1043.       begin
  1044.         // Draw client area
  1045.         XCnt := rw div w;
  1046.         YCnt := rh div h;
  1047.         for X := 0 to XCnt do
  1048.         for Y := 0 to YCnt do
  1049.         begin
  1050.           if X * w + w > rw then XO := X * W + W - rw else XO := 0;
  1051.           if Y * h + h > rh then YO := Y * h + h - rh else YO := 0;
  1052.           CopyRect(Rect(NCLRect.Left + X * w, NCLRect.Top + Y * h,
  1053.              NCLRect.Left + X * w + w - XO,
  1054.              NCLRect.Top + Y * h + h - YO),
  1055.              SB.Canvas,
  1056.              Rect(R.Left + ClRect.Left, R.Top + ClRect.Top,
  1057.              R.Left + ClRect.Right - XO,
  1058.              R.Top + ClRect.Bottom - YO));
  1059.          end;
  1060.     end;
  1061.   end;
  1062. end;
  1063. procedure CreateSkinMask;
  1064. var
  1065.   i, j, k: Integer;
  1066.   LWidth, TWidth, RWidth, BWidth: Integer;
  1067.   Ofs: Integer;
  1068.   W, H: Integer;
  1069. begin
  1070.   LWidth := ClRect.Left;
  1071.   TWidth := ClRect.Top;
  1072.   RWidth := FMask.Width - ClRect.Right;
  1073.   BWidth := FMask.Height - ClRect.Bottom;
  1074.   //left
  1075.   W := LWidth;
  1076.   H := RectHeight(NewClRect);
  1077.   if (W > 0) and (H > 0) then
  1078.   begin
  1079.   RMLeft.Width := W;
  1080.   RMLeft.Height := H;
  1081.   j := LBPt.Y - LTPt.Y;
  1082.   with RMLeft.Canvas do
  1083.   begin
  1084.     if j <> 0
  1085.     then
  1086.     for i := 0 to RMLeft.Height div j do
  1087.     begin
  1088.       if i * j + j > RMLeft.Height
  1089.       then Ofs := i * j + j - RMLeft.Height else Ofs := 0;
  1090.       CopyRect(Rect(0, i * j, LWidth, i * j + j - Ofs),
  1091.                FMask.Canvas,
  1092.                Rect(0, LTPt.Y, LWidth, LBPt.Y - Ofs));
  1093.     end;
  1094.     k := LTPt.Y - ClRect.Top;
  1095.     if k > 0 then
  1096.       CopyRect(Rect(0, 0, LWidth, k),
  1097.                FMask.Canvas,
  1098.                Rect(0, ClRect.Top, LWidth, LTPt.Y));
  1099.     k := ClRect.Bottom - LBPt.Y;
  1100.     if k > 0 then
  1101.       CopyRect(Rect(0, RMLeft.Height - k, LWidth, RMLeft.Height),
  1102.                FMask.Canvas,
  1103.                Rect(0, LBPt.Y, LWidth, ClRect.Bottom));
  1104.   end;
  1105.   end;
  1106.   //right
  1107.   W := RWidth;
  1108.   H := RectHeight(NewClRect);
  1109.   if (W > 0) and (H > 0) then
  1110.   begin
  1111.   RMRight.Width  := W;
  1112.   RMRight.Height := H;
  1113.   j := RBPt.Y - RTPt.Y;
  1114.   with RMRight.Canvas do
  1115.   begin
  1116.     if j <> 0 then 
  1117.     for i := 0 to RMRight.Height div j do
  1118.     begin
  1119.       if i * j + j > RMRight.Height
  1120.       then Ofs := i * j + j - RMRight.Height else Ofs := 0;
  1121.       CopyRect(Rect(0, i * j, RWidth, i * j + j - Ofs),
  1122.                FMask.Canvas,
  1123.                Rect(ClRect.Right, RTPt.Y, FMask.Width, RBPt.Y - Ofs));
  1124.     end;           
  1125.     k := RTPt.Y - ClRect.Top;
  1126.     if k > 0 then
  1127.       CopyRect(Rect(0, 0, RWidth, k),
  1128.                FMask.Canvas,
  1129.                Rect(FMask.Width - RWidth, ClRect.Top, FMask.Width, RTPt.Y));
  1130.     k := ClRect.Bottom - RBPt.Y;
  1131.     if k > 0 then
  1132.       CopyRect(Rect(0, RMRight.Height - k, RWidth, RMRight.Height),
  1133.                FMask.Canvas,
  1134.                Rect(FMask.Width - RWidth, RBPt.Y, FMask.Width, CLRect.Bottom));
  1135.   end;
  1136.   end;
  1137.   // top
  1138.   H := TWidth;
  1139.   W := AW;
  1140.   if (W > 0) and (H > 0) then
  1141.   begin
  1142.   j := RTPt.X - LTPt.X;
  1143.   RMTop.Height := H;
  1144.   RMTop.Width := W;
  1145.   with RMTop.Canvas do
  1146.   begin
  1147.     if j <> 0 then
  1148.     for i := 0 to RMTop.Width div j do
  1149.     begin
  1150.       if NewLTPt.X + i * j + j > NewRTPt.X
  1151.       then Ofs := NewLTPt.X + i * j + j - NewRTPt.X else Ofs := 0;
  1152.       CopyRect(Rect(NewLTPt.X + i * j, 0, NewLTPt.X + i * j + j - Ofs, TWidth),
  1153.                FMask.Canvas,
  1154.                Rect(LTPt.X, 0, RTPt.X - Ofs, TWidth));
  1155.     end;
  1156.     CopyRect(Rect(0, 0, LTPt.X, TWidth), FMask.Canvas,
  1157.              Rect(0, 0, LTPt.X, TWidth));
  1158.     CopyRect(Rect(NewRTPt.X, 0, RMTop.Width, TWidth), FMask.Canvas,
  1159.              Rect(RTPt.X, 0, FMask.Width, TWidth));
  1160.   end;
  1161.   end;
  1162.   // bottom
  1163.   W := AW;
  1164.   H := BWidth;
  1165.   if (W > 0) and (H > 0) then
  1166.   begin
  1167.   j := RBPt.X - LBPt.X;
  1168.   RMBottom.Height := H;
  1169.   RMBottom.Width := W;
  1170.   with RMBottom.Canvas do
  1171.   begin
  1172.     if j <> 0 then
  1173.     for i := 0 to RMBottom.Width div j do
  1174.     begin
  1175.       if NewLBPt.X + i * j + j > NewRBPt.X
  1176.       then Ofs := NewLBPt.X + i * j + j - NewRBPt.X else Ofs := 0;
  1177.       CopyRect(Rect(NewLBPt.X + i * j, 0, NewLBPt.X + i * j + j - Ofs, BWidth),
  1178.                FMask.Canvas,
  1179.                Rect(LBPt.X, ClRect.Bottom, RBPt.X - Ofs, FMask.Height));
  1180.     end;
  1181.     CopyRect(Rect(0, 0, LBPt.X, BWidth), FMask.Canvas,
  1182.              Rect(0, ClRect.Bottom, LBPt.X, FMask.Height));
  1183.     CopyRect(Rect(NewRBPt.X, 0, RMBottom.Width, BWidth), FMask.Canvas,
  1184.              Rect(RBPt.X, ClRect.Bottom, FMask.Width, FMask.Height));
  1185.   end;
  1186.   end;
  1187. end;
  1188. procedure CreateSkinSimplyRegion(var FRgn: HRgn; FMask: TBitMap);
  1189. var
  1190.   Size: Integer;
  1191.   RgnData: PRgnData;
  1192. begin
  1193.   Size := CreateRgnFromBmp(FMask, 0, 0, RgnData);
  1194.   FRgn := ExtCreateRegion(nil, Size, RgnData^);
  1195.   FreeMem(RgnData, Size);
  1196. end;
  1197. procedure CreateSkinRegion;
  1198. var
  1199.   RMTop, RMBottom, RMLeft, RMRight: TBitMap;
  1200.   Size: Integer;
  1201.   RgnData: PRgnData;
  1202.   R1, R2, R3, R4: HRGN;
  1203. begin
  1204.   if (NewLtPt.X > NewRTPt.X) or (NewLtPt.Y > NewLBPt.Y)
  1205.   then
  1206.     begin
  1207.       FRgn := 0;
  1208.       Exit;
  1209.     end;
  1210.   RMTop := TBitMap.Create;
  1211.   RMBottom := TBitMap.Create;
  1212.   RMLeft := TBitMap.Create;
  1213.   RMRight := TBitMap.Create;
  1214.   //
  1215.   CreateSkinMask(LTPt, RTPt, LBPt, RBPt, ClRect,
  1216.                NewLtPt, NewRTPt, NewLBPt, NewRBPt, NewClRect,
  1217.                FMask, RMTop, RMLeft, RMRight, RMBottom,
  1218.                AW, AH);
  1219.   //
  1220.   if (RMTop.Width > 0) and (RMTop.Height > 0) 
  1221.   then
  1222.     begin
  1223.       Size := CreateRgnFromBmp(RMTop, 0, 0, RgnData);
  1224.       R1 := ExtCreateRegion(nil, Size, RgnData^);
  1225.       FreeMem(RgnData, Size);
  1226.     end
  1227.   else
  1228.     R1 := 0;
  1229.   if (RMBottom.Width > 0) and (RMBottom.Height > 0)
  1230.   then
  1231.     begin
  1232.       Size := CreateRgnFromBmp(RMBottom, 0, NewClRect.Bottom, RgnData);
  1233.       R2 := ExtCreateRegion(nil, Size, RgnData^);
  1234.       FreeMem(RgnData, Size);
  1235.     end
  1236.   else
  1237.     R2 := 0;
  1238.   if (RMLeft.Width > 0) and (RMleft.Height > 0)
  1239.   then
  1240.     begin
  1241.       Size := CreateRgnFromBmp(RMLeft, 0, NewClRect.Top, RgnData);
  1242.       R3 := ExtCreateRegion(nil, Size, RgnData^);
  1243.       FreeMem(RgnData, Size);
  1244.     end
  1245.   else
  1246.     R3 := 0;
  1247.   if (RMRight.Width > 0) and (RMRight.Height > 0)
  1248.   then
  1249.     begin
  1250.       Size := CreateRgnFromBmp(RMRight, NewClRect.Right, NewClRect.Top, RgnData);
  1251.       R4 := ExtCreateRegion(nil, Size, RgnData^);
  1252.       FreeMem(RgnData, Size);
  1253.     end
  1254.   else
  1255.     R4 := 0;  
  1256.   if not isNullRect(NewClRect)
  1257.   then
  1258.     FRgn := CreateRectRgn(NewClRect.Left, NewClRect.Top,
  1259.                           NewClRect.Right, NewClRect.Bottom)
  1260.   else
  1261.     FRgn := 0;
  1262.   CombineRgn(R1, R1, R2, RGN_OR);
  1263.   CombineRgn(R3, R3, R4, RGN_OR);
  1264.   CombineRgn(R3, R3, R1, RGN_OR);
  1265.   CombineRgn(FRgn, FRgn, R3, RGN_OR);
  1266.   DeleteObject(R1);
  1267.   DeleteObject(R2);
  1268.   DeleteObject(R3);
  1269.   DeleteObject(R4);
  1270.   //
  1271.   RMTop.Free;
  1272.   RMBottom.Free;
  1273.   RMLeft.Free;
  1274.   RMRight.Free;
  1275. end;
  1276. procedure DrawGlyph;
  1277. var
  1278.   B: TBitMap;
  1279.   gw, gh: Integer;
  1280.   GR: TRect;
  1281. begin
  1282.   if FGlyph.Empty then Exit;
  1283.   gw := FGlyph.Width div FNumGlyphs;
  1284.   gh := FGlyph.Height;
  1285.   B := TBitMap.Create;
  1286.   B.Width := gw;
  1287.   B.Height := gh;
  1288.   GR := Rect(gw * (FGlyphNum - 1), 0, gw * FGlyphNum, gh);
  1289.   B.Canvas.CopyRect(Rect(0, 0, gw, gh), FGlyph.Canvas, GR);
  1290.   B.Transparent := True;
  1291.   Cnvs.Draw(X, Y, B);
  1292.   B.Free;
  1293. end;
  1294. procedure CreateSkinBorderImages;
  1295. var
  1296.   XCnt, YCnt, i, X, Y, XO, YO, w, h: Integer;
  1297. begin
  1298.   // top
  1299.   w := AW;
  1300.   h := NewClRect.Top;
  1301.   if (w > 0) and (h > 0) and (RTPt.X - LTPt.X > 0)
  1302.   then
  1303.     begin
  1304.       TopB.Width := w;
  1305.       TopB.Height := h;
  1306.       w := RTPt.X - LTPt.X;
  1307.       XCnt := TopB.Width div w;
  1308.       for X := 0 to XCnt do
  1309.       begin
  1310.         if X * w + w > TopB.Width
  1311.         then XO := X * w + w -  TopB.Width else XO := 0;
  1312.         with TopB.Canvas do
  1313.         begin
  1314.           CopyRect(Rect(X * w, 0, X * w + w - XO, h),
  1315.                    SB.Canvas,
  1316.                    Rect(R.Left + LTPt.X, R.Top,
  1317.                    R.Left + RTPt.X - XO, R.Top + h));
  1318.         end;
  1319.       end;
  1320.       with TopB.Canvas do
  1321.       begin
  1322.         CopyRect(Rect(0, 0, NewLTPt.X, h), SB.Canvas,
  1323.                  Rect(R.Left, R.Top, R.Left + LTPt.X, R.Top + h));
  1324.         CopyRect(Rect(NewRTPt.X, 0, TopB.Width, h), SB.Canvas,
  1325.                  Rect(R.Left + RTPt.X, R.Top, R.Right, R.Top + h));
  1326.       end;
  1327.     end;
  1328.   // bottom
  1329.   w := AW;
  1330.   h := AH - NewClRect.Bottom;
  1331.   if (w > 0) and (h > 0) and (RBPt.X - LBPt.X > 0)
  1332.   then
  1333.     begin
  1334.       BottomB.Width := w;
  1335.       BottomB.Height := h;
  1336.       w := RBPt.X - LBPt.X;
  1337.       XCnt := BottomB.Width div w;
  1338.       for X := 0 to XCnt do
  1339.       begin
  1340.         if X * w + w > BottomB.Width
  1341.         then XO := X * w + w -  BottomB.Width else XO := 0;
  1342.           with BottomB.Canvas do
  1343.           begin
  1344.             CopyRect(Rect(X * w, 0, X * w + w - XO, h),
  1345.                      SB.Canvas,
  1346.                      Rect(R.Left + LBPt.X, R.Bottom - h,
  1347.                           R.Left + RBPt.X - XO, R.Bottom));
  1348.           end;
  1349.       end;
  1350.       with BottomB.Canvas do
  1351.       begin
  1352.         CopyRect(Rect(0, 0, NewLBPt.X, h), SB.Canvas,
  1353.                  Rect(R.Left, R.Bottom - h, R.Left + LBPt.X, R.Bottom));
  1354.         CopyRect(Rect(NewRBPt.X, 0, BottomB.Width, h), SB.Canvas,
  1355.                  Rect(R.Left + RBPt.X, R.Bottom - h, R.Right, R.Bottom));
  1356.       end;
  1357.     end;
  1358.   // draw left
  1359.   h := AH - BottomB.Height - TopB.Height;
  1360.   w := NewClRect.Left;
  1361.   if (w > 0) and (h > 0) and (LBPt.Y - LTPt.Y > 0)
  1362.   then
  1363.     begin
  1364.       LeftB.Width := w;
  1365.       LeftB.Height := h;
  1366.       h := LBPt.Y - LTPt.Y;
  1367.       YCnt := LeftB.Height div h;
  1368.       for Y := 0 to YCnt do
  1369.       begin
  1370.         if Y * h + h > LeftB.Height
  1371.         then YO := Y * h + h - LeftB.Height else YO := 0;
  1372.         with LeftB.Canvas do
  1373.           CopyRect(Rect(0, Y * h, w, Y * h + h - YO),
  1374.                    SB.Canvas,
  1375.                    Rect(R.Left, R.Top + LTPt.Y, R.Left + w, R.Top + LBPt.Y - YO));
  1376.       end;
  1377.       with LeftB.Canvas do
  1378.       begin
  1379.         YO := LTPt.Y - ClRect.Top;
  1380.         if YO > 0
  1381.         then
  1382.           CopyRect(Rect(0, 0, w, YO), SB.Canvas,
  1383.                    Rect(R.Left, R.Top + ClRect.Top,
  1384.                    R.Left + w, R.Top + LTPt.Y));
  1385.         YO :=  ClRect.Bottom - LBPt.Y;
  1386.         if YO > 0
  1387.         then
  1388.           CopyRect(Rect(0, LeftB.Height - YO, w, LeftB.Height),
  1389.                    SB.Canvas,
  1390.                    Rect(R.Left, R.Top + LBPt.Y,
  1391.                    R.Left + w, R.Top + ClRect.Bottom));
  1392.       end;
  1393.     end;
  1394.    // draw right
  1395.   h := AH - BottomB.Height - TopB.Height;
  1396.   w := AW - NewClRect.Right;
  1397.   if (w > 0) and (h > 0) and (RBPt.Y - RTPt.Y > 0)
  1398.   then
  1399.     begin
  1400.       RightB.Width := w;
  1401.       RightB.Height := h;
  1402.       h := RBPt.Y - RTPt.Y;
  1403.       YCnt := RightB.Height div h;
  1404.       for Y := 0 to YCnt do
  1405.       begin
  1406.         if Y * h + h > RightB.Height
  1407.         then YO := Y * h + h - RightB.Height else YO := 0;
  1408.         with RightB.Canvas do
  1409.         CopyRect(Rect(0, Y * h, w, Y * h + h - YO),
  1410.                  SB.Canvas,
  1411.                  Rect(R.Left + ClRect.Right, R.Top + RTPt.Y,
  1412.                       R.Right, R.Top + RBPt.Y - YO));
  1413.       end;
  1414.       with RightB.Canvas do
  1415.       begin
  1416.         YO := RTPt.Y - ClRect.Top;
  1417.         if YO > 0
  1418.         then
  1419.           CopyRect(Rect(0, 0, w, YO), SB.Canvas,
  1420.                    Rect(R.Left + ClRect.Right, R.Top + ClRect.Top,
  1421.                    R.Right, R.Top + RTPt.Y));
  1422.                   
  1423.         YO :=  ClRect.Bottom - RBPt.Y;
  1424.         if YO > 0
  1425.         then
  1426.           CopyRect(Rect(0, RightB.Height - YO, w, RightB.Height),
  1427.                    SB.Canvas,
  1428.                    Rect(R.Left + ClRect.Right, R.Top + RBPt.Y,
  1429.                         R.Right, R.Top + ClRect.Bottom));
  1430.       end;
  1431.     end;
  1432. end;
  1433. procedure DrawRCloseImage(C: TCanvas; R: TRect; Color: TColor);
  1434. var
  1435.   X, Y: Integer;
  1436. begin
  1437.   X := R.Left + RectWidth(R) div 2 - 5;
  1438.   Y := R.Top + RectHeight(R) div 2 - 5;
  1439.   DrawCloseImage(C, X, Y, Color);
  1440. end;
  1441. procedure DrawCloseImage(C: TCanvas; X, Y: Integer; Color: TColor);
  1442. begin
  1443.   with C do
  1444.   begin
  1445.     Pen.Color := Color;
  1446.     MoveTo(X + 1, Y + 1); LineTo(X + 9, Y + 9);
  1447.     MoveTo(X + 9, Y + 1); LineTo(X + 1, Y + 9);
  1448.     MoveTo(X + 2, Y + 1); LineTo(X + 10, Y + 9);
  1449.     MoveTo(X + 8, Y + 1); LineTo(X, Y + 9);
  1450.   end;
  1451. end;
  1452. procedure DrawSysMenuImage(C: TCanvas; X, Y: Integer; Color: TColor);
  1453. begin
  1454.   with C do
  1455.   begin                
  1456.     Pen.Color := Color;
  1457.     Brush.Style := bsClear;
  1458.     Rectangle(X + 1, Y + 3, X + 9, Y + 6);
  1459.   end;
  1460. end;
  1461. procedure DrawMinimizeImage(C: TCanvas; X, Y: Integer; Color: TColor);
  1462. begin
  1463.   with C do
  1464.   begin
  1465.     Pen.Color := Color;
  1466.     MoveTo(X + 1, Y + 8); LineTo(X + 9, Y + 8);
  1467.     MoveTo(X + 1, Y + 9); LineTo(X + 9, Y + 9);
  1468.   end;
  1469. end;
  1470. procedure DrawMaximizeImage(C: TCanvas; X, Y: Integer; Color: TColor);
  1471. begin
  1472.   with C do
  1473.   begin
  1474.     Brush.Style := bsClear;
  1475.     Pen.Color := Color;
  1476.     Rectangle(X, Y, X + 11, Y + 10);
  1477.     Rectangle(X, Y, X + 11, Y + 2);
  1478.   end;
  1479. end;
  1480. procedure DrawRestoreImage(C: TCanvas; X, Y: Integer; Color: TColor);
  1481. begin
  1482.   with C do
  1483.   begin
  1484.     Brush.Style := bsClear;
  1485.     Pen.Color := Color;
  1486.     Rectangle(X + 2, Y, X + 10, Y + 6);
  1487.     Rectangle(X + 2, Y, X + 10, Y + 2);
  1488.     Rectangle(X, Y + 4, X + 7, Y + 10);
  1489.     Rectangle(X, Y + 4, X + 7, Y + 6);
  1490.   end;
  1491. end;
  1492. procedure DrawRestoreRollUpImage(C: TCanvas; X, Y: Integer; Color: TColor);
  1493. begin
  1494.   with C do
  1495.   begin
  1496.     Pen.Color := Color;
  1497.     MoveTo(X + 5, Y + 2); LineTo(X + 5, Y + 2);
  1498.     MoveTo(X + 4, Y + 3); LineTo(X + 6, Y + 3);
  1499.     MoveTo(X + 3, Y + 4); LineTo(X + 7, Y + 4);
  1500.     MoveTo(X + 2, Y + 5); LineTo(X + 8, Y + 5);
  1501.     MoveTo(X + 1, Y + 6); LineTo(X + 9, Y + 6);
  1502.   end;
  1503. end;
  1504. procedure DrawRollUpImage(C: TCanvas; X, Y: Integer; Color: TColor);
  1505. begin
  1506.   with C do
  1507.   begin
  1508.     Pen.Color := Color;
  1509.     MoveTo(X + 1, Y + 6); LineTo(X + 9, Y + 6);
  1510.     MoveTo(X + 2, Y + 5); LineTo(X + 8, Y + 5);
  1511.     MoveTo(X + 3, Y + 4); LineTo(X + 7, Y + 4);
  1512.     MoveTo(X + 4, Y + 3); LineTo(X + 6, Y + 3);
  1513.     MoveTo(X + 5, Y + 2); LineTo(X + 5, Y + 2);
  1514.   end;
  1515. end;
  1516. procedure DrawMTImage(C: TCanvas; X, Y: Integer; Color: TColor);
  1517. begin
  1518.   with C do
  1519.   begin
  1520.     Pen.Color := Color;
  1521.     Brush.Color := Color;
  1522.     Rectangle(X + 2, Y + 2, X + 7, Y + 7);
  1523.   end;
  1524. end;
  1525. function ExtractDay(ADate: TDateTime): Word;
  1526. var
  1527.   M, Y: Word;
  1528. begin
  1529.   DecodeDate(ADate, Y, M, Result);
  1530. end;
  1531. function ExtractMonth(ADate: TDateTime): Word;
  1532. var
  1533.   D, Y: Word;
  1534. begin
  1535.   DecodeDate(ADate, Y, Result, D);
  1536. end;
  1537. function ExtractYear(ADate: TDateTime): Word;
  1538. var
  1539.   D, M: Word;
  1540. begin
  1541.   DecodeDate(ADate, Result, M, D);
  1542. end;
  1543. function IsLeapYear(AYear: Integer): Boolean;
  1544. begin
  1545.   Result := (AYear mod 4 = 0) and ((AYear mod 100 <> 0) or (AYear mod 400 = 0));
  1546. end;
  1547. function DaysPerMonth(AYear, AMonth: Integer): Integer;
  1548. const
  1549.   DaysInMonth: array[1..12] of Integer =
  1550.     (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
  1551. begin
  1552.   Result := DaysInMonth[AMonth];
  1553.   if (AMonth = 2) and IsLeapYear(AYear) then Inc(Result); { leap-year Feb is special }
  1554. end;
  1555. end.