NewProgressBar.pas 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. unit NewProgressBar;
  2. {
  3. Inno Setup
  4. Copyright (C) 1997-2025 Jordan Russell
  5. Portions by Martijn Laan
  6. For conditions of distribution and use, see LICENSE.TXT.
  7. TNewProgressBar component - a smooth 32 bit TProgressBar
  8. Note: themed animated progress bars don't immediately show changes.
  9. This applies both to Position and State. For example if you set State while the
  10. progress bar is still moving towards a new Position, the new State doesnt show until
  11. the moving animation has finished.
  12. }
  13. interface
  14. uses
  15. Messages, Classes, Controls, ComCtrls;
  16. type
  17. TNewProgressBarState = (npbsNormal, npbsError, npbsPaused);
  18. TNewProgressBarStyle = (npbstNormal, npbstMarquee);
  19. TNewProgressBar = class(TWinControl)
  20. private
  21. FMin: LongInt;
  22. FMax: LongInt;
  23. FPosition: LongInt;
  24. FState: TNewProgressBarState;
  25. FStyle: TNewProgressBarStyle;
  26. procedure SetMin(Value: LongInt);
  27. procedure SetMax(Value: LongInt);
  28. procedure SetPosition(Value: LongInt);
  29. procedure SetState(Value: TNewProgressBarState);
  30. procedure SetStyle(Value: TNewProgressBarStyle);
  31. procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
  32. protected
  33. procedure CreateParams(var Params: TCreateParams); override;
  34. procedure CreateWnd; override;
  35. public
  36. constructor Create(AOwner: TComponent); override;
  37. published
  38. property Anchors;
  39. property Min: LongInt read FMin write SetMin;
  40. property Max: LongInt read FMax write SetMax;
  41. property Position: LongInt read FPosition write SetPosition default 0;
  42. property State: TNewProgressBarState read FState write SetState default npbsNormal;
  43. property Style: TNewProgressBarStyle read FStyle write SetStyle default npbstMarquee;
  44. property Visible default True;
  45. end;
  46. procedure Register;
  47. implementation
  48. uses
  49. Windows, CommCtrl;
  50. procedure Register;
  51. begin
  52. RegisterComponents('JR', [TNewProgressBar]);
  53. end;
  54. constructor TNewProgressBar.Create(AOwner: TComponent);
  55. begin
  56. inherited;
  57. Width := 150;
  58. Height := GetSystemMetrics(SM_CYVSCROLL);
  59. FMin := 0;
  60. FMax := 100;
  61. end;
  62. procedure TNewProgressBar.CreateParams(var Params: TCreateParams);
  63. const
  64. PBS_SMOOTH = 1;
  65. PBS_MARQUEE = 8;
  66. begin
  67. InitCommonControls;
  68. inherited;
  69. CreateSubClass(Params, PROGRESS_CLASS);
  70. Params.Style := Params.Style or PBS_SMOOTH;
  71. if Style = npbstMarquee then
  72. Params.Style := Params.Style or PBS_MARQUEE;
  73. end;
  74. procedure TNewProgressBar.CreateWnd;
  75. const
  76. PBM_SETMARQUEE = WM_USER+10;
  77. begin
  78. inherited CreateWnd;
  79. SendMessage(Handle, PBM_SETRANGE, 0, MAKELPARAM(0, 65535));
  80. SetPosition(FPosition);
  81. SetState(FState);
  82. SendMessage(Handle, PBM_SETMARQUEE, WPARAM(FStyle = npbstMarquee), 0);
  83. end;
  84. procedure TNewProgressBar.SetMin(Value: LongInt);
  85. begin
  86. FMin := Value;
  87. SetPosition(FPosition);
  88. end;
  89. procedure TNewProgressBar.SetMax(Value: LongInt);
  90. begin
  91. FMax := Value;
  92. SetPosition(FPosition);
  93. end;
  94. procedure TNewProgressBar.SetPosition(Value: LongInt);
  95. begin
  96. if Value < FMin then
  97. Value := FMin
  98. else if Value > FMax then
  99. Value := FMax;
  100. FPosition := Value;
  101. if HandleAllocated and (FStyle <> npbstMarquee) then
  102. SendMessage(Handle, PBM_SETPOS, MulDiv(Value - FMin, 65535, FMax - FMin), 0);
  103. end;
  104. procedure TNewProgressBar.SetState(Value: TNewProgressBarState);
  105. const
  106. PBST_NORMAL = $0001;
  107. PBST_ERROR = $0002;
  108. PBST_PAUSED = $0003;
  109. PBM_SETSTATE = WM_USER+16;
  110. States: array[TNewProgressBarState] of UINT = (PBST_NORMAL, PBST_ERROR, PBST_PAUSED);
  111. begin
  112. FState := Value;
  113. if HandleAllocated then
  114. SendMessage(Handle, PBM_SETSTATE, States[Value], 0);
  115. end;
  116. procedure TNewProgressBar.SetStyle(Value: TNewProgressBarStyle);
  117. begin
  118. if FStyle <> Value then begin
  119. FStyle := Value;
  120. RecreateWnd;
  121. end;
  122. end;
  123. procedure TNewProgressBar.WMEraseBkgnd(var Message: TWMEraseBkgnd);
  124. begin
  125. { Bypass TWinControl's default WM_ERASEBKGND handling.
  126. On Windows Vista with COMCTL32 v6, a WM_ERASEBKGND message is sent every
  127. time a progress bar's position changes. TWinControl.WMEraseBkgnd does a
  128. FillRect on the whole client area, which results in ugly flickering.
  129. Previous versions of Windows only sent a WM_ERASEBKGND message when a
  130. progress bar moved backwards, so flickering was rarely apparent. }
  131. DefaultHandler(Message);
  132. end;
  133. end.