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

Delphi控件源码

开发平台:

Delphi

  1. {*****************************************************}
  2. {                                                     }
  3. {     Varian Component Workshop                       }
  4. {                                                     }
  5. {     Varian Software NL (c) 1996-2000                }
  6. {     All Rights Reserved                             }
  7. {                                                     }
  8. {*****************************************************}
  9. unit VrShapeBtn;
  10. {$I VRLIB.INC}
  11. interface
  12. uses
  13.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  14.   VrControls, VrSysUtils;
  15. type
  16.   TVrShapeBtn = class(TVrGraphicImageControl)
  17.   private
  18.     FBitmap: TBitmap;
  19.     FBitmapUp: TBitmap;
  20.     FBitmapDown: TBitmap;
  21.     FMaskBitmap: TBitmap;
  22.     FDown, FPressed: Boolean;
  23.     procedure AdjustBounds;
  24.     function BevelColor(Pressed: Boolean; const TopLeft: Boolean): TColor;
  25.     procedure Create3DBitmap(Source: TBitmap; Pressed: Boolean; Target: TBitmap);
  26.     procedure SetBitmap(Value: TBitmap);
  27.     procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR;
  28.     procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
  29.     procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
  30.     procedure CMSysColorChange(var Message: TMessage); message CM_SYSCOLORCHANGE;
  31.     function PtInMask(const X, Y: Integer): Boolean;
  32.     procedure BitmapChanged(Sender: TObject);
  33.   protected
  34.     procedure DefineProperties(Filer: TFiler); override;
  35.     function GetPalette: HPALETTE; override;
  36.     procedure Loaded; override;
  37.     procedure CreateMaskBitmap;
  38.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;  X, Y: Integer); override;
  39.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  40.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;  X, Y: Integer); override;
  41.     procedure Paint; override;
  42.     procedure Click; override;
  43.     procedure ReadBitmapData(Stream: TStream); virtual;
  44.     procedure WriteBitmapData(Stream: TStream); virtual;
  45.   public
  46.     constructor Create(AOwner: TComponent); override;
  47.     destructor Destroy; override;
  48.     procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  49.   published
  50.     property Bitmap: TBitmap read FBitmap write SetBitmap;
  51.     property Transparent;
  52. {$IFDEF VER110}
  53.     property Anchors;
  54.     property Constraints;
  55. {$ENDIF}
  56.     property Caption;
  57.     property DragCursor;
  58. {$IFDEF VER110}
  59.     property DragKind;
  60. {$ENDIF}
  61.     property DragMode;
  62.     property Enabled;
  63.     property Font;
  64.     property ParentFont default false;
  65.     property ParentShowHint;
  66.     property PopupMenu;
  67.     property ShowHint;
  68.     property Visible;
  69.     property OnClick;
  70. {$IFDEF VER130}
  71.     property OnContextPopup;
  72. {$ENDIF}
  73.     property OnDragDrop;
  74.     property OnDragOver;
  75. {$IFDEF VER110}
  76.     property OnEndDock;
  77. {$ENDIF}
  78.     property OnEndDrag;
  79.     property OnMouseDown;
  80.     property OnMouseMove;
  81.     property OnMouseUp;
  82. {$IFDEF VER110}
  83.     property OnStartDock;
  84. {$ENDIF}
  85.     property OnStartDrag;
  86.   end;
  87. implementation
  88. type
  89.   Apair = array[0..1] of Integer;
  90. function MakeBorder(Source, NewSource: TBitmap; const OffsetPts: array of Apair;
  91.   TransparentColor: TColor): TBitmap;
  92. var
  93.   I : Integer;
  94.   R, NewR: TRect;
  95.   SmallMask, BigMask, NewSourceMask: TBitmap;
  96.   function GetMask(Source: TBitmap; TransColor: TColor): TBitmap;
  97.   begin
  98.     Result := TBitmap.Create;
  99.     try
  100.       Result.Assign(Source);
  101.       Result.Mask(TransColor);
  102.     except
  103.       Result.Free;
  104.       raise;
  105.     end;
  106.   end;
  107. begin
  108.   Result := TBitmap.Create;
  109.   try
  110.     R := Rect(0, 0, Source.Width, Source.Height);
  111.     Result.Monochrome := True;
  112.     Result.Width := Source.Width;
  113.     Result.Height := Source.Height;
  114.     SmallMask := GetMask(Source, TransparentColor);
  115.     NewSourceMask := GetMask(NewSource, TransparentColor);
  116.     BigMask := GetMask(NewSourceMask, TransparentColor);
  117.     try
  118.       BigMask.Canvas.CopyMode := cmSrcCopy;
  119.       BigMask.Canvas.CopyRect(R, NewSourceMask.Canvas, R);
  120.       for I := Low(OffsetPts) to High(OffsetPts) do
  121.       begin
  122.         if (OffsetPts[I, 0] = 0) and (OffsetPts[I, 1] = 0) then
  123.           Break;
  124.         NewR := R;
  125.         OffsetRect(NewR, OffsetPts[I, 0], OffsetPts[I, 1]);
  126.         BigMask.Canvas.CopyMode := cmSrcAnd;
  127.         BigMask.Canvas.CopyRect(NewR, SmallMask.Canvas, R);
  128.       end;
  129.       BigMask.Canvas.CopyMode := cmSrcCopy;
  130.       with Result do
  131.       begin
  132.         Canvas.CopyMode := cmSrcCopy;
  133.         Canvas.CopyRect(R, NewSourceMask.Canvas, R);
  134.         Canvas.CopyMode := $00DD0228;
  135.         Canvas.CopyRect(R, BigMask.Canvas, R);
  136.       end;
  137.     finally
  138.       SmallMask.Free;
  139.       NewSourceMask.Free;
  140.       BigMask.Free;
  141.     end;
  142.   except
  143.     Result.Free;
  144.     Raise;
  145.   end;
  146. end;
  147. constructor TVrShapeBtn.Create(AOwner: TComponent);
  148. begin
  149.   inherited Create(AOwner);
  150.   Width := 50;
  151.   Height := 50;
  152.   ControlStyle := ControlStyle + [csCaptureMouse, csOpaque] - [csDoubleClicks];
  153.   FBitmap := TBitmap.Create;
  154.   FBitmap.OnChange := BitmapChanged;
  155.   FBitmapUp := TBitmap.Create;
  156.   FBitmapDown := TBitmap.Create;
  157.   FMaskBitmap := TBitmap.Create;
  158.   ParentFont := True;
  159. end;
  160. destructor TVrShapeBtn.Destroy;
  161. begin
  162.   FBitmap.Free;
  163.   FBitmapUp.Free;
  164.   FBitmapDown.Free;
  165.   FMaskBitmap.Free;
  166.   inherited Destroy;
  167. end;
  168. procedure TVrShapeBtn.Loaded;
  169. begin
  170.   inherited Loaded;
  171.   CreateMaskBitmap;
  172. end;
  173. procedure TVrShapeBtn.CreateMaskBitmap;
  174. begin
  175.   if not FBitmap.Empty then
  176.   begin
  177.     FMaskBitmap.Assign(FBitmap);
  178.     FMaskBitmap.Mask(FBitmap.TransparentColor);
  179.   end;
  180. end;
  181. procedure TVrShapeBtn.AdjustBounds;
  182. begin
  183.   SetBounds(Left, Top, Width, Height);
  184. end;
  185. procedure TVrShapeBtn.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
  186. var W, H: Integer;
  187. begin
  188.   W := AWidth;
  189.   H := AHeight;
  190.   if FBitmap <> nil then
  191.     if not (csLoading in ComponentState) and (not FBitmap.Empty) then
  192.     begin
  193.       W := FBitmap.Width;
  194.       H := FBitmap.Height;
  195.     end;
  196.   inherited SetBounds(ALeft, ATop, W, H);
  197. end;
  198. procedure TVrShapeBtn.Paint;
  199. var
  200.   R: TRect;
  201.   CurrentBmp: TBitmap;
  202. begin
  203.   ClearBitmapCanvas;
  204.   if (not FPressed) then CurrentBmp := FBitmapUp
  205.   else CurrentBmp := FBitmapDown;
  206.   with BitmapCanvas do
  207.   begin
  208.     if not CurrentBmp.Empty then
  209.     begin
  210.       R := BitmapRect(BitmapImage);
  211.       if FPressed then OffsetRect(R, 1, 1);
  212.       Brush.Color := FBitmap.TransparentColor;
  213.       if Transparent then Brush.Style := bsClear
  214.       else Brush.Style := bsSolid;
  215.       BrushCopy(R, CurrentBmp, BitmapRect(CurrentBmp),
  216.         FBitmap.TransparentColor);
  217.     end;
  218.     if Length(Caption) > 0 then
  219.     begin
  220.       R := ClientRect;
  221.       Font := Self.Font;
  222.       Brush.Style := bsClear;
  223.       if FPressed then OffsetRect(R, 1, 1);
  224.       DrawText(BitmapCanvas.Handle, PChar(Caption), -1, R,
  225.         DT_CENTER or DT_VCENTER or DT_SINGLELINE);
  226.     end;
  227.   end;
  228.   ShowDesignFrame(BitmapCanvas);
  229.   inherited Paint;
  230. end;
  231. procedure TVrShapeBtn.Click;
  232. begin
  233. end;
  234. function TVrShapeBtn.PtInMask(const X, Y: Integer): Boolean;
  235. begin
  236.   Result := True;
  237.   if FMaskBitmap <> nil then
  238.     Result := (FMaskBitmap.Canvas.Pixels[X, Y] = clBlack);
  239. end;
  240. procedure TVrShapeBtn.MouseDown(Button: TMouseButton; Shift: TShiftState;
  241.   X, Y: Integer);
  242. var
  243.   Clicked: Boolean;
  244. begin
  245.   if (Button = mbLeft) and Enabled then
  246.   begin
  247.     Clicked := PtInMask(X, Y);
  248.     if Clicked then
  249.     begin
  250.       FDown := True;
  251.       FPressed := True;
  252.       UpdateControlCanvas;
  253.     end;
  254.   end;
  255.   inherited MouseDown(Button, Shift, X, Y);
  256. end;
  257. procedure TVrShapeBtn.MouseMove(Shift: TShiftState; X, Y: Integer);
  258. var
  259.   OldValue: Boolean;
  260. begin
  261.   OldValue := FPressed;
  262.   FPressed := FDown and PtInMask(X, Y);
  263.   if FPressed <> OldValue then
  264.     UpdateControlCanvas;
  265.   inherited MouseMove(Shift, X, Y);
  266. end;
  267. procedure TVrShapeBtn.MouseUp(Button: TMouseButton; Shift: TShiftState;
  268.   X, Y: Integer);
  269. var
  270.   DoClick: Boolean;
  271. begin
  272.   DoClick := false;
  273.   if FDown then
  274.   begin
  275.     DoClick := PtInMask(X, Y);
  276.     FDown := false;
  277.     FPressed := false;
  278.     UpdateControlCanvas;
  279.   end;
  280.   inherited MouseUp(Button, Shift, X, Y);
  281.   if DoClick then inherited Click;
  282. end;
  283. function TVrShapeBtn.GetPalette: HPALETTE;
  284. begin
  285.   Result := FBitmap.Palette;
  286. end;
  287. procedure TVrShapeBtn.SetBitmap(Value: TBitmap);
  288. begin
  289.   FBitmap.Assign(Value);
  290. end;
  291. procedure TVrShapeBtn.BitmapChanged(Sender: TObject);
  292. var
  293.   OldCursor: TCursor;
  294.   W, H: Integer;
  295. begin
  296.   AdjustBounds;
  297.   if not ((csReading in ComponentState) or (csLoading in ComponentState)) then
  298.   begin
  299.     if FBitmap.Empty then
  300.     begin
  301.       FBitmapUp.Assign(nil);
  302.       FBitmapDown.Assign(nil);
  303.     end
  304.     else
  305.     begin
  306.       W := FBitmap.Width;
  307.       H := FBitmap.Height;
  308.       OldCursor := Screen.Cursor;
  309.       Screen.Cursor := crHourGlass;
  310.       try
  311.         FBitmapUp.Width := W;
  312.         FBitmapUp.Height := H;
  313.         FBitmapDown.Width := W;
  314.         FBitmapDown.Height := H;
  315.         Create3DBitmap(FBitmap, False, FBitmapUp);
  316.         Create3DBitmap(FBitmap, True, FBitmapDown);
  317.         CreateMaskBitmap;
  318.       finally
  319.         Screen.Cursor := OldCursor;
  320.       end;
  321.     end;
  322.   end;
  323.   UpdateControlCanvas;
  324. end;
  325. procedure TVrShapeBtn.CMDialogChar(var Message: TCMDialogChar);
  326. begin
  327.   with Message do
  328.     if IsAccel(CharCode, Caption) and Enabled then
  329.     begin
  330.       Click;
  331.       Result := 1;
  332.     end else
  333.       inherited;
  334. end;
  335. procedure TVrShapeBtn.CMFontChanged(var Message: TMessage);
  336. begin
  337.   inherited;
  338.   UpdateControlCanvas;
  339. end;
  340. procedure TVrShapeBtn.CMTextChanged(var Message: TMessage);
  341. begin
  342.   inherited;
  343.   UpdateControlCanvas;
  344. end;
  345. procedure TVrShapeBtn.CMSysColorChange(var Message: TMessage);
  346. begin
  347.   inherited;
  348.   BitmapChanged(Self);
  349. end;
  350. function TVrShapeBtn.BevelColor(Pressed: Boolean; const TopLeft: Boolean): TColor;
  351. begin
  352.   if (not Pressed) then
  353.   begin
  354.     if TopLeft then Result := clBtnHighlight
  355.     else Result := clBtnShadow
  356.   end
  357.   else { bsDown }
  358.   begin
  359.     if TopLeft then Result := clBtnShadow
  360.     else Result := clBtnHighlight;
  361.   end;
  362. end;
  363. procedure TVrShapeBtn.Create3DBitmap(Source: TBitmap;
  364.   Pressed: Boolean; Target: TBitmap);
  365. type
  366.   OutlineOffsetPts = array[1..3, 0..1, 0..12] of Apair;
  367. const
  368.   OutlinePts: OutlineOffsetPts =
  369.     ( (((1,-1),(1,0),(1,1),(0,1),(-1,1),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0)),
  370.        ((-1,0),(-1,-1),(0,-1),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0))),
  371.       (((2,-2),(2,-1),(2, 0),(2, 1),(2, 2),(1, 2),(0, 2),(-1,2),(-2,2),(0,0),(0,0),(0,0),(0,0)),
  372.        ((-2,1),(-2,0),(-2,-1),(-2,-2),(-1,-2),(0,-2),(1,-2),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0))),
  373.       (((3,-3),(3,-2),(3,-1),(3,0),(3,1),(3,2),(3,3),(2,3),(1,3),(0,3),(-1,3),(-2,3),(-3,3)),
  374.        ((-3,2),(-3,1),(-3,0),(-3,-1),(-3,-2),(-3,-3),(-2,-3),(-1,-3),(0,-3),(1,-3),(2,-3),(0,0),(0,0)))
  375.     );
  376. var
  377.   I, J, W, H, Outlines: Integer;
  378.   R: TRect;
  379.   OutlineMask, Overlay, NewSource: TBitmap;
  380. begin
  381.   if (Source = nil) or (Target = nil) then
  382.     Exit;
  383.   W := Source.Width;
  384.   H := Source.Height;
  385.   R := Rect(0, 0, W, H);
  386.   Overlay := TBitmap.Create;
  387.   NewSource := TBitmap.Create;
  388.   try
  389.     NewSource.Width := W;
  390.     NewSource.Height := H;
  391.     Target.Canvas.CopyMode := cmSrcCopy;
  392.     Target.Canvas.CopyRect(R, Source.Canvas, R);
  393.     Overlay.Width := W;
  394.     Overlay.Height := H;
  395.     Outlines := 2;
  396.     for I := 1 to Outlines do
  397.     begin
  398.       with NewSource.Canvas do
  399.       begin
  400.         CopyMode := cmSrcCopy;
  401.         CopyRect(R, Target.Canvas, R);
  402.       end;
  403.       for J := 0 to 1 do
  404.       begin
  405.         if (Pressed) and (I = Outlines) and (J = 0) then
  406.           Continue;
  407.         OutlineMask := MakeBorder(Source, NewSource, OutlinePts[I, J],
  408.                         FBitmap.TransparentColor);
  409.         try
  410.           with Overlay.Canvas do
  411.           begin
  412.             if (I = Outlines)  then
  413.               Brush.Color := clBlack
  414.             else
  415.               Brush.Color := BevelColor(Pressed, (J = 1));
  416.             CopyMode := $0030032A; { PSna }
  417.             CopyRect(R, OutlineMask.Canvas, R);
  418.           end;
  419.           with Target.Canvas do
  420.           begin
  421.             CopyMode := cmSrcAnd; { DSa }
  422.             CopyRect(R, OutlineMask.Canvas, R);
  423.             CopyMode := cmSrcPaint; { DSo }
  424.             CopyRect(R, Overlay.Canvas, R);
  425.             CopyMode := cmSrcCopy;
  426.           end;
  427.         finally
  428.           OutlineMask.Free;
  429.         end;
  430.       end;
  431.     end;
  432.   finally
  433.     Overlay.Free;
  434.     NewSource.Free;
  435.   end;
  436. end;
  437. procedure TVrShapeBtn.DefineProperties(Filer: TFiler);
  438. begin
  439.   inherited DefineProperties(Filer);
  440.   Filer.DefineBinaryProperty('BitmapData', ReadBitmapData, WriteBitmapData, True);
  441. end;
  442. procedure TVrShapeBtn.ReadBitmapData(Stream: TStream);
  443. begin
  444.   FBitmapUp.LoadFromStream(Stream);
  445.   FBitmapDown.LoadFromStream(Stream);
  446. end;
  447. procedure TVrShapeBtn.WriteBitmapData(Stream: TStream);
  448. begin
  449.   FBitmapUp.SaveToStream(Stream);
  450.   FBitmapDown.SaveToStream(Stream);
  451. end;
  452. end.