关于进度条和线程的问题?

劣势 2006-03-08 01:35:26
本人写了一个关于公用进度条的程序,进度条处理的时候出现了一个很棘手的问题,即外部运行事件中有关于VCL控件操作的代码,线程中如果用Synchronize(外部事件)有时后会出现进度条窗口无法关闭的问题,请各位帮我看看,该怎么觉得这个问题,谢谢!
程序先列一下;
unit f_SimpleProgress;

interface

uses 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);

implementation

uses 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.
...全文
358 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
skertone 2006-03-14
  • 打赏
  • 举报
回复
绝望中的方法,好用。。。。严重同意
ZyxIp 2006-03-10
  • 打赏
  • 举报
回复
怎么不可以呀?甚至可以将进度显示窗体体放在DLL中.传出它的HANDLE,只要发送消息就可以显示了.
劣势 2006-03-10
  • 打赏
  • 举报
回复
这样好像不可以做成公用的方法
ZyxIp 2006-03-09
  • 打赏
  • 举报
回复
自己定义一个消息9527

然后在进度显示窗体用
procedure OnShowProgress(Var Msg:TMessage) message 9527;

线程中给这个窗体发消息

postmessage(WinHandle,9527,参数1 ,参数2);

参数1,参数2可以为当前进度和其它的数值.窗体收到后用给定的值设置进度条就可以了
劣势 2006-03-08
  • 打赏
  • 举报
回复
楼上的能否具体些
ZyxIp 2006-03-08
  • 打赏
  • 举报
回复
在线程中发PostMessage消息给窗体,消息中传递当前的进度
劣势 2006-03-08
  • 打赏
  • 举报
回复
自己顶。。。。。
周公梦游 2006-03-08
  • 打赏
  • 举报
回复
太长了,眼都看花了
劣势 2006-03-08
  • 打赏
  • 举报
回复
不好意思,上面的代码要去掉uses f_GlobalSet;
另Tfrm_SimpleProgress.FormCreate修改一下:
procedure Tfrm_SimpleProgress.FormCreate(Sender: TObject);
begin
FbTerminate := False;
lblMsg.Caption := '';
end;
这样估计大家可以在有进度条的窗口下使用上面的代码了
希望各位多提宝贵意见,谢谢

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧