本人写了一个关于公用进度条的程序,进度条处理的时候出现了一个很棘手的问题,即外部运行事件中有关于VCL控件操作的代码,线程中如果用Synchronize(外部事件)有时后会出现进度条窗口无法关闭的问题,请各位帮我看看,该怎么觉得这个问题,谢谢!
程序先列一下;
unit f_SimpleProgress;interfaceuses Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls, 
  Buttons, ExtCtrls, Gauges;type
  //过程类型定义
  TProgressRunEvent = procedure (lpzVar: Pointer; var sMsg: string;
    var iPos: Integer) of object;  TProgressRunEventThread = class;
  TProgressDisPlayThread = class;
  //主控窗口
  Tfrm_SimpleProgress = class(TForm)
    pnlCaption: TPanel;
    lbBusinessName: TLabel;
    lblMsg: TLabel;
    GaugeMain: TGauge;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    FRunThread: TProgressRunEventThread;
    FDisplayThread: TProgressDisPlayThread;
    procedure OnThreadTerminate(Sender: TObject);
  public
    { Public declarations }
    FsMsg: string;
    FiPos: Integer;
    FVar: Pointer;
    FbTerminate: Boolean;
    constructor Create(AVar: Pointer; RunEvent: TProgressRunEvent;
      iMaxProgress: Integer; sCaption, sSubCaption: string; bHaveVCL: Boolean);
  end;  //外部过程运行线程
  TProgressRunEventThread = class(TThread)
  private
    FProgressForm: Tfrm_SimpleProgress;
    FRunEvent: TProgressRunEvent;
    FbHaveVCL: Boolean;
    procedure RunHaveVCL;
  protected
    procedure Execute;override;
  public
    constructor Create(Sender: Tfrm_SimpleProgress; RunEvent: TProgressRunEvent;
      bHaveVCL: Boolean);
  end;
  //进度信息显示线程
  TProgressDisPlayThread = class(TThread)
  private
    FProgressForm: Tfrm_SimpleProgress;
    procedure Display;
  protected
    procedure Execute;override;
  public
    constructor Create(Sender: Tfrm_SimpleProgress);
  end;var
  frm_SimpleProgress: Tfrm_SimpleProgress;procedure DoProgress(AVar: Pointer; RunEvent: TProgressRunEvent;
  iMaxPos: Integer; sCaption, sSunCaption: string; bHaveVCL: Boolean = False);implementationuses f_GlobalSet;procedure DoProgress(AVar: Pointer; RunEvent: TProgressRunEvent;
  iMaxPos: Integer; sCaption, sSunCaption: string; bHaveVCL: Boolean = False);
begin
  with Tfrm_SimpleProgress.Create(AVar, RunEvent, iMaxPos,
    sCaption, sSunCaption, bHaveVCL) do
  try
    ShowModal;
  finally
    Free;
  end;
end;{$R *.dfm}{ TProgressRunEventThread }constructor TProgressRunEventThread.Create(Sender: Tfrm_SimpleProgress;
  RunEvent: TProgressRunEvent; bHaveVCL: Boolean);
begin
  FProgressForm := Sender;
  FRunEvent := RunEvent;
  FbHaveVCL := bHaveVCL;
  FreeOnTerminate := True;
  inherited Create(False);
end;procedure TProgressRunEventThread.Execute;
begin
  inherited;
  //if not FbHaveVCL then RunHaveVCL
  //else Synchronize(RunHaveVCL);
  RunHaveVCL;
end;procedure TProgressRunEventThread.RunHaveVCL;
begin
  FRunEvent(FProgressForm.FVar, FProgressForm.FsMsg, FProgressForm.FiPos);
end;{ TProgressDisPlayThread }constructor TProgressDisPlayThread.Create(Sender: Tfrm_SimpleProgress);
begin
  FProgressForm := Sender;
  FreeOnTerminate := True;
  inherited Create(False);
end;procedure TProgressDisPlayThread.Display;
begin
  if not FProgressForm.FbTerminate then
  begin
    FProgressForm.lblMsg.Caption := FProgressForm.FsMsg;
    FProgressForm.GaugeMain.Progress := FProgressForm.FiPos;
    Application.ProcessMessages;
    //FProgressForm.Refresh;
  end;
end;procedure TProgressDisPlayThread.Execute;
begin
  inherited;
  while not FProgressForm.FbTerminate do Synchronize(Display);
end;{ Tfrm_SimpleProgress }constructor Tfrm_SimpleProgress.Create(AVar: Pointer;
  RunEvent: TProgressRunEvent; iMaxProgress: Integer; sCaption,
  sSubCaption: string; bHaveVCL: Boolean);
begin
  inherited Create(nil);
  Caption := sCaption;
  lbBusinessName.Caption := sSubCaption;
  Application.ProcessMessages;
  //FVar := AVar;
  //CopyMemory(FVar, AVar, size(AVar));
  FVar := AVar;
  GaugeMain.MaxValue := iMaxProgress;
  FbTerminate := False; 
  FRunThread := TProgressRunEventThread.Create(Self, RunEvent, bHaveVCL);
  FRunThread.OnTerminate := OnThreadTerminate;
  FDisplayThread := TProgressDisPlayThread.Create(Self);
end;procedure Tfrm_SimpleProgress.OnThreadTerminate(Sender: TObject);
begin
  FbTerminate := True;
  ModalResult := mrOk;
end;procedure Tfrm_SimpleProgress.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  if not FbTerminate then
  begin
    if not FRunThread.Suspended then
      FRunThread.Suspend;
    if not FDisplayThread.Suspended then
      FRunThread.Suspend;
    FbTerminate := True;
  end;
end;procedure Tfrm_SimpleProgress.FormCreate(Sender: TObject);
begin
  if gclFrameBackColor <> clBlack then
    Color := gclFrameBackColor;
  if gclTopBarColor <> clBlack then
  begin
    GaugeMain.ForeColor := gclTopBarColor;
  end;
  if gclTopBarColor <> clBlack then
     pnlCaption.Color := gclTopBarColor;
  FbTerminate := False;
  lblMsg.Caption := '';
end;end.

解决方案 »

  1.   

    不好意思,上面的代码要去掉uses f_GlobalSet;
    另Tfrm_SimpleProgress.FormCreate修改一下:
    procedure Tfrm_SimpleProgress.FormCreate(Sender: TObject);
    begin
      FbTerminate := False;
      lblMsg.Caption := '';
    end;
    这样估计大家可以在有进度条的窗口下使用上面的代码了
    希望各位多提宝贵意见,谢谢
      

  2.   

    在线程中发PostMessage消息给窗体,消息中传递当前的进度
      

  3.   

    自己定义一个消息9527然后在进度显示窗体用
    procedure OnShowProgress(Var Msg:TMessage) message 9527;线程中给这个窗体发消息postmessage(WinHandle,9527,参数1 ,参数2);参数1,参数2可以为当前进度和其它的数值.窗体收到后用给定的值设置进度条就可以了
      

  4.   

    怎么不可以呀?甚至可以将进度显示窗体体放在DLL中.传出它的HANDLE,只要发送消息就可以显示了.