본문 바로가기
Delphi, RadStudio

[delphi] Thread를 이용하여 ProgressBar 그리기

by SB리치퍼슨 2016. 7. 16.

[delphi] Thread를 이용하여 ProgressBar 그리기

 

2003.12.16

 

 

http://www.swissdelphicenter.ch/torry/showcode.php?id=1887...paint a moving progress bar using a background thread? 
Author: P. Below  
1 Comment to this tip [Write new comment] 
[ Print tip ]     

Tip Rating (6):   
       




  Question: 

  I am trying query to display records in a dbgrid.however, due to size 
  of tables and joins takes a while for the query to Execute.is 
  there any way to Show a prorgess bar with a timer that increments 
  position but continues to work while the query is being executed.BTW, 
  using access so BDE is not used. 

DB그리드에 레코드를 표시하기 위해 쿼리를 시도 중입니다.
그러나 테이블 및 조인의 크기 때문에 쿼리를 실행하는 데 시간이 걸립니다.
쿼리가 실행되는 동안 위치를 증가시키지만 계속 작동하는 타이머로 
Progess 막대를 표시할 수 있는 방법이 있습니까?
어쨌든, 액세스 사용에 BDE를 사용하지 않습니다.


  Answer: 
   
  A progress bar would not be an ideal choice since you cannot determine up 
  front how long the query will take, so you do not know the range the progress 
  bar has to cover.A simple kind of animation that tells the user basically 
  only that the application is not hung would be more appropriate.One could do 
  such a thing in a secondary thread but it would have to be done using the 
  plain Windows API and * no * Synchronize calls (since the main thread is 
  blocked in the BDE call).Here is an example: unit anithread; 

진행률 막대는 쿼리에 시간이 걸릴지 미리 결정할 수 없으므로 이상적인 선택이 아닙니다. 
따라서 진행률 표시줄이 어디까지 적용되어야 하는지 알 수 없습니다.
사용자에게 어플리케이션이 멈춰있지 않은 것만 
기본적으로 알려주는 간단한 애니메이션이 더 적절할 것이다.

보조 스레드에서 이러한 작업을 수행할 수 있지만 
일반 Windows API와 * No * Synchroniz 호출을 사용하여 수행되어야 합니다
(기본 스레드가 BDE 호출에서 차단되었으므로).

다음은 anithread 단위의 예입니다.
interface 

uses 
  Classes, Windows, Controls, Graphics; 

type 
  TAnimationThread = class(TThread) 
  private 
    { Private declarations } 
    FWnd: HWND; 
    FPaintRect: TRect; 
    FbkColor, FfgColor: TColor; 
    FInterval: integer; 
  protected 
    procedure Execute; override; 
  public 
    constructor Create(paintsurface : TWinControl; {Control to paint on } 
      paintrect : TRect;          {area for animation bar } 
      bkColor, barcolor : TColor; {colors to use } 
      interval : integer);       {wait in msecs between 
paints} 
  end; 

implementation 

constructor TAnimationThread.Create(paintsurface : TWinControl; 
  paintrect : TRect; bkColor, barcolor : TColor; interval : integer); 
begin 
  inherited Create(True); 
  FWnd := paintsurface.Handle; 
  FPaintRect := paintrect; 
  FbkColor := bkColor; 
  FfgColor := barColor; 
  FInterval := interval; 
  FreeOnterminate := True; 
  Resume; 
end; { TAnimationThread.Create } 

procedure TAnimationThread.Execute; 
var 
  image : TBitmap; 
  DC : HDC; 
  left, right : integer; 
  increment : integer; 
  imagerect : TRect; 
  state : (incRight, incLeft, decLeft, decRight); 
begin 
  Image := TBitmap.Create; 
  try 
    with Image do  
    begin 
      Width := FPaintRect.Right - FPaintRect.Left; 
      Height := FPaintRect.Bottom - FPaintRect.Top; 
      imagerect := Rect(0, 0, Width, Height); 
    end; { with } 
    left := 0; 
    right := 0; 
    increment := imagerect.right div 50; 
    state := Low(State); 
    while not Terminated do  
    begin 
      with Image.Canvas do  
      begin 
        Brush.Color := FbkColor; 
        FillRect(imagerect); 
        case state of 
          incRight:  
          begin 
            Inc(right, increment); 
            if right > imagerect.right then  
            begin 
              right := imagerect.right; 
              Inc(state); 
            end; { if } 
          end; { Case incRight } 
          incLeft:  
          begin 
            Inc(left, increment); 
            if left >= right then  
            begin 
              left := right; 
              Inc(state); 
            end; { if } 
          end; { Case incLeft } 
          decLeft:  
          begin 
            Dec(left, increment); 
            if left <= 0 then  
            begin 
              left := 0; 
              Inc(state); 
            end; { if } 
          end; { Case decLeft } 
          decRight:  
          begin 
            Dec(right, increment); 
            if right <= 0 then  
            begin 
              right := 0; 
              state := incRight; 
            end; { if } 
          end; { Case decLeft } 
        end; { Case } 
        Brush.Color := FfgColor; 
        FillRect(Rect(left, imagerect.top, right, imagerect.bottom)); 
      end; { with } 
      DC := GetDC(FWnd); 
      if DC <> 0 then 
        try 
          BitBlt(DC, 
            FPaintRect.Left, 
            FPaintRect.Top, 
            imagerect.right, 
            imagerect.bottom, 
            Image.Canvas.handle, 
            0, 0, 
            SRCCOPY); 
        finally 
          ReleaseDC(FWnd, DC); 
        end; 
      Sleep(FInterval); 
    end; { While } 
  finally 
    Image.Free; 
  end; 
  InvalidateRect(FWnd, nil, True); 
end; { TAnimationThread.Execute } 

end. 

{Usage: 
Place a TPanel on a form, size it as appropriate.Create an instance of the 
TanimationThread call like this: procedure TForm1.Button1Click(Sender : TObject); 
} 
var 
  ani : TAnimationThread; 
  r : TRect; 
  begin   
  r := panel1.clientrect; 
  InflateRect(r, - panel1.bevelwidth, - panel1.bevelwidth); 
  ani := TanimationThread.Create(panel1, r, panel1.color, clBlue, 25); 
  Button1.Enabled := False; 
  Application.ProcessMessages; 
  Sleep(30000);  // replace with query.Open or such 
  Button1.Enabled := True; 
  ani.Terminate; 
  ShowMessage('Done'); 
end;
반응형

댓글