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

Delphi控件源码

开发平台:

Delphi

  1. unit fcProgressBar;
  2. {
  3. //
  4. // Components : TfcProgressBar
  5. //
  6. // Copyright (c) 2003 by Woll2Woll Software
  7. }
  8. interface
  9. {$i fcIfdef.pas}
  10. uses
  11.   SysUtils, Classes, Controls, messages, windows,
  12.   {$ifdef fcDelphi7Up}
  13.   Themes,
  14.   {$endif}
  15.   {$ifdef ThemeManager}
  16.   thememgr, themesrv, uxtheme,
  17.   {$endif}
  18.   graphics, db, dbctrls;
  19. type
  20.   TfcProgressBarOrientation = (fcpbHorizontal, fcpbVertical);
  21.   TfcProgressBar = class(TCustomControl)
  22.   private
  23.     FDisableThemes: boolean;
  24.     FMin: Integer;
  25.     FMax: Integer;
  26.     FPosition: Integer;
  27.     FStep: Integer;
  28.     FOrientation: TfcProgressBarOrientation;
  29.     FSmooth: Boolean;
  30.     FBlockSize: integer;
  31.     FBlockColor: TColor;
  32.     FShowProgressText: boolean;
  33.     FDataLink: TFieldDataLink;
  34.     FOnChange: TNotifyEvent;
  35.     FCanvas: TControlCanvas; // For csPaintCopy State
  36.     FDisplayFormat: string;
  37.     function GetMin: Integer;
  38.     function GetMax: Integer;
  39.     function GetProgress: Integer;
  40.     procedure SetParams(AMin, AMax: Integer);
  41.     procedure SetMin(Value: Integer);
  42.     procedure SetMax(Value: Integer);
  43.     procedure SetProgress(Value: Integer);
  44.     procedure SetStep(Value: Integer);
  45.     procedure SetOrientation(Value: TfcProgressBarOrientation);
  46.     procedure SetSmooth(Value: Boolean);
  47.     procedure SetBlockSize(Value: integer);
  48.     procedure SetBlockColor(Value: TColor);
  49.     procedure SetDisplayFormat(Value: String);
  50.     procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  51.     procedure WMEraseBkGnd(var Message: TWMEraseBkGnd); message WM_ERASEBKGND;
  52.     procedure CMGetDataLink(var Message: TMessage); message CM_GETDATALINK;
  53.     function GetCanvas: TCanvas;
  54.     function GetDataField: string;
  55.     function GetDataSource: TDataSource;
  56.     procedure SetDataField(const Value: string);
  57.     procedure SetDataSource(Value: TDataSource);
  58.     function GetField: TField;
  59.     procedure PaintAsText(AnImage: TBitmap; PaintRect: TRect);
  60.   protected
  61.     procedure DrawBar(Canvas: TCanvas); virtual;
  62. //    procedure DrawProgressText(Canvas: TCanvas); virtual;
  63.     procedure Changed; virtual;
  64.     procedure UpdateData(Sender: TObject); virtual;
  65.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  66.     procedure DataChange(Sender: TObject); virtual;
  67.     procedure CreateParams(var Params: TCreateParams); override;
  68.     procedure Loaded; override;
  69.     procedure PaintProgressBar; virtual;
  70. //    procedure CreateWnd; override;
  71. //    procedure DestroyWnd; override;
  72.   public
  73.     constructor Create(AOwner: TComponent); override;
  74.     destructor Destroy; override;
  75.     procedure StepIt;
  76.     procedure StepBy(Delta: Integer);
  77.     property DataLink: TFieldDataLink read FDataLink;
  78.     property Field: TField read GetField;
  79.     property Canvas: TCanvas read GetCanvas;
  80.   published
  81.     property DisableThemes : boolean read FDisableThemes write FDisableThemes default False;
  82.     property Align;
  83.     property Anchors;
  84.     property BorderWidth;
  85.     property DragCursor;
  86.     property DragKind;
  87.     property DragMode;
  88.     property Enabled;
  89.     property Hint;
  90.     property Constraints;
  91.     property Color;
  92.     property DataField: string read GetDataField write SetDataField;
  93.     property DataSource: TDataSource read GetDataSource write SetDataSource;
  94.     property OnChange: TNotifyEvent read FOnChange write FOnChange;
  95.     property ShowProgressText : boolean read FShowProgressText write FShowProgressText default True;
  96.     property Min: Integer read GetMin write SetMin default 0;
  97.     property Max: Integer read GetMax write SetMax default 100;
  98.     property BlockSize: integer read FBlockSize write SetBlockSize default 10;
  99.     property BlockColor: TColor read FBlockColor write SetBlockColor default clHighlight;
  100.     property Orientation: TfcProgressBarOrientation read FOrientation
  101.       write SetOrientation default fcpbHorizontal;
  102.     property ParentShowHint;
  103.     property PopupMenu;
  104.     property Progress: Integer read GetProgress write SetProgress default 0;
  105.     property Smooth: Boolean read FSmooth write SetSmooth default False;
  106.     property Step: Integer read FStep write SetStep default 10;
  107.     property DisplayFormat: string read FDisplayFormat write SetDisplayFormat;
  108.     property ShowHint;
  109.     property TabOrder;
  110.     property TabStop;
  111.     property Visible;
  112.     property OnContextPopup;
  113.     property OnDragDrop;
  114.     property OnDragOver;
  115.     property OnEndDock;
  116.     property OnEndDrag;
  117.     property OnEnter;
  118.     property OnExit;
  119.     property OnMouseDown;
  120.     property OnMouseMove;
  121.     property OnMouseUp;
  122.     property OnStartDock;
  123.     property OnStartDrag;
  124.   end;
  125. procedure Register;
  126. implementation
  127. uses consts, fccommon;
  128. procedure Register;
  129. begin
  130.   RegisterComponents('1stClass', [TfcProgressBar]);
  131. end;
  132. procedure TfcProgressBar.DrawBar;
  133. var
  134.     {$ifdef fcUseThemeManager}
  135.     Details: TThemedElementDetails;
  136.     {$endif}
  137.     ChunkRect, TempRect: TRect;
  138.     r: TRect;
  139.     current, lastBottom, lastleft: integer;
  140. begin
  141.    if fcUseThemes(self) then
  142.    begin
  143.      {$ifdef fcUseThemeManager}
  144.      if Orientation = fcpbVertical then
  145.      begin
  146.         Details := ThemeServices.GetElementDetails(tpBarVert);
  147.         ThemeServices.DrawElement(Canvas.Handle, Details, ClientRect);
  148.         Details := ThemeServices.GetElementDetails(tpChunkVert);
  149.         ChunkRect:= ClientRect;
  150.         InflateRect(ChunkRect, -3, -3);
  151.         ChunkRect.Top:= ChunkRect.Bottom - Trunc((ChunkRect.Bottom-ChunkRect.top) * (Progress-Min)/(Max-Min));
  152.         ThemeServices.DrawElement(Canvas.Handle, Details, ChunkRect);
  153.      end
  154.      else begin
  155.         Details := ThemeServices.GetElementDetails(tpBar);
  156.         ThemeServices.DrawElement(Canvas.Handle, Details, ClientRect);
  157.         Details := ThemeServices.GetElementDetails(tpChunk);
  158.         ChunkRect:= ClientRect;
  159.         InflateRect(ChunkRect, -3, -3);
  160.         ChunkRect.Right:= ChunkRect.Left + Trunc((ChunkRect.Right-ChunkRect.Left) * (Progress-Min)/(Max-Min));
  161.         ThemeServices.DrawElement(Canvas.Handle, Details, ChunkRect);
  162.      end
  163.      {$endif}
  164.    end
  165.    else begin
  166.      if Orientation = fcpbVertical then
  167.      begin
  168.         Canvas.Brush.Color:= Color;
  169.         Canvas.FillRect(ClientRect);
  170.         r:= ClientRect;
  171.         DrawEdge(Canvas.Handle, r, EDGE_SUNKEN, BF_TOP or BF_LEFT);
  172.         DrawEdge(Canvas.Handle, r, EDGE_SUNKEN, BF_RIGHT or BF_BOTTOM);
  173.         ChunkRect:= ClientRect;
  174.         InflateRect(ChunkRect, -3, -3);
  175.         current:= Min;
  176.         LastBottom:= ChunkRect.bottom;
  177.         current:= current + BlockSize;
  178.         while (current<=Progress) do begin
  179.            Canvas.Brush.Color:= BlockColor;
  180.            TempRect:= ChunkRect;
  181.            TempRect.Top:= ChunkRect.Bottom - Trunc((ChunkRect.Bottom-ChunkRect.top) * (Current-Min)/(Max-Min));
  182.            TempRect.Top:= fcMax(TempRect.Top, ChunkRect.Top);
  183.            TempRect.Bottom:= fcMax(ChunkRect.Top, LastBottom);
  184.            if Smooth then LastBottom:= TempRect.Top
  185.            else LastBottom:= TempRect.Top - 2;
  186.            Canvas.FillRect(TempRect);
  187.            current:= current + BlockSize;
  188.         end;
  189.      end
  190.      else begin
  191.         Canvas.Brush.Color:= Color;
  192.         Canvas.FillRect(ClientRect);
  193.         r:= ClientRect;
  194.         DrawEdge(Canvas.Handle, r, EDGE_SUNKEN, BF_TOP or BF_LEFT);
  195.         DrawEdge(Canvas.Handle, r, EDGE_SUNKEN, BF_RIGHT or BF_BOTTOM);
  196.         ChunkRect:= ClientRect;
  197.         InflateRect(ChunkRect, -3, -3);
  198.         current:= Min;
  199.         LastLeft:= ChunkRect.Left;
  200.         current:= current + BlockSize;
  201.         while (current<=Progress) do begin
  202.            Canvas.Brush.Color:= BlockColor;
  203.            TempRect:= ChunkRect;
  204.            TempRect.Left:= fcMin(ChunkRect.Right, LastLeft);
  205.            TempRect.Right:= ChunkRect.Left + Trunc((ChunkRect.Right-ChunkRect.Left) * (Current-Min)/(Max-Min));
  206.            TempRect.Right:= fcMin(TempRect.Right, ChunkRect.Right);
  207.            if Smooth then
  208.              LastLeft:= TempRect.Right
  209.            else
  210.              LastLeft:= TempRect.Right + 2;
  211.            Canvas.FillRect(TempRect);
  212.            current:= current + BlockSize;
  213.         end;
  214.      end
  215.    end;
  216. end;
  217. (*procedure TfcProgressBar.DrawProgressText;
  218. var DrawFlags: integer;
  219.     percent: integer;
  220.     percentStr: string;
  221.     halfx, halfy: integer;
  222.     r: TRect;
  223. begin
  224.    if ShowProgressText then
  225.    begin
  226.      SetBkMode(Canvas.Handle, windows.TRANSPARENT);
  227.      Drawflags:= DT_NOPREFIX;
  228.      Percent:= Trunc(Progress/(Max-Min)*100);
  229.      PercentStr:= FloatToStr(Percent);
  230.      HalfX:= ClientWidth div 2;
  231.      HalfY:= ClientHeight div 2;
  232.      r:= Rect(HalfX - Canvas.TextWidth(Percentstr) div 2, HalfY - Canvas.TextHeight(PercentStr) div 2,
  233.               HalfX + Canvas.TextWidth(Percentstr) div 2, HalfY + Canvas.TextHeight(PercentStr) div 2);
  234.      DrawText(Canvas.Handle, pchar(PercentStr), length(PercentStr), r, DrawFlags);
  235.    end;
  236. end;
  237. *)
  238. procedure TfcProgressBar.WMPaint(var Message: TWMPaint);
  239. var DC: HDC;
  240.     PS: TPaintStruct;
  241.   procedure CanvasNeeded;
  242.   begin
  243.     if FCanvas = nil then
  244.     begin
  245.       FCanvas := TControlCanvas.Create;
  246.       FCanvas.Control := Self;
  247.     end;
  248.   end;
  249. begin
  250.   if (csPaintCopy in ControlState) then
  251.   begin
  252.       try
  253.          if FCanvas = nil then
  254.          begin
  255.             FCanvas := TControlCanvas.Create;
  256.             FCanvas.Control := Self;
  257.          end;
  258.          CanvasNeeded;
  259.          if Message.DC = 0 then DC := BeginPaint(Handle, PS)
  260.          else DC:= Message.DC;
  261.          FCanvas.Handle := DC;
  262.          PaintProgressBar;
  263.        finally
  264.          FCanvas.Handle := 0;
  265.          if Message.DC = 0 then EndPaint(Handle, PS);
  266.        end;
  267.        exit;
  268.    end;
  269.    PaintProgressBar;
  270.    inherited;
  271. end;
  272. type
  273.   TBltBitmap = class(TBitmap)
  274.     procedure MakeLike(ATemplate: TBitmap);
  275.   end;
  276. { TBltBitmap }
  277. procedure TBltBitmap.MakeLike(ATemplate: TBitmap);
  278. begin
  279.   Width := ATemplate.Width;
  280.   Height := ATemplate.Height;
  281.   Canvas.Brush.Color := clWindowFrame;
  282.   Canvas.Brush.Style := bsSolid;
  283.   Canvas.FillRect(Rect(0, 0, Width, Height));
  284. end;
  285. procedure TfcProgressBar.PaintProgressBar;
  286. var
  287.   TheImage: TBitmap;
  288.   OverlayImage: TBltBitmap;
  289.   PaintRect: TRect;
  290. begin
  291.     TheImage := TBitmap.Create;
  292.     try
  293.       TheImage.Height := Height;
  294.       TheImage.Width := Width;
  295.       DrawBar(TheImage.Canvas);
  296.       OverlayImage := TBltBitmap.Create;
  297.       try
  298.         OverlayImage.MakeLike(TheImage);
  299. //        PaintBackground(OverlayImage);
  300.         DrawBar(TheImage.Canvas);
  301. //        DrawProgressText(TheImage.Canvas);
  302.         TheImage.Canvas.CopyMode := cmSrcInvert;
  303.         TheImage.Canvas.Draw(0, 0, OverlayImage);
  304.         TheImage.Canvas.CopyMode := cmSrcCopy;
  305.         PaintRect := ClientRect;
  306. //        DrawProgressText(TheImage.Canvas);
  307. {        if ShowText then }PaintAsText(TheImage, PaintRect);
  308.       finally
  309.         OverlayImage.Free;
  310.       end;
  311.       Canvas.CopyMode := cmSrcCopy;
  312.       Canvas.Draw(0, 0, TheImage);
  313.     finally
  314.       TheImage.Destroy;
  315.     end;
  316. //   DrawBar;
  317. //   DrawProgressText;
  318. end;
  319. function TfcProgressBar.GetMin: Integer;
  320. begin
  321.    Result := FMin;
  322. end;
  323. function TfcProgressBar.GetMax: Integer;
  324. begin
  325.    Result := FMax;
  326. end;
  327. function TfcProgressBar.GetProgress: Integer;
  328. var
  329.   Value: integer;
  330. begin
  331.    if (csPaintCopy in  ControlState) and (FDataLink.Field <> nil) then
  332.    begin
  333.       Value:= FDataLink.Field.AsInteger;
  334.       if Value>Max then Value:= Max;
  335.       result:= Value;
  336.    end
  337.    else begin
  338.       result:= FPosition;
  339.    end;
  340. end;
  341. procedure TfcProgressBar.SetMin(Value: Integer);
  342. begin
  343.   SetParams(Value, FMax);
  344. end;
  345. procedure TfcProgressBar.SetMax(Value: Integer);
  346. begin
  347.   SetParams(FMin, Value);
  348. end;
  349. procedure TfcProgressBar.Loaded;
  350. begin
  351.    inherited;
  352.    Changed; 
  353. end;
  354. procedure TfcProgressBar.Changed;
  355. begin
  356.    if Assigned(FOnChange) then FOnChange(Self);
  357. end;
  358. procedure TfcProgressBar.SetProgress(Value: Integer);
  359. begin
  360.    if FPosition<>Value then
  361.    begin
  362.      Value := fcMin(Value, Max);
  363.      FPosition:= fcMax(Value, Min);
  364.      if not (csLoading in ComponentState) then
  365.         Changed;
  366.      Invalidate;
  367.    end
  368. end;
  369. procedure TfcProgressBar.SetParams(AMin, AMax: Integer);
  370. begin
  371.   if AMax < AMin then
  372.     raise EInvalidOperation.CreateFmt(SPropertyOutOfRange, [Self.Classname]);
  373.   if (FMin <> AMin) or (FMax <> AMax) then
  374.   begin
  375.     FMin := AMin;
  376.     FMax := AMax;
  377.   end;
  378. end;
  379. procedure TfcProgressBar.SetStep(Value: Integer);
  380. begin
  381.   if Value <> FStep then
  382.   begin
  383.     FStep := Value;
  384.   end;
  385. end;
  386. procedure TfcProgressBar.StepIt;
  387. begin
  388.   Progress:= fcMin(Max, Progress + Step);
  389. end;
  390. procedure TfcProgressBar.StepBy(Delta: Integer);
  391. begin
  392.   Progress:= fcMin(Max, Progress + Delta);
  393. end;
  394. procedure TfcProgressBar.SetOrientation(Value: TfcProgressBarOrientation);
  395. begin
  396.   if FOrientation <> Value then
  397.   begin
  398.     FOrientation := Value;
  399.     RecreateWnd;
  400.   end;
  401. end;
  402. procedure TfcProgressBar.SetSmooth(Value: Boolean);
  403. begin
  404.   if FSmooth <> Value then
  405.   begin
  406.     FSmooth := Value;
  407.     Invalidate;
  408.   end;
  409. end;
  410. procedure TfcProgressBar.SetDisplayFormat(Value: String);
  411. begin
  412.   if FDisplayFormat <> Value then
  413.   begin
  414.      FDisplayFormat:= Value;
  415.      Invalidate;
  416.   end
  417. end;
  418. procedure TfcProgressBar.SetBlockSize(Value: Integer);
  419. begin
  420.   if FBlockSize <> Value then
  421.   begin
  422.     FBlockSize := Value;
  423.     Invalidate;
  424.   end;
  425. end;
  426. procedure TfcProgressBar.SetBlockColor(Value: TColor);
  427. begin
  428.   if FBlockColor <> Value then
  429.   begin
  430.     FBlockColor := Value;
  431.     Invalidate;
  432.   end;
  433. end;
  434. constructor TfcProgressBar.Create(AOwner: TComponent);
  435. begin
  436.    Inherited Create(AOwner);
  437.    ControlStyle := ControlStyle + [csReplicatable];
  438.    Width := 150;
  439.    Height := GetSystemMetrics(SM_CYVSCROLL);
  440.    FMin := 0;
  441.    FMax := 100;
  442.    FStep := 10;
  443.    FOrientation := fcpbHorizontal;
  444.    FBlockColor:= clHighlight;
  445.    FBlockSize:= 10;
  446.    FShowProgressText:= True;
  447.    FDataLink := TFieldDataLink.Create;
  448.    FDataLink.Control := Self;
  449.    FDataLink.OnDataChange := DataChange;
  450.    FDataLink.OnUpdateData := UpdateData;
  451. end;
  452. procedure TfcProgressBar.CreateParams(var Params: TCreateParams);
  453. begin
  454.   inherited CreateParams(Params);
  455. //  ControlStyle := ControlStyle + [csAcceptsControls];
  456. end;
  457. function TfcProgressBar.GetDataSource: TDataSource;
  458. begin
  459.   if (FDataLink<>Nil) and (FDataLink.DataSource is TDataSource) then begin
  460.      Result := FDataLink.DataSource as TDataSource
  461.   end
  462.   else Result:= Nil;
  463. end;
  464. procedure TfcProgressBar.SetDataSource(Value: TDataSource);
  465. begin
  466.   FDataLink.DataSource := Value;
  467.   if Value <> nil then begin
  468.     Value.FreeNotification(Self);
  469.   end
  470. end;
  471. function TfcProgressBar.GetDataField: string;
  472. begin
  473.   Result := FDataLink.FieldName;
  474. end;
  475. procedure TfcProgressBar.SetDataField(const Value: string);
  476. begin
  477.   FDataLink.FieldName := Value;
  478. end;
  479. procedure TfcProgressBar.Notification(AComponent: TComponent;
  480.   Operation: TOperation);
  481. begin
  482.   inherited Notification(AComponent, Operation);
  483.   if (Operation = opRemove) and (FDataLink <> nil) and
  484.     (AComponent = DataSource) then DataSource := nil;
  485. end;
  486. function TfcProgressBar.GetField: TField;
  487. begin
  488.   Result := FDataLink.Field;
  489. end;
  490. procedure TfcProgressBar.UpdateData(Sender: TObject);
  491. begin
  492.     if (FDataLink.Field.asInteger <> Progress) then
  493.        FDataLink.Field.asInteger:= Progress;
  494. end;
  495. procedure TfcProgressBar.DataChange(Sender: TObject);
  496. var Value: Integer;
  497. begin
  498.   if FDataLink.Field <> nil then
  499.   begin
  500.     Value := FDataLink.Field.asInteger;
  501.     Progress:= Value;
  502.   end
  503. end;
  504. procedure TfcProgressBar.WMEraseBkGnd(var Message: TWMEraseBkGnd);
  505. begin
  506.     Message.Result := 1;
  507.     exit;
  508. {  if ThemeServices.ThemesEnabled then
  509.   begin
  510.     Message.Result := 1;
  511.   end
  512.   else
  513.      inherited;}
  514. end;
  515. procedure TfcProgressBar.CMGetDataLink(var Message: TMessage);
  516. begin
  517.   Message.Result := Integer(FDataLink);
  518. end;
  519. destructor TfcProgressBar.Destroy;
  520. begin
  521.   FDataLink.OnDataChange := nil;
  522.   FDataLink.Free;
  523.   FDataLink := nil;
  524.   FCanvas.Free;
  525.   inherited Destroy;
  526. end;
  527. function TfcProgressBar.GetCanvas: TCanvas;
  528. begin
  529.    if csPaintCopy in ControlState then
  530.       result:= FCanvas
  531.    else result:= inherited Canvas;
  532. end;
  533. procedure TfcProgressBar.PaintAsText(AnImage: TBitmap; PaintRect: TRect);
  534. var
  535.   S: string;
  536.   X, Y: Integer;
  537.   OverRect: TBltBitmap;
  538.   Percent: integer;
  539. begin
  540.   if not ShowProgressText then exit;
  541.   OverRect := TBltBitmap.Create;
  542.   try
  543.     OverRect.MakeLike(AnImage);
  544.     Percent:= Trunc(Progress/(Max-Min)*100);
  545.     if DisplayFormat = '' then
  546.        S:= FloatToStr(Percent) + '%'
  547.     else S := FormatFloat(DisplayFormat, Percent);
  548.     with OverRect.Canvas do
  549.     begin
  550.       Brush.Style := bsClear;
  551.       Font := Self.Font;
  552.       Font.Color := clWhite;
  553.       with PaintRect do
  554.       begin
  555.         X := (Right - Left + 1 - TextWidth(S)) div 2;
  556.         Y := (Bottom - Top + 1 - TextHeight(S)) div 2;
  557.       end;
  558.       TextRect(PaintRect, X, Y, S);
  559.     end;
  560.     AnImage.Canvas.CopyMode := cmSrcInvert;
  561.     AnImage.Canvas.Draw(0, 0, OverRect);
  562.   finally
  563.     OverRect.Free;
  564.   end;
  565. end;
  566. end.