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线程发送事件以更新进度条。

我认为最初的问题与进度条的计时和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版本中保留这段代码(尽管我没有)。

在“性能选项”中禁用视觉效果选项“为窗口内的控件和元素设置动画”。那么progressbars将不再被设置动画。

我也遇到了同样的问题。Fozi的tipp对我很有帮助。在设置新值之前,我已将值设置为+1。要使此值也能100%工作,最大值必须在之前增加。以下操作对我很有效

if (NewValue < progressBar.Maximum)
{
  progressBar.Value = NewValue + 1;
  progressBar.Value--;
}
else
{
  progressBar.Maximum++;
  progressBar.Value = progressBar.Maximum;
  progressBar.Value--;
  progressBar.Maximum--;
}
if(NewValue
对于面临相同问题的Delphi用户:下面是一个名为ProgressBarFix的单元,您可以使用它自动修补问题,而无需担心更改进度条形码——只需在ComCtrls使用后将ProgressBarFix包含在表单的界面“uses”子句中,您就可以自动获得解决方法:

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.
unitprogressbarfix;
(*Windows主题化下的标准进度条失败--无法设置动画
一直到右边,C.f。,
http://stackoverflow.com/questions/2217688/windows-7-aero-theme-progress-bar-bug
要解决此问题,请在接口部分的
在*ComCtrls之后使用*子句(这将替换中的TProgressBar定义)
这里的ConCtrls,有效地允许在
要用修补程序版本替换的表单。
c、 f。,http://www.deltics.co.nz/blog/?p=222and http://melander.dk/articles/splitter *)
接口
使用通讯录;
类型TProgressBar=class(ComCtrls.TProgressBar)
私有的
程序设置位置(值:整数);
函数GetPosition:整数;
出版
属性位置:整数读取GetPosition写入SetPosition默认值0;
结束;
实施
{TProgressBar}
函数TProgressBar.GetPosition:整数;
开始
结果:=继承位置
结束;
程序TProgressBar.SetPosition(值:整数);
开始
如果值=继承的位置,则
出口
if value(2015年9月)我刚从D6跳到XE8。有很多问题。包括这个TProgressBar的东西。把它放了一段时间。今晚遇到了这个(Erik Knowles)修复。太棒了。除了:我运行的第一个场景的最大值是9770880。它(Erik Knowles的“原始”修复)真的增加了这个过程所需的时间(包括ProgressBar的所有额外实际更新)

因此,我扩展了他的类,以减少ProgressBar实际重画自身的次数。但前提是“原始”最大值大于MIN_to_REWORK_PCTS(我在这里设定为5000)

如果是这样的话,ProgressBar只会更新自己HUNDO次(我从这里开始)
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.