Windows 7 Windows7 Aero主题进度条错误? 我碰到了我认为是Windows 7上的进度条错误。为了演示这个bug,我创建了一个带有按钮和进度条的WinForm应用程序。在按钮的“点击”手柄中,我有以下代码 private void buttonGo_Click(object sender, EventArgs e) { this.progressBar.Minimum = 0; this.progressBar.Maximum = 100; this.buttonGo.Text = "Busy"; this.buttonGo.Update(); for (int i = 0; i <= 100; ++i) { this.progressBar.Value = i; this.Update(); System.Threading.Thread.Sleep(10); } this.buttonGo.Text = "Ready"; } private void按钮单击(对象发送者,事件参数e) { 此.progressBar.Minimum=0; 此.progressBar.最大值=100; this.buttonGo.Text=“忙”; this.buttonGo.Update(); 对于(inti=0;i

Windows 7 Windows7 Aero主题进度条错误? 我碰到了我认为是Windows 7上的进度条错误。为了演示这个bug,我创建了一个带有按钮和进度条的WinForm应用程序。在按钮的“点击”手柄中,我有以下代码 private void buttonGo_Click(object sender, EventArgs e) { this.progressBar.Minimum = 0; this.progressBar.Maximum = 100; this.buttonGo.Text = "Busy"; this.buttonGo.Update(); for (int i = 0; i <= 100; ++i) { this.progressBar.Value = i; this.Update(); System.Threading.Thread.Sleep(10); } this.buttonGo.Text = "Ready"; } private void按钮单击(对象发送者,事件参数e) { 此.progressBar.Minimum=0; 此.progressBar.最大值=100; this.buttonGo.Text=“忙”; this.buttonGo.Update(); 对于(inti=0;i,windows-7,progress-bar,aero,Windows 7,Progress Bar,Aero,我在Vista和Windows7上看到了类似的进度条问题 我的例子中的关键问题是UI线程阻塞(就像您在示例中所做的那样) Windows不喜欢不响应消息队列中新消息的应用程序。如果您在一条消息上花费太多时间,Windows会将您的应用程序标记为“无响应”。在Vista/Win7中,Windows还会决定停止更新您的应用程序窗口 作为一种解决方法,您可以将实际工作放在后台工作人员身上,或者每隔一段时间调用Application.DoEvents()。您确实需要确保进度条窗口是模态的,否则DoEve

我在Vista和Windows7上看到了类似的进度条问题

我的例子中的关键问题是UI线程阻塞(就像您在示例中所做的那样)

Windows不喜欢不响应消息队列中新消息的应用程序。如果您在一条消息上花费太多时间,Windows会将您的应用程序标记为“无响应”。在Vista/Win7中,Windows还会决定停止更新您的应用程序窗口

作为一种解决方法,您可以将实际工作放在后台工作人员身上,或者每隔一段时间调用
Application.DoEvents()
。您确实需要确保进度条窗口是模态的,否则DoEvents()可能会使新命令在后台处理的中途开始执行


如果这让人觉得很尴尬,更合适的方法是在
BackgroundWorker
线程上进行后台工作。它支持将事件发送到UI线程以更新进度条。

我在Vista和Windows 7上看到过类似的进度条问题

我的例子中的关键问题是UI线程阻塞(就像您在示例中所做的那样)

Windows不喜欢不响应消息队列中新消息的应用程序。如果您在一条消息上花费太多时间,Windows会将您的应用程序标记为“无响应”。在Vista/Win7中,Windows还会决定停止更新您的应用程序窗口

作为一种解决方法,您可以将实际工作放在后台工作人员身上,或者每隔一段时间调用
Application.DoEvents()
。您确实需要确保进度条窗口是模态的,否则DoEvents()可能会使新命令在后台处理的中途开始执行


如果这让人觉得很尴尬,更合适的方法是在
BackgroundWorker
线程上进行后台工作。它支持向UI线程发送事件以更新进度条。

我认为最初的问题与进度条的计时和Win7(或Aero)动画机制有关

此子项位于包含进度条(pBar)的表单上

它改变了条的最大值,并将条的最大值固定为10,完成百分比为1到99。条的最小值在设计时设置为0

这为我解决了问题

Public Sub UpdateStatusPC(ByVal pc As Integer)

    Try

        If pc < 0 Then
            pBar.Maximum = 100
            pBar.Value = 0
        ElseIf pc > 100 Then
            pBar.Maximum = 100
            pBar.Value = 100
        ElseIf pc = 0 Then
            pBar.Maximum = 10
            pBar.Value = 0
        Else
            pBar.Value = 10
            pBar.Maximum = 10 / CDbl(pc / 100.0)
        End If

        pBar.Update()

    Catch ex As Exception

        MsgBox("UpdateStatusPC: " & ex.Message)

    End Try

End Sub
Public Sub-UpdateStatusPC(ByVal pc作为整数)
尝试
如果pc<0,则
pBar.最大值=100
pBar.Value=0
如果pc>100,则
pBar.最大值=100
pBar.值=100
ElseIf pc=0,则
pBar.最大值=10
pBar.Value=0
其他的
pBar.值=10
pBar最大值=10/CDbl(pc/100.0)
如果结束
pBar.Update()
特例
MsgBox(“UpdateStatusPC:&ex.Message”)
结束尝试
端接头

我认为最初的问题与进度条的计时和Win7(或Aero)动画机制有关

此子项位于包含进度条(pBar)的表单上

它改变了条的最大值,并将条的最大值固定为10,完成百分比为1到99。条的最小值在设计时设置为0

这为我解决了问题

Public Sub UpdateStatusPC(ByVal pc As Integer)

    Try

        If pc < 0 Then
            pBar.Maximum = 100
            pBar.Value = 0
        ElseIf pc > 100 Then
            pBar.Maximum = 100
            pBar.Value = 100
        ElseIf pc = 0 Then
            pBar.Maximum = 10
            pBar.Value = 0
        Else
            pBar.Value = 10
            pBar.Maximum = 10 / CDbl(pc / 100.0)
        End If

        pBar.Update()

    Catch ex As Exception

        MsgBox("UpdateStatusPC: " & ex.Message)

    End Try

End Sub
Public Sub-UpdateStatusPC(ByVal pc作为整数)
尝试
如果pc<0,则
pBar.最大值=100
pBar.Value=0
如果pc>100,则
pBar.最大值=100
pBar.值=100
ElseIf pc=0,则
pBar.最大值=10
pBar.Value=0
其他的
pBar.值=10
pBar最大值=10/CDbl(pc/100.0)
如果结束
pBar.Update()
特例
MsgBox(“UpdateStatusPC:&ex.Message”)
结束尝试
端接头

这与进度条的动画有关。如果进度条为0%,而您将其设置为100%,则它不会跳到那里,而是将进度条平滑填充。如果速度太慢,您将在进度条完成动画制作之前完成。因此,即使您已将其设置为80%、90%和100%,动画仍将继续仍然落后


我从未找到关闭此功能的方法,但是我有一个解决方法。只有当你增加进度条时,动画才会完成。如果你向后移动它,它会立即跳到该位置。因此,如果我希望进度条位于x%(x!=100),则我将其移动到x+1,然后移动到x。如果我希望进度条位于100%,则将其移动到100%、99%和100%。(或者不管你使用什么值,你都会明白的。)这工作速度足够快,以至于看不见,你也可以在以前的Windows版本中保留这段代码(尽管我没有).

这与进度条的动画有关。如果进度条为0%,而您将其设置为100%,则它将不会跳到那里,而是将进度条平滑填充。如果速度太慢,您将在进度条完成动画制作之前完成。因此,即使您已将其设置为80%、90%和100%,动画仍将继续直到落后

我从未找到关闭此功能的方法,但是我有一个解决方法。只有当你增加进度条时,动画才会完成。如果你向后移动它,它会立即跳到该位置。因此,如果我希望进度条位于x%(x!=100),则我将其移动到x+1,然后移动到x。如果我希望进度条位于100%,则将其移动到100%、99%和100%。(或者,不管你使用什么值,你都能理解。)这项技术的工作速度足够快,以至于看不见
unit ProgressBarFix;
(* The standard progress bar fails under Windows theming -- it fails to animate
   all the way to the right side. C.f.,
   http://stackoverflow.com/questions/2217688/windows-7-aero-theme-progress-bar-bug

   To work around the problem, include ProgressBarFix in the interface section's
   "uses" clause *after* ComCtrls (this replaces the TProgressBar definition in
   ConCtrls with the one here, effectively allowing the control defined on the
   form to be replaced with the patch version.

   c.f., http://www.deltics.co.nz/blog/?p=222and http://melander.dk/articles/splitter *)

interface
uses ComCtrls ;

type TProgressBar = class(ComCtrls.TProgressBar)
private
    procedure SetPosition(Value: Integer);
    function GetPosition: Integer;
published
    property Position: Integer read GetPosition write SetPosition default 0;
end ;

implementation

{ TProgressBar }

function TProgressBar.GetPosition: Integer;
begin
    result := inherited Position
end;

procedure TProgressBar.SetPosition(Value: Integer);
begin
    if Value=inherited Position then
        exit ;
    if value<Max then begin
        inherited Position := value+1 ;
        inherited Position := value
    end else begin
        Max := Max+1 ;
        inherited Position := Max ;
        inherited Position := value ;
        Max := Max-1
    end            
end;

end.
if Abs(FOriginalMax - value) <= 1 then
  pct := HUNDO
:
uses
  :
  ProgressBarFix;

const
  PROGRESS_PTS = 500001;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    PB: TProgressBar;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  x: integer;
begin
PB.Min := 0;
PB.Max := PROGRESS_PTS;
PB.Position := 0;

for x := 1 to PROGRESS_PTS do
  begin
  //let's do something
  //
  Label1.Caption := Format('%d of %d',[x,PROGRESS_PTS]);
  Update;

  PB.Position := x;
  end;

PB.Position := 0;
end;

end.
unit ProgressBarFix;

interface

uses
  Vcl.ComCtrls;

type
  TProgressBar = class(Vcl.ComCtrls.TProgressBar)
  const
    HUNDO = 100;
    MIN_TO_REWORK_PCTS = 5000;
  private
    function  GetMax: integer;
    procedure SetMax(value: integer);
    function  GetPosition: integer;
    procedure SetPosition(value: integer);
  published
    property Max: integer read GetMax write SetMax default 100;
    property Position: integer read GetPosition write SetPosition default 0;

  private
    FReworkingPcts: boolean;
    FOriginalMax:   integer;
    FLastPct:       integer;
  end;

implementation

function TProgressBar.GetMax: integer;
begin
result := inherited Max;
end;

procedure TProgressBar.SetMax(value: integer);
begin
FOriginalMax := value;
FLastPct := 0;

FReworkingPcts := FOriginalMax > MIN_TO_REWORK_PCTS;

if FReworkingPcts then
  inherited Max := HUNDO
else
  inherited Max := value;
end;

function TProgressBar.GetPosition: integer;
begin
result := inherited Position;
end;

procedure TProgressBar.SetPosition(value: integer);
var
  pct: integer;
begin
//Application.ProcessMessages;

if value = inherited Position then
  exit;

if FReworkingPcts then
  begin
  if Abs(FOriginalMax - value) <= 1 then
    pct := HUNDO
  else
    pct := Trunc((value / FOriginalMax) * HUNDO);

  if pct = FLastPct then
    exit;

  FLastPct := pct;

  value := pct;
  end;

if value < Max then
  begin
  inherited Position := Succ(value);
  inherited Position := value;
  end
else
  begin
  Max := Succ(Max);
  inherited Position := Max;
  inherited Position := value;
  Max := Pred(Max);
  end;
end;

end.