VrSysUtils.pas
上传用户:hbszzs
上传日期:2008-08-20
资源大小:628k
文件大小:30k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {*****************************************************}
  2. {                                                     }
  3. {     Varian Component Workshop                       }
  4. {                                                     }
  5. {     Varian Software NL (c) 1996-2000                }
  6. {     All Rights Reserved                             }
  7. {                                                     }
  8. {*****************************************************}
  9. unit VrSysUtils;
  10. {$I VRLIB.INC}
  11. interface
  12. uses
  13.   Windows, Classes, SysUtils, Graphics, Controls, Messages,
  14.   VrTypes, Forms;
  15. type
  16.   TVrGradDirection = (gdUpDown, gdLeftRight, gdChord1, gdChord2);
  17. function SolveForX(Y, Z: Longint): Longint;
  18. function SolveForY(X, Z: Longint): Longint;
  19. procedure FreeObject(AObject: TObject);
  20. function MinIntVal(X, Y: Integer): Integer;
  21. function MaxIntVal(X, Y: Integer): Integer;
  22. function InRange(Value, X, Y: Integer): boolean;
  23. procedure AdjustRange(var Value: Integer; X, Y: Integer);
  24. function Percent(a, b: Integer): Integer;
  25. function WidthOf(const R: TRect): Integer;
  26. function HeightOf(const R: TRect): Integer;
  27. procedure AllocateBitmaps(var Items: array of TBitmap);
  28. procedure DeallocateBitmaps(var Items: array of TBitmap);
  29. function Color2RGB(Color: TColor): Longint;
  30. function AdjustColor(Color: TColor; Value:Integer): TColor;
  31. procedure ClearBitmapCanvas(R: TRect; Bitmap: TBitmap; Color: TColor);
  32. procedure DrawShape(Canvas: TCanvas; Shape: TVrShapeType; X, Y, W, H: Integer);
  33. procedure CalcTextBounds(Canvas: TCanvas; const Client: TRect;
  34.   var TextBounds: TRect; const Caption: string);
  35. procedure DrawButtonText(Canvas: TCanvas; const Caption: string;
  36.   TextBounds: TRect; Enabled: Boolean);
  37. function CreateDitherPattern(Light, Face: TColor): TBitmap;
  38. procedure CalcImageTextLayout(Canvas: TCanvas; const Client: TRect;
  39.   const Offset: TPoint; const Caption: string; Layout: TVrImageTextLayout;
  40.   Margin, Spacing: Integer; ImageSize: TPoint; var ImagePos: TPoint;
  41.   var TextBounds: TRect);
  42. procedure DrawOutline3D(Canvas: TCanvas; var Rect: TRect;
  43.   TopColor, BottomColor: TColor; Width: Integer);
  44. procedure DrawFrame3D(Canvas: TCanvas; var Rect: TRect;
  45.   TopColor, BottomColor: TColor; Width: Integer);
  46. procedure GetRGB(Color: TColor; var R, G, B: Byte);
  47. procedure DrawGradient(Canvas: TCanvas; const Rect: TRect; StartColor,
  48.   TargetColor: TColor; Orientation: TVrOrientation; LineWidth: Integer);
  49. procedure DrawGradientExt(Canvas: TCanvas; const Rect: TRect; StartColor,
  50.   EndColor: TColor; Direction: TVrGradDirection; ColorWidth: Integer);
  51. procedure CopyParentImage(Control: TControl; Dest: TCanvas);
  52. function GetOwnerControl(Component: TComponent): TComponent;
  53. procedure SetCanvasTextAngle(Canvas: TCanvas; Angle: Word);
  54. procedure CanvasTextOutAngle(Canvas: TCanvas; X, Y: Integer;
  55.   Angle: Word; const Text: string);
  56. function GetTextSize(Canvas: TCanvas; const Text: string): TPoint;
  57. procedure Draw3DText(Canvas: TCanvas; X, Y: Integer; const Text: String;
  58.   HighEdge, LowEdge: TColor);
  59. procedure DrawShadowTextExt(Canvas: TCanvas; X, Y : Integer;
  60.   const Text: string; ShadowColor: TColor; SX, SY: Integer);
  61. procedure StretchPaintOnText(Dest: TCanvas; DestRect: TRect; X, Y: Integer;
  62.   const Text: string; Bitmap: TBitmap; Angle: Word);
  63. procedure DrawOutlinedText(Canvas: TCanvas; X, Y : Integer;
  64.   const Text: string; Color: TColor; Depth: Integer);
  65. procedure DrawRasterPattern(Canvas: TCanvas; Rect: TRect;
  66.   ForeColor, BackColor: TColor; PixelSize, Spacing: Integer);
  67. procedure StretchPaintOnRasterPattern(Dest: TCanvas; Rect: TRect; Image: TBitmap;
  68.   ForeColor, BackColor: TColor; PixelSize, Spacing: Integer);
  69. procedure BitmapToLCD(Dest: TBitmap; Source: TBitmap;
  70.   ForeColor, BackColor: TColor; PixelSize, Spacing: Integer);
  71. procedure DrawTiledBitmap(Canvas: TCanvas; const Rect: TRect; Glyph: TBitmap);
  72. function BitmapRect(Bitmap: TBitmap): TRect;
  73. procedure ChangeBitmapColor(Bitmap: TBitmap; FromColor, ToColor: TColor);
  74. procedure DrawBitmap(Canvas: TCanvas; DestRect: TRect;
  75.   Bitmap: TBitmap; SourceRect: TRect; Transparent: Boolean; TransColor: TColor);
  76. implementation
  77. { This function solves for x in the equation "x is y% of z". }
  78. function SolveForX(Y, Z: Longint): Longint;
  79. begin
  80.   Result := Trunc( Z * (Y * 0.01) );
  81. end;
  82. { This function solves for y in the equation "x is y% of z". }
  83. function SolveForY(X, Z: Longint): Longint;
  84. begin
  85.   if Z = 0 then Result := 0
  86.   else Result := Trunc( (X * 100.0) / Z );
  87. end;
  88. {$HINTS OFF}
  89. procedure FreeObject(AObject: TObject);
  90. begin
  91.   if AObject <> nil then
  92.   begin
  93.     AObject.Free;
  94.     AObject := nil;
  95.   end;
  96. end;
  97. {$HINTS ON}
  98. function MinIntVal(X, Y: Integer): Integer;
  99. begin
  100.   Result := X;
  101.   if X > Y then Result := Y;
  102. end;
  103. function MaxIntVal(X, Y: Integer): Integer;
  104. begin
  105.   Result := Y;
  106.   if X > Y then Result := X;
  107. end;
  108. function InRange(Value, X, Y: Integer): boolean;
  109. begin
  110.   Result := (Value >= X) and (Value <= Y);
  111. end;
  112. procedure AdjustRange(var Value: Integer; X, Y: Integer);
  113. begin
  114.   if Value < X then Value := X
  115.   else if Value > Y then Value := Y;
  116. end;
  117. function Percent(a, b: Integer): Integer;
  118. begin
  119.   Result := Trunc((a / b)*100);
  120. end;
  121. function WidthOf(const R: TRect): Integer;
  122. begin
  123.   Result := R.Right - R.Left;
  124. end;
  125. function HeightOf(const R: TRect): Integer;
  126. begin
  127.   Result := R.Bottom - R.Top;
  128. end;
  129. procedure AllocateBitmaps(var Items: array of TBitmap);
  130. var
  131.   I: Integer;
  132. begin
  133.   for I := Low(Items) to High(Items) do
  134.     Items[I] := TBitmap.Create;
  135. end;
  136. procedure DeallocateBitmaps(var Items: array of TBitmap);
  137. var
  138.   I: Integer;
  139. begin
  140.   for I := Low(Items) to High(Items) do
  141.     if Items[I] <> nil then
  142.     begin
  143.       Items[I].Free;
  144.       Items[I] := nil;
  145.     end;
  146. end;
  147. type
  148.   TRGBMap = packed record
  149.     case boolean of
  150.       TRUE:  (RGBVal: DWORD);
  151.       FALSE: (Red, Green, Blue, Unused: byte);
  152.   end;
  153.   TParentControl = class(TWinControl);
  154. { CorrectColor }
  155. function CorrectColor(C: Real) : Integer;
  156. begin
  157.   Result := Round(C);
  158.   if Result > 255 then Result := 255
  159.   else if Result < 0 then Result := 0;
  160. end;
  161. { ERGB }
  162. function ERGB(R, G, B: Real): TColor;
  163. begin
  164.   Result := RGB(CorrectColor(R), CorrectColor(G), CorrectColor(B));
  165. end;
  166. { Color2RGB }
  167. function Color2RGB(Color: TColor): Longint;
  168. begin
  169.   if Color < 0 then
  170.     Result := GetSysColor(Color and $000000FF)
  171.   else Result := Color;
  172. end;
  173. { AdjustColor }
  174. function AdjustColor(Color: TColor; Value:Integer): TColor;
  175. var
  176.   R, G, B: integer;
  177. begin
  178.   R := GetRValue(ColorToRGB(Color));
  179.   G := GetGValue(ColorToRGB(Color));
  180.   B := GetBValue(ColorToRGB(Color));
  181.   if Value > 0 then
  182.   begin
  183.     if R + Value > 255 then R := 254 else Inc(R, Value);
  184.     if G + Value > 255 then G := 254 else Inc(G, Value);
  185.     if B + Value > 255 then B := 254 else Inc(B, Value);
  186.   end else
  187.   begin
  188.     if R + Value < 0 then R := 1 else Inc(R, Value);
  189.     if G + Value < 0 then G := 1 else Inc(G, Value);
  190.     if B + Value < 0 then B := 1 else Inc(B, Value);
  191.   end;
  192.   Result := RGB(R, G, B);
  193. end;
  194. { DrawGradientHorizontal }
  195. procedure DrawGradientHorizontal(Canvas: TCanvas; const Rect: TRect;
  196.   R1, G1, B1, R2, G2, B2: Integer; LineWidth: Integer);
  197. var
  198.   R, G, B: Real;
  199.   Width, Height, I: Integer;
  200.   ColorRect: TRect;
  201. begin
  202.   Width := WidthOf(Rect);
  203.   Height := HeightOf(Rect);
  204.   ColorRect := Bounds(Rect.Left, Rect.Top, LineWidth, Height);
  205.   R := R1; G := G1; B := B1;
  206.   I := 0;
  207.   while I <= Width do
  208.   begin
  209.     Canvas.Brush.Color := ERGB(R, G, B);
  210.     Canvas.FillRect(ColorRect);
  211.     OffsetRect(ColorRect, LineWidth, 0);
  212.     Inc(I, LineWidth);
  213.     R := R + R2 / Width * LineWidth;
  214.     G := G + G2 / Width * LineWidth;
  215.     B := B + B2 / Width * LineWidth;
  216.   end;
  217. end;
  218. { DrawGradientVertical }
  219. procedure DrawGradientVertical(Canvas: TCanvas; const Rect: TRect;
  220.   R1, G1, B1, R2, G2, B2: Integer; LineWidth: Integer);
  221. var
  222.   R, G, B: Real;
  223.   Width, Height, I: Integer;
  224.   ColorRect: TRect;
  225. begin
  226.   Width := WidthOf(Rect);
  227.   Height := HeightOf(Rect);
  228.   ColorRect := Bounds(Rect.Left, Rect.Top, Width, LineWidth);
  229.   R := R1; G := G1; B := B1;
  230.   I := 0;
  231.   while I <= Height do
  232.   begin
  233.     Canvas.Brush.Color := ERGB(R, G, B);
  234.     Canvas.FillRect(ColorRect);
  235.     OffsetRect(ColorRect, 0, LineWidth);
  236.     Inc(I, LineWidth);
  237.     R := R + R2 / Height * LineWidth;
  238.     G := G + G2 / Height * LineWidth;
  239.     B := B + B2 / Height * LineWidth;
  240.   end;
  241. end;
  242. { DrawGradient }
  243. procedure DrawGradient(Canvas: TCanvas; const Rect: TRect; StartColor,
  244.   TargetColor: TColor; Orientation: TVrOrientation; LineWidth: Integer);
  245. var
  246.   R1,G1,B1: Integer;
  247.   R2,G2,B2: Integer;
  248. begin
  249.   //Implement Top Color
  250.   StartColor := Color2RGB(StartColor);
  251.   R1 := GetRValue(StartColor);
  252.   G1 := GetGValue(StartColor);
  253.   B1 := GetBValue(StartColor);
  254.   //Implement Bottom Color
  255.   TargetColor := Color2RGB(TargetColor);
  256.   R2 := GetRValue(TargetColor) - R1;
  257.   G2 := GetGValue(TargetColor) - G1;
  258.   B2 := GetBValue(TargetColor) - B1;
  259.   case Orientation of
  260.     voVertical:
  261.      DrawGradientVertical(Canvas, Rect, R1, G1, B1, R2, G2, B2, LineWidth);
  262.     voHorizontal:
  263.      DrawGradientHorizontal(Canvas, Rect, R1, G1, B1, R2, G2, B2, LineWidth);
  264.   end;
  265. end;
  266. procedure GetRGB(Color: TColor; var R, G, B: Byte);
  267. begin
  268.   Color := Color2RGB(Color);
  269.   R := GetRValue(Color);
  270.   G := GetGValue(Color);
  271.   B := GetBValue(Color);
  272. end;
  273. procedure DrawGradientExt(Canvas: TCanvas; const Rect: TRect; StartColor,
  274.   EndColor: TColor; Direction: TVrGradDirection; ColorWidth: Integer);
  275. var
  276.   I, LoopEnd: Integer;
  277.   ColorRect: TRect;
  278.   R, G, B: Byte;
  279.   R1, G1, B1, R2, G2, B2: Byte;
  280.   P: TPoint;
  281.   DC: HDC;
  282. begin
  283.   P.X := WidthOf(Rect);
  284.   P.Y := HeightOf(Rect);
  285.   GetRGB(StartColor, R1, G1, B1);
  286.   GetRGB(EndColor, R2, G2, B2);
  287.   case Direction of
  288.   gdLeftRight:
  289.     begin
  290.       ColorRect := Bounds(Rect.Left, Rect.Top, ColorWidth, P.Y);
  291.       I := 0;
  292.       while I <= P.X do
  293.       begin
  294.         R := R1 + I * (R2 - R1) div P.X;
  295.         G := G1 + I * (G2 - G1) div P.X;
  296.         B := B1 + I * (B2 - B1) div P.X;
  297.         Canvas.Brush.Color := RGB(R, G, B);
  298.         FillRect(Canvas.Handle, ColorRect, Canvas.Brush.Handle);
  299.         OffsetRect(ColorRect, ColorWidth, 0);
  300.         Inc(I, ColorWidth);
  301.       end;
  302.     end;
  303.   gdUpDown:
  304.     begin
  305.       ColorRect := Bounds(Rect.Left, Rect.Top, P.X, ColorWidth);
  306.       I := 0;
  307.       while I <= P.Y do
  308.       begin
  309.         R := R1 + I * (R2 - R1) div P.Y;
  310.         G := G1 + I * (G2 - G1) div P.Y;
  311.         B := B1 + I * (B2 - B1) div P.Y;
  312.         Canvas.Brush.Color := RGB(R, G, B);
  313.         FillRect(Canvas.Handle, ColorRect, Canvas.Brush.Handle);
  314.         OffsetRect(ColorRect, 0, ColorWidth);
  315.         Inc(I, ColorWidth);
  316.       end;
  317.     end;
  318.   gdChord1:
  319.     begin
  320.       LoopEnd := P.X + P.Y;
  321.       I := 0;
  322.       Canvas.Pen.Width := ColorWidth;
  323.       while I <= LoopEnd do
  324.       begin
  325.         R := R1 + I * (R2 - R1) div LoopEnd;
  326.         G := G1 + I * (G2 - G1) div LoopEnd;
  327.         B := B1 + I * (B2 - B1) div LoopEnd;
  328.         Canvas.Pen.Color := RGB(R, G, B);
  329.         DC := Canvas.Handle;
  330.         MoveToEx(DC, I, 0, nil);
  331.         LineTo(DC, -1, I);
  332.         Inc(I, ColorWidth);
  333.       end;
  334.     end;
  335.   gdChord2:
  336.     begin
  337.       LoopEnd := P.X + P.Y;
  338.       I := 0;
  339.       Canvas.Pen.Width := ColorWidth;
  340.       while I <= LoopEnd do
  341.       begin
  342.         R := R1 + I *(R2 - R1) div LoopEnd;
  343.         G := G1 + I *(G2 - G1) div LoopEnd;
  344.         B := B1 + I *(B2 - B1) div LoopEnd;
  345.         Canvas.Pen.Color := RGB(R, G, B);
  346.         DC := Canvas.Handle;
  347.         MoveToEx(DC, 0, P.Y - I, nil);
  348.         LineTo(DC, I, P.Y);
  349.         Inc(I, ColorWidth);
  350.       end;
  351.     end;
  352.   end; //case
  353. end;
  354. { DrawShape }
  355. procedure DrawShape(Canvas: TCanvas; Shape: TVrShapeType; X, Y, W, H: Integer);
  356. var
  357.   S: Integer;
  358. begin
  359.   with Canvas do
  360.   begin
  361.     if Pen.Width = 0 then
  362.     begin
  363.       Dec(W);
  364.       Dec(H);
  365.     end;
  366.     if W < H then S := W else S := H;
  367.     if Shape in [stSquare, stRoundSquare, stCircle] then
  368.     begin
  369.       Inc(X, (W - S) div 2);
  370.       Inc(Y, (H - S) div 2);
  371.       W := S;
  372.       H := S;
  373.     end;
  374.     case Shape of
  375.       stRectangle, stSquare:
  376.         Rectangle(X, Y, X + W, Y + H);
  377.       stRoundRect, stRoundSquare:
  378.         RoundRect(X, Y, X + W, Y + H, S div 4, S div 4);
  379.       stCircle, stEllipse:
  380.         Ellipse(X, Y, X + W, Y + H);
  381.     end;
  382.   end;
  383. end;
  384. { CalcTextBounds }
  385. procedure CalcTextBounds(Canvas: TCanvas; const Client: TRect;
  386.   var TextBounds: TRect; const Caption: string);
  387. var
  388.   X, Y: Integer;
  389.   TextSize: TPoint;
  390. begin
  391.   TextBounds := Rect(0, 0, Client.Right - Client.Left, 0);
  392.   DrawText(Canvas.Handle, PChar(Caption), Length(Caption), TextBounds, DT_CALCRECT);
  393.   TextSize := Point(TextBounds.Right - TextBounds.Left,
  394.     TextBounds.Bottom - TextBounds.Top);
  395.   X := (WidthOf(Client) - TextSize.X + 1) div 2;
  396.   Y := (HeightOf(Client) - TextSize.Y + 1) div 2;
  397.   OffsetRect(TextBounds, Client.Left + X, Client.Top + Y);
  398. end;
  399. { DrawButtonText }
  400. procedure DrawButtonText(Canvas: TCanvas; const Caption: string;
  401.   TextBounds: TRect; Enabled: Boolean);
  402. begin
  403.   with Canvas do
  404.   begin
  405.     Brush.Style := bsClear;
  406.     if not Enabled then
  407.     begin
  408.       OffsetRect(TextBounds, 1, 1);
  409.       Font.Color := clBtnHighlight;
  410.       DrawText(Handle, PChar(Caption), Length(Caption), TextBounds, 0);
  411.       OffsetRect(TextBounds, -1, -1);
  412.       Font.Color := clBtnShadow;
  413.       DrawText(Handle, PChar(Caption), Length(Caption), TextBounds, 0);
  414.     end else
  415.       DrawText(Handle, PChar(Caption), Length(Caption), TextBounds,
  416.         DT_CENTER or DT_VCENTER or DT_SINGLELINE);
  417.   end;
  418. end;
  419. { ClearBitmapCanvas }
  420. procedure ClearBitmapCanvas(R: TRect; Bitmap: TBitmap; Color: TColor);
  421. begin
  422.   Bitmap.Width := WidthOf(R);
  423.   Bitmap.Height := HeightOf(R);
  424.   with Bitmap.Canvas do
  425.   begin
  426.     Brush.Color := Color;
  427.     Brush.Style := bsSolid;
  428.     FillRect(R);
  429.   end;
  430. end;
  431. { CreateDitherPattern }
  432. function CreateDitherPattern(Light, Face: TColor): TBitmap;
  433. var
  434.   X, Y: Integer;
  435. begin
  436.   Result := TBitmap.Create;
  437.   Result.Width := 8;
  438.   Result.Height := 8;
  439.   with Result.Canvas do
  440.   begin
  441.     Brush.Color := Face;
  442.     Brush.Style := bsSolid;
  443.     FillRect(Rect(0, 0, Result.Width, Result.Height));
  444.     for Y := 0 to 7 do
  445.       for X := 0 to 7 do
  446.         if (Y mod 2) = (X mod 2) then Pixels[X, Y] := Light;
  447.   end;
  448. end;
  449. { CalcImageTextLayout }
  450. procedure CalcImageTextLayout(Canvas: TCanvas; const Client: TRect;
  451.   const Offset: TPoint; const Caption: string; Layout: TVrImageTextLayout;
  452.   Margin, Spacing: Integer; ImageSize: TPoint; var ImagePos: TPoint;
  453.   var TextBounds: TRect);
  454. var
  455.   TextPos: TPoint;
  456.   ClientSize, TextSize: TPoint;
  457.   TotalSize: TPoint;
  458. begin
  459.   ClientSize := Point(Client.Right - Client.Left, Client.Bottom -
  460.     Client.Top);
  461.   if Length(Caption) > 0 then
  462.   begin
  463.     TextBounds := Rect(0, 0, Client.Right - Client.Left, 0);
  464.     DrawText(Canvas.Handle, PChar(Caption), Length(Caption), TextBounds, DT_CALCRECT);
  465.     TextSize := Point(TextBounds.Right - TextBounds.Left, TextBounds.Bottom -
  466.       TextBounds.Top);
  467.   end
  468.   else
  469.   begin
  470.     TextBounds := Rect(0, 0, 0, 0);
  471.     TextSize := Point(0,0);
  472.   end;
  473.   if Layout in [ImageLeft, ImageRight] then
  474.   begin
  475.     ImagePos.Y := (ClientSize.Y - ImageSize.Y + 1) div 2;
  476.     TextPos.Y := (ClientSize.Y - TextSize.Y + 1) div 2;
  477.   end
  478.   else
  479.   begin
  480.     ImagePos.X := (ClientSize.X - ImageSize.X + 1) div 2;
  481.     TextPos.X := (ClientSize.X - TextSize.X + 1) div 2;
  482.   end;
  483.   if (TextSize.X = 0) or (ImageSize.X = 0) then
  484.     Spacing := 0;
  485.   if Margin = -1 then
  486.   begin
  487.     if Spacing = -1 then
  488.     begin
  489.       TotalSize := Point(ImageSize.X + TextSize.X, ImageSize.Y + TextSize.Y);
  490.       if Layout in [ImageLeft, ImageRight] then
  491.         Margin := (ClientSize.X - TotalSize.X) div 3
  492.       else
  493.         Margin := (ClientSize.Y - TotalSize.Y) div 3;
  494.       Spacing := Margin;
  495.     end
  496.     else
  497.     begin
  498.       TotalSize := Point(ImageSize.X + Spacing + TextSize.X, ImageSize.Y +
  499.         Spacing + TextSize.Y);
  500.       if Layout in [ImageLeft, ImageRight] then
  501.         Margin := (ClientSize.X - TotalSize.X + 1) div 2
  502.       else
  503.         Margin := (ClientSize.Y - TotalSize.Y + 1) div 2;
  504.     end;
  505.   end
  506.   else
  507.   begin
  508.     if Spacing = -1 then
  509.     begin
  510.       TotalSize := Point(ClientSize.X - (Margin + ImageSize.X), ClientSize.Y -
  511.         (Margin + ImageSize.Y));
  512.       if Layout in [ImageLeft, ImageRight] then
  513.         Spacing := (TotalSize.X - TextSize.X) div 2
  514.       else
  515.         Spacing := (TotalSize.Y - TextSize.Y) div 2;
  516.     end;
  517.   end;
  518.   case Layout of
  519.     ImageLeft:
  520.       begin
  521.         ImagePos.X := Margin;
  522.         TextPos.X := ImagePos.X + ImageSize.X + Spacing;
  523.       end;
  524.     ImageRight:
  525.       begin
  526.         ImagePos.X := ClientSize.X - Margin - ImageSize.X;
  527.         TextPos.X := ImagePos.X - Spacing - TextSize.X;
  528.       end;
  529.     ImageTop:
  530.       begin
  531.         ImagePos.Y := Margin;
  532.         TextPos.Y := ImagePos.Y + ImageSize.Y + Spacing;
  533.       end;
  534.     ImageBottom:
  535.       begin
  536.         ImagePos.Y := ClientSize.Y - Margin - ImageSize.Y;
  537.         TextPos.Y := ImagePos.Y - Spacing - TextSize.Y;
  538.       end;
  539.   end;
  540.   with ImagePos do
  541.   begin
  542.     Inc(X, Client.Left + Offset.X);
  543.     Inc(Y, Client.Top + Offset.Y);
  544.   end;
  545.   OffsetRect(TextBounds, TextPos.X + Client.Left + Offset.X,
  546.     TextPos.Y + Client.Top + Offset.X);
  547. end;
  548. { Draw3DOutline - BottomLeft.X correction disabled }
  549. procedure DrawOutline3D(Canvas: TCanvas; var Rect: TRect;
  550.   TopColor, BottomColor: TColor; Width: Integer);
  551.   procedure DoRect;
  552.   var
  553.     TopRight, BottomLeft: TPoint;
  554.   begin
  555.     with Canvas, Rect do
  556.     begin
  557.       TopRight.X := Right;
  558.       TopRight.Y := Top;
  559.       BottomLeft.X := Left;
  560.       BottomLeft.Y := Bottom;
  561.       Pen.Color := TopColor;
  562.       PolyLine([BottomLeft, TopLeft, TopRight]);
  563.       Pen.Color := BottomColor;
  564.       PolyLine([TopRight, BottomRight, BottomLeft]);
  565.     end;
  566.   end;
  567. begin
  568.   Canvas.Pen.Width := 1;
  569.   Dec(Rect.Bottom); Dec(Rect.Right);
  570.   while Width > 0 do
  571.   begin
  572.     Dec(Width);
  573.     DoRect;
  574.     InflateRect(Rect, -1, -1);
  575.   end;
  576.   Inc(Rect.Bottom); Inc(Rect.Right);
  577. end;
  578. { DrawFrame3D }
  579. procedure DrawFrame3D(Canvas: TCanvas; var Rect: TRect;
  580.   TopColor, BottomColor: TColor; Width: Integer);
  581.   procedure DoRect;
  582.   var
  583.     TopRight, BottomLeft: TPoint;
  584.   begin
  585.     with Canvas, Rect do
  586.     begin
  587.       TopRight.X := Right;
  588.       TopRight.Y := Top;
  589.       BottomLeft.X := Left;
  590.       BottomLeft.Y := Bottom;
  591.       Pen.Color := TopColor;
  592.       PolyLine([BottomLeft, TopLeft, TopRight]);
  593.       Pen.Color := BottomColor;
  594.       Dec(BottomLeft.X);
  595.       PolyLine([TopRight, BottomRight, BottomLeft]);
  596.     end;
  597.   end;
  598. begin
  599.   Canvas.Pen.Width := 1;
  600.   Dec(Rect.Bottom); Dec(Rect.Right);
  601.   while Width > 0 do
  602.   begin
  603.     Dec(Width);
  604.     DoRect;
  605.     InflateRect(Rect, -1, -1);
  606.   end;
  607.   Inc(Rect.Bottom); Inc(Rect.Right);
  608. end;
  609. procedure CopyParentImage(Control: TControl; Dest: TCanvas);
  610. var
  611.   I, Count, X, Y, SaveIndex: Integer;
  612.   DC: HDC;
  613.   R, SelfR, CtlR: TRect;
  614. begin
  615.   if (Control = nil) or (Control.Parent = nil) then Exit;
  616.   Count := Control.Parent.ControlCount;
  617.   DC := Dest.Handle;
  618.   with Control.Parent do ControlState := ControlState + [csPaintCopy];
  619.   try
  620.     with Control do
  621.     begin
  622.       SelfR := Bounds(Left, Top, Width, Height);
  623.       X := -Left; Y := -Top;
  624.     end;
  625.     { Copy parent control image }
  626.     SaveIndex := SaveDC(DC);
  627.     try
  628.       SetViewportOrgEx(DC, X, Y, nil);
  629.       IntersectClipRect(DC, 0, 0, Control.Parent.ClientWidth,
  630.         Control.Parent.ClientHeight);
  631.       with TParentControl(Control.Parent) do
  632.       begin
  633.         Perform(WM_ERASEBKGND, DC, 0);
  634.         PaintWindow(DC);
  635.       end;
  636.     finally
  637.       RestoreDC(DC, SaveIndex);
  638.     end;
  639.     { Copy images of graphic controls }
  640.     for I := 0 to Count - 1 do begin
  641.       if Control.Parent.Controls[I] = Control then Break
  642.       else if (Control.Parent.Controls[I] <> nil) and
  643.         (Control.Parent.Controls[I] is TGraphicControl) then
  644.       begin
  645.         with TGraphicControl(Control.Parent.Controls[I]) do
  646.         begin
  647.           CtlR := Bounds(Left, Top, Width, Height);
  648.           if Bool(IntersectRect(R, SelfR, CtlR)) and Visible then
  649.           begin
  650.             ControlState := ControlState + [csPaintCopy];
  651.             SaveIndex := SaveDC(DC);
  652.             try
  653.               SetViewportOrgEx(DC, Left + X, Top + Y, nil);
  654.               IntersectClipRect(DC, 0, 0, WidthOf(R), HeightOf(R));
  655.               Perform(WM_PAINT, DC, 0);
  656.             finally
  657.               RestoreDC(DC, SaveIndex);
  658.               ControlState := ControlState - [csPaintCopy];
  659.             end;
  660.           end;
  661.         end;
  662.       end;
  663.     end;
  664.   finally
  665.     with Control.Parent do ControlState := ControlState - [csPaintCopy];
  666.   end;
  667. end;
  668. { GetOwnerControl }
  669. function GetOwnerControl(Component: TComponent): TComponent;
  670. var
  671.   AOwner: TComponent;
  672. begin
  673.   Result := nil;
  674.   AOwner := Component.Owner;
  675.   while (AOwner <> nil) and (AOwner is TWinControl) do
  676.   begin
  677.     Result := AOwner;
  678.     AOwner := Result.Owner;
  679.   end;
  680. end;
  681. { SetCanvasTextAngle }
  682. procedure SetCanvasTextAngle(Canvas: TCanvas; Angle: Word);
  683. var
  684.   LogRec: TLOGFONT;
  685. begin
  686.   GetObject(Canvas.Font.Handle, SizeOf(LogRec), Addr(LogRec));
  687.   LogRec.lfEscapement := Angle * 10;
  688.   Canvas.Font.Handle := CreateFontIndirect(LogRec);
  689. end;
  690. { CanvasTextOutAngle }
  691. procedure CanvasTextOutAngle(Canvas: TCanvas; X, Y: Integer;
  692.   Angle: Word; const Text: string);
  693. var
  694.   LogRec: TLOGFONT;
  695.   OldFontHandle,
  696.   NewFontHandle: HFONT;
  697. begin
  698.   GetObject(Canvas.Font.Handle, SizeOf(LogRec), Addr(LogRec));
  699.   LogRec.lfEscapement := Angle * 10;
  700.   NewFontHandle := CreateFontIndirect(LogRec);
  701.   OldFontHandle := SelectObject(Canvas.Handle, NewFontHandle);
  702.   Canvas.TextOut(X, Y, Text);
  703.   NewFontHandle := SelectObject(Canvas.Handle, OldFontHandle);
  704.   DeleteObject(NewFontHandle);
  705. end;
  706. { GetTextSize }
  707. function GetTextSize(Canvas: TCanvas; const Text: string): TPoint;
  708. var
  709.   TextBounds: TRect;
  710. begin
  711.   TextBounds := Rect(0, 0, 0, 0);
  712.   DrawText(Canvas.Handle, PChar(Text), Length(Text), TextBounds, DT_CALCRECT);
  713.   Result := Point(TextBounds.Right - TextBounds.Left,
  714.     TextBounds.Bottom - TextBounds.Top);
  715. end;
  716. { Draw3DText }
  717. procedure Draw3DText(Canvas: TCanvas; X, Y: Integer; const Text: String;
  718.   HighEdge, LowEdge: TColor);
  719. var
  720.   OrgColor: TColor;
  721. begin
  722.   with Canvas do
  723.   begin
  724.     OrgColor := Font.Color;
  725.     Brush.Style := bsClear;
  726.     Font.Color := LowEdge;
  727.     TextOut(X + 1, Y + 1, Text);
  728.     Font.Color := HighEdge;
  729.     TextOut(X - 1, Y - 1, Text);
  730.     Font.Color := OrgColor;
  731.     TextOut(X, Y, Text);
  732.   end;
  733. end;
  734. { DrawShadowTextExt }
  735. procedure DrawShadowTextExt(Canvas: TCanvas; X, Y : Integer; const Text: string;
  736.   ShadowColor: TColor; SX, SY: Integer);
  737. var
  738.   OrgColor: TColor;
  739. begin
  740.   with Canvas do
  741.   begin
  742.     OrgColor := Font.Color;
  743.     Brush.Style := bsClear;
  744.     Font.Color := ShadowColor;
  745.     TextOut(X + SX, Y + SY, Text);
  746.     Font.Color := OrgColor;
  747.     TextOut(X, Y, Text);
  748.   end;
  749. end;
  750. { StretchPaintOnText }
  751. procedure StretchPaintOnText(Dest: TCanvas; DestRect: TRect; X, Y : Integer;
  752.   const Text: String; Bitmap: TBitmap; Angle: Word);
  753. var
  754.   R: TRect;
  755.   FMask, FStore: TBitmap;
  756. begin
  757.   FMask := TBitmap.Create;
  758.   try
  759.     with FMask, FMask.Canvas do
  760.     begin
  761.       Monochrome := True;
  762.       Font.Assign(Dest.Font);
  763.       Font.Color := clBlack;
  764.       Width := WidthOf(DestRect);
  765.       Height := HeightOf(DestRect);
  766.       SetCanvasTextAngle(FMask.Canvas, Angle);
  767.       TextOut(X, Y, Text);
  768.     end;
  769.     FStore := TBitmap.Create;
  770.     try
  771.       with FStore do
  772.       begin
  773.         Width := FMask.Width;
  774.         Height := FMask.Height;
  775.         R := Rect(0, 0, Width, Height);
  776.         with Canvas do
  777.         begin
  778.           CopyRect(R, Dest, Bounds(0, 0, Width, Height));
  779.           CopyMode := cmSrcInvert;
  780.           StretchDraw(R, Bitmap);
  781.           CopyMode := cmSrcAnd;
  782.           Draw(0, 0, FMask);
  783.           CopyMode := cmSrcInvert;
  784.           StretchDraw(R, Bitmap);
  785.         end;
  786.       end;
  787.       Dest.Draw(0, 0, FStore);
  788.     finally
  789.       FStore.Free;
  790.     end;
  791.   finally
  792.     FMask.Free;
  793.   end;
  794. end;
  795. { DrawOutlinedText }
  796. procedure DrawOutlinedText(Canvas: TCanvas; X, Y : Integer; const Text: String;
  797.   Color: TColor; Depth: Integer);
  798. var
  799.   I: Integer;
  800.   Tmp: TColor;
  801. begin
  802.   with Canvas do
  803.   begin
  804.     Tmp := Font.Color;
  805.     Font.Color := Color;
  806.     Brush.Style := bsClear;
  807.     for I := 1 to Depth do
  808.     begin
  809.       TextOut(X + I, Y + I, Text);
  810.       TextOut(X - I, Y + I, Text);
  811.       TextOut(X - I, Y - I, Text);
  812.       TextOut(X + I, Y - I, Text);
  813.     end;
  814.     Font.Color := Tmp;
  815.     TextOut(X, Y, Text);
  816.   end;
  817. end;
  818. { DrawRasterPattern }
  819. procedure DrawRasterPattern(Canvas: TCanvas; Rect: TRect;
  820.   ForeColor, BackColor: TColor; PixelSize, Spacing: Integer);
  821. var
  822.   R: TRect;
  823.   X, Y: Integer;
  824.   Bitmap: TBitmap;
  825. begin
  826.   Bitmap := TBitmap.Create;
  827.   try
  828.     Bitmap.Width := (PixelSize + Spacing) * 20;
  829.     Bitmap.Height := Bitmap.Width;
  830.     with Bitmap do
  831.     begin
  832.       Canvas.Brush.Color := BackColor;
  833.       Canvas.FillRect(Rect);
  834.       Canvas.Brush.Color := ForeColor;
  835.       X := 0;
  836.       while X <= Width do
  837.       begin
  838.         Y := 0;
  839.         while Y <= Height do
  840.         begin
  841.           R := Bounds(X, Y, PixelSize, PixelSize);
  842.           Canvas.FillRect(R);
  843.           Inc(Y, PixelSize + Spacing);
  844.         end;
  845.         Inc(X, PixelSize + Spacing);
  846.       end;
  847.     end;
  848.     with Canvas do
  849.     begin
  850.       X := Rect.Left;
  851.       while X < Rect.Right do
  852.       begin
  853.         Y := Rect.Top;
  854.         while Y < Rect.Bottom do
  855.         begin
  856.           Draw(X, Y, Bitmap);
  857.           Inc(Y, Bitmap.Height);
  858.         end;
  859.         Inc(X, Bitmap.Width);
  860.       end;
  861.     end;
  862.   finally
  863.     Bitmap.Free;
  864.   end;
  865. end;
  866. { StretchPaintOnText }
  867. procedure StretchPaintOnRasterPattern(Dest: TCanvas; Rect: TRect;
  868.   Image: TBitmap; ForeColor, BackColor: TColor; PixelSize, Spacing: Integer);
  869. var
  870.   R: TRect;
  871.   FMask, FStore: TBitmap;
  872. begin
  873.   FMask := TBitmap.Create;
  874.   try
  875.     with FMask, FMask.Canvas do
  876.     begin
  877.       Width := WidthOf(Rect);
  878.       Height := HeightOf(Rect);
  879.       DrawRasterPattern(FMask.Canvas, Bounds(0, 0, Width, Height),
  880.         clBlack, clWhite, PixelSize, Spacing);
  881.     end;
  882.     FStore := TBitmap.Create;
  883.     try
  884.       with FStore do
  885.       begin
  886.         Width := FMask.Width;
  887.         Height := FMask.Height;
  888.         R := Classes.Rect(0, 0, Width, Height);
  889.         DrawRasterPattern(Canvas, R, ForeColor, BackColor,
  890.           PixelSize, Spacing);
  891.         with Canvas do
  892.         begin
  893.           CopyMode := cmSrcInvert;
  894.           StretchDraw(R, Image);
  895.           CopyMode := cmSrcAnd;
  896.           Draw(0, 0, FMask);
  897.           CopyMode := cmSrcInvert;
  898.           StretchDraw(R, Image);
  899.         end;
  900.       end;
  901.       Dest.Draw(0, 0, FStore);
  902.     finally
  903.       FStore.Free;
  904.     end;
  905.   finally
  906.     FMask.Free;
  907.   end;
  908. end;
  909. { BitmapToLCD }
  910. procedure BitmapToLCD(Dest: TBitmap; Source: TBitmap;
  911.   ForeColor, BackColor: TColor; PixelSize, Spacing: Integer);
  912. var
  913.   R: TRect;
  914.   FMask, FStore: TBitmap;
  915. begin
  916.   Dest.Width := Source.Width * (PixelSize + Spacing);
  917.   Dest.Height := Source.Height * (PixelSize + Spacing);
  918.   FMask := TBitmap.Create;
  919.   try
  920.     with FMask, FMask.Canvas do
  921.     begin
  922.       Width := Dest.Width;
  923.       Height := Dest.Height;
  924.       DrawRasterPattern(FMask.Canvas, Bounds(0, 0, Width, Height),
  925.         clBlack, clWhite, PixelSize, Spacing);
  926.     end;
  927.     FStore := TBitmap.Create;
  928.     try
  929.       with FStore do
  930.       begin
  931.         Width := FMask.Width;
  932.         Height := FMask.Height;
  933.         R := Classes.Rect(0, 0, Width, Height);
  934.         DrawRasterPattern(Canvas, R, ForeColor, BackColor,
  935.           PixelSize, Spacing);
  936.         with Canvas do
  937.         begin
  938.           CopyMode := cmSrcInvert;
  939.           StretchDraw(R, Source);
  940.           CopyMode := cmSrcAnd;
  941.           Draw(0, 0, FMask);
  942.           CopyMode := cmSrcInvert;
  943.           StretchDraw(R, Source);
  944.         end;
  945.       end;
  946.       Dest.Canvas.Draw(0, 0, FStore);
  947.     finally
  948.       FStore.Free;
  949.     end;
  950.   finally
  951.     FMask.Free;
  952.   end;
  953. end;
  954. { DrawTiledBitmap - no clipping}
  955. procedure DrawTiledBitmap(Canvas: TCanvas; const Rect: TRect; Glyph: TBitmap);
  956. var
  957.   X, Y: Integer;
  958. begin
  959.   X := Rect.Left;
  960.   while X < Rect.Right do
  961.   begin
  962.     Y := Rect.Top;
  963.     while Y < Rect.Bottom do
  964.     begin
  965.       Canvas.Draw(X, Y, Glyph);
  966.       Inc(Y, Glyph.Height);
  967.     end;
  968.     Inc(X, Glyph.Width);
  969.   end;
  970. end;
  971. { BitmapRect }
  972. function BitmapRect(Bitmap: TBitmap): TRect;
  973. begin
  974.   Result := Bounds(0, 0, Bitmap.Width, Bitmap.Height);
  975. end;
  976. { ChangeBitmapColor }
  977. procedure ChangeBitmapColor(Bitmap: TBitmap; FromColor, ToColor: TColor);
  978. const
  979.   ROP_DSPDxax = $00E20746;
  980. var
  981.   DestDC: HDC;
  982.   DDB, MonoBmp: TBitmap;
  983.   IWidth, IHeight: Integer;
  984.   IRect: TRect;
  985. begin
  986.   IWidth := Bitmap.Width;
  987.   IHeight := Bitmap.Height;
  988.   IRect := Rect(0, 0, IWidth, IHeight);
  989.   MonoBmp := TBitmap.Create;
  990.   DDB := TBitmap.Create;
  991.   try
  992.     DDB.Assign(Bitmap);
  993.     DDB.HandleType := bmDDB;
  994.     with Bitmap.Canvas do
  995.     begin
  996.       MonoBmp.Width := IWidth;
  997.       MonoBmp.Height := IHeight;
  998.       MonoBmp.Monochrome := True;
  999.       { Convert white to clBtnHighlight }
  1000.       DDB.Canvas.Brush.Color := FromColor;
  1001.       MonoBmp.Canvas.CopyRect(IRect, DDB.Canvas, IRect);
  1002.       Brush.Color := ToColor;
  1003.       DestDC := Bitmap.Canvas.Handle;
  1004.       SetTextColor(DestDC, clBlack);
  1005.       SetBkColor(DestDC, clWhite);
  1006.       BitBlt(DestDC, 0, 0, IWidth, IHeight,
  1007.       MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
  1008.     end;
  1009.   finally
  1010.     DDB.Free;
  1011.     MonoBmp.Free;
  1012.   end;
  1013. end;
  1014. {DrawBitmap}
  1015. procedure DrawBitmap(Canvas: TCanvas; DestRect: TRect;
  1016.   Bitmap: TBitmap; SourceRect: TRect; Transparent: Boolean; TransColor: TColor);
  1017. begin
  1018.   with Canvas do
  1019.   begin
  1020.     if Transparent then
  1021.     begin
  1022.       Brush.Style := bsClear;
  1023.       BrushCopy(DestRect, Bitmap, SourceRect, TransColor);
  1024.     end
  1025.     else
  1026.     begin
  1027.       Brush.Style := bsSolid;
  1028.       StretchDraw(DestRect, Bitmap);
  1029.     end;
  1030.   end;
  1031. end;
  1032. end.