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

Delphi控件源码

开发平台:

Delphi

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