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

Delphi控件源码

开发平台:

Delphi

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