Explorar o código

Merge branch 'main' into autoreload

Martijn Laan hai 1 mes
pai
achega
6f3d187ed6

+ 193 - 0
Components/BitmapButton.pas

@@ -0,0 +1,193 @@
+unit BitmapButton;
+
+{
+  Inno Setup
+  Copyright (C) 1997-2025 Jordan Russell
+  Portions by Martijn Laan
+  For conditions of distribution and use, see LICENSE.TXT.
+
+  A TImage-like component for bitmaps without the TPicture bloat and
+  which is actually a button with a focus rectangle when focused - in
+  other words: an accessible TImage
+  
+  Make sure to set the Caption property, even if it isn't visible
+
+  Also see TBitmapImage which is the TGraphicControl version
+}
+
+interface
+
+uses
+  Windows, Messages, Controls, Graphics, Classes,
+  BitmapImage;
+
+type
+  TBitmapButton = class(TCustomControl)
+  private
+    FFocusBorderWidthHeight: Integer;
+    FImpl: TBitmapImageImplementation;
+    FOnClick: TNotifyEvent;
+    FOnDblClick: TNotifyEvent;
+    procedure SetBackColor(Value: TColor);
+    procedure SetBitmap(Value: TBitmap);
+    procedure SetCenter(Value: Boolean);
+    procedure SetReplaceColor(Value: TColor);
+    procedure SetReplaceWithColor(Value: TColor);
+    procedure SetStretch(Value: Boolean);
+    procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
+    procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
+    procedure CNCommand(var Message: TWMCommand); message CN_COMMAND;
+  protected
+    procedure CreateParams(var Params: TCreateParams); override;
+    function GetPalette: HPALETTE; override;
+    procedure Paint; override;
+    procedure SetAutoSize(Value: Boolean); override;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    function InitializeFromIcon(const Instance: HINST; const Name: PChar; const BkColor: TColor; const AscendingTrySizes: array of Integer): Boolean;
+  published
+    property Align;
+    property Anchors;
+    property AutoSize: Boolean read FImpl.AutoSize write SetAutoSize default False;
+    property BackColor: TColor read FImpl.BackColor write SetBackColor default clNone;
+    property Caption;
+    property Center: Boolean read FImpl.Center write SetCenter default True;
+    property Enabled;
+    property ParentShowHint;
+    property Bitmap: TBitmap read FImpl.Bitmap write SetBitmap;
+    property PopupMenu;
+    property ShowHint;
+    property Stretch: Boolean read FImpl.Stretch write SetStretch default False;
+    property ReplaceColor: TColor read FImpl.ReplaceColor write SetReplaceColor default clNone;
+    property ReplaceWithColor: TColor read FImpl.ReplaceWithColor write SetReplaceWithColor default clNone;
+    property TabOrder;
+    property TabStop default True;
+    property Visible;
+    property OnClick: TNotifyEvent read FOnClick write FOnClick;
+    property OnDblClick: TNotifyEvent read FOnDblClick write FOnDblClick;
+    property OnPaint: TPaintEvent read FImpl.OnPaint write FImpl.OnPaint;
+  end;
+
+procedure Register;
+
+implementation
+
+procedure Register;
+begin
+  RegisterComponents('JR', [TBitmapButton]);
+end;
+
+constructor TBitmapButton.Create(AOwner: TComponent);
+begin
+  inherited;
+  ControlStyle := ControlStyle + [csReplicatable];
+  { Using a fixed focus border width/height to avoid design problems between systems }
+  FFocusBorderWidthHeight := 2;
+  const DoubleFBWH = 2*FFocusBorderWidthHeight;
+  FImpl.Init(Self, DoubleFBWH, DoubleFBWH);
+  Center := True;
+  TabStop := True;
+  Width := 75+DoubleFBWH;
+  Height := 25+DoubleFBWH;
+end;
+
+procedure TBitmapButton.CreateParams(var Params: TCreateParams);
+begin
+  inherited;
+  CreateSubClass(Params, 'BUTTON');
+end;
+
+destructor TBitmapButton.Destroy;
+begin
+  FImpl.DeInit;
+  inherited;
+end;
+
+function TBitmapButton.InitializeFromIcon(const Instance: HINST; const Name: PChar; const BkColor: TColor; const AscendingTrySizes: array of Integer): Boolean;
+begin
+  Result := FImpl.InitializeFromIcon(HInstance, Name, BkColor, AscendingTrySizes);
+end;
+
+procedure TBitmapButton.SetAutoSize(Value: Boolean);
+begin
+  FImpl.SetAutoSize(Self, Value);
+end;
+
+procedure TBitmapButton.SetBackColor(Value: TColor);
+begin
+  FImpl.SetBackColor(Self, Value);
+end;
+
+procedure TBitmapButton.SetBitmap(Value: TBitmap);
+begin
+  FImpl.SetBitmap(Value);
+end;
+
+procedure TBitmapButton.SetCenter(Value: Boolean);
+begin
+  FImpl.SetCenter(Self, Value);
+end;
+
+procedure TBitmapButton.SetReplaceColor(Value: TColor);
+begin
+  FImpl.SetReplaceColor(Self, Value);
+end;
+
+procedure TBitmapButton.SetReplaceWithColor(Value: TColor);
+begin
+  FImpl.SetReplaceWithColor(Self, Value);
+end;
+
+procedure TBitmapButton.SetStretch(Value: Boolean);
+begin
+  FImpl.SetStretch(Self, Value);
+end;
+
+function TBitmapButton.GetPalette: HPALETTE;
+begin
+  Result := FImpl.GetPalette;
+end;
+
+procedure TBitmapButton.Paint;
+begin
+  Canvas.Font := Font;
+  Canvas.Brush.Color := Color;
+
+  var R := ClientRect;
+
+  if Focused and (SendMessage(Handle, WM_QUERYUISTATE, 0, 0) and UISF_HIDEFOCUS = 0) then begin
+    { See TBitBtn.DrawItem in Vcl.Buttons.pas }
+    Canvas.Pen.Color := clWindowFrame;
+    Canvas.Brush.Style := bsSolid;
+    Canvas.Brush.Color := clBtnFace;
+    { This might draw a focus border thinner or thicker than our FFocusBorderWidthHeight but that's okay }
+    Canvas.DrawFocusRect(R);
+  end;
+
+  InflateRect(R, -FFocusBorderWidthHeight, -FFocusBorderWidthHeight);
+
+  FImpl.Paint(Self, Canvas, R);
+end;
+
+procedure TBitmapButton.WMSetFocus(var Message: TWMSetFocus);
+begin
+  inherited;
+  Invalidate;
+end;
+
+procedure TBitmapButton.WMKillFocus(var Message: TWMKillFocus);
+begin
+  inherited;
+  Invalidate;
+end;
+
+procedure TBitmapButton.CNCommand(var Message: TWMCommand);
+begin
+  if (Message.NotifyCode = BN_CLICKED) and Assigned(FOnClick) then
+    FOnClick(Self)
+  else if (Message.NotifyCode = BN_DBLCLK) and Assigned(FOnDblClick) then
+    FOnDblClick(Self);
+end;
+
+end.

+ 240 - 157
Components/BitmapImage.pas

@@ -2,11 +2,13 @@ unit BitmapImage;
 
 
 {
 {
   Inno Setup
   Inno Setup
-  Copyright (C) 1997-2019 Jordan Russell
+  Copyright (C) 1997-2025 Jordan Russell
   Portions by Martijn Laan
   Portions by Martijn Laan
   For conditions of distribution and use, see LICENSE.TXT.
   For conditions of distribution and use, see LICENSE.TXT.
 
 
   A TImage-like component for bitmaps without the TPicture bloat
   A TImage-like component for bitmaps without the TPicture bloat
+
+  Also see TBitmapButton which is the TWinControl version
 }
 }
 
 
 interface
 interface
@@ -15,25 +17,48 @@ uses
   Windows, Controls, Graphics, Classes;
   Windows, Controls, Graphics, Classes;
 
 
 type
 type
-  TBitmapImage = class(TGraphicControl)
+  TPaintEvent = procedure(Sender: TObject; Canvas: TCanvas; var ARect: TRect) of object;
+
+  TBitmapImageImplementation = record
   private
   private
-    FAutoSize: Boolean;
-    FBackColor: TColor;
-    FBitmap: TBitmap;
-    FCenter: Boolean;
-    FReplaceColor: TColor;
-    FReplaceWithColor: TColor;
-    FStretch: Boolean;
-    FStretchedBitmap: TBitmap;
-    FStretchedBitmapValid: Boolean;
+    FControl: TControl;
+  public
+    AutoSize: Boolean;
+    AutoSizeExtraWidth, AutoSizeExtraHeight: Integer;
+    BackColor: TColor;
+    Bitmap: TBitmap;
+    Center: Boolean;
+    ReplaceColor: TColor;
+    ReplaceWithColor: TColor;
+    Stretch: Boolean;
+    StretchedBitmap: TBitmap;
+    StretchedBitmapValid: Boolean;
+    OnPaint: TPaintEvent;
+    procedure Init(const AControl: TControl; const AAutoSizeExtraWidth: Integer = 0;
+      const AAutoSizeExtraHeight: Integer = 0);
+    procedure DeInit;
+    function InitializeFromIcon(const Instance: HINST; const Name: PChar; const BkColor: TColor; const AscendingTrySizes: array of Integer): Boolean;
     procedure BitmapChanged(Sender: TObject);
     procedure BitmapChanged(Sender: TObject);
+    procedure SetAutoSize(Sender: TObject; Value: Boolean);
+    procedure SetBackColor(Sender: TObject; Value: TColor);
+    procedure SetBitmap(Value: TBitmap);
+    procedure SetCenter(Sender: TObject; Value: Boolean);
+    procedure SetReplaceColor(Sender: TObject; Value: TColor);
+    procedure SetReplaceWithColor(Sender: TObject; Value: TColor);
+    procedure SetStretch(Sender: TObject; Value: Boolean);
+    function GetPalette: HPALETTE;
+    procedure Paint(const Sender: TObject; const Canvas: TCanvas; var R: TRect);
+  end;
+
+  TBitmapImage = class(TGraphicControl)
+  private
+    FImpl: TBitmapImageImplementation;
     procedure SetBackColor(Value: TColor);
     procedure SetBackColor(Value: TColor);
     procedure SetBitmap(Value: TBitmap);
     procedure SetBitmap(Value: TBitmap);
     procedure SetCenter(Value: Boolean);
     procedure SetCenter(Value: Boolean);
     procedure SetReplaceColor(Value: TColor);
     procedure SetReplaceColor(Value: TColor);
     procedure SetReplaceWithColor(Value: TColor);
     procedure SetReplaceWithColor(Value: TColor);
     procedure SetStretch(Value: Boolean);
     procedure SetStretch(Value: Boolean);
-    function GetBitmap: TBitmap;
   protected
   protected
     function GetPalette: HPALETTE; override;
     function GetPalette: HPALETTE; override;
     procedure Paint; override;
     procedure Paint; override;
@@ -45,19 +70,19 @@ type
   published
   published
     property Align;
     property Align;
     property Anchors;
     property Anchors;
-    property AutoSize: Boolean read FAutoSize write SetAutoSize default False;
-    property BackColor: TColor read FBackColor write SetBackColor default clBtnFace;
-    property Center: Boolean read FCenter write SetCenter default False;
+    property AutoSize: Boolean read FImpl.AutoSize write SetAutoSize default False;
+    property BackColor: TColor read FImpl.BackColor write SetBackColor default clBtnFace;
+    property Center: Boolean read FImpl.Center write SetCenter default False;
     property DragCursor;
     property DragCursor;
     property DragMode;
     property DragMode;
     property Enabled;
     property Enabled;
     property ParentShowHint;
     property ParentShowHint;
-    property Bitmap: TBitmap read GetBitmap write SetBitmap;
+    property Bitmap: TBitmap read FImpl.Bitmap write SetBitmap;
     property PopupMenu;
     property PopupMenu;
     property ShowHint;
     property ShowHint;
-    property Stretch: Boolean read FStretch write SetStretch default False;
-    property ReplaceColor: TColor read FReplaceColor write SetReplaceColor default clNone;
-    property ReplaceWithColor: TColor read FReplaceWithColor write SetReplaceWithColor default clNone;
+    property Stretch: Boolean read FImpl.Stretch write SetStretch default False;
+    property ReplaceColor: TColor read FImpl.ReplaceColor write SetReplaceColor default clNone;
+    property ReplaceWithColor: TColor read FImpl.ReplaceWithColor write SetReplaceWithColor default clNone;
     property Visible;
     property Visible;
     property OnClick;
     property OnClick;
     property OnDblClick;
     property OnDblClick;
@@ -67,6 +92,7 @@ type
     property OnMouseDown;
     property OnMouseDown;
     property OnMouseMove;
     property OnMouseMove;
     property OnMouseUp;
     property OnMouseUp;
+    property OnPaint: TPaintEvent read FImpl.OnPaint write FImpl.OnPaint;
     property OnStartDrag;
     property OnStartDrag;
   end;
   end;
 
 
@@ -75,51 +101,68 @@ procedure Register;
 implementation
 implementation
 
 
 uses
 uses
-  Math, Resample;
+  SysUtils, Math, Resample;
 
 
 procedure Register;
 procedure Register;
 begin
 begin
   RegisterComponents('JR', [TBitmapImage]);
   RegisterComponents('JR', [TBitmapImage]);
 end;
 end;
 
 
-function TBitmapImage.InitializeFromIcon(const Instance: HINST; const Name: PChar; const BkColor: TColor; const AscendingTrySizes: array of Integer): Boolean;
-var
-  Flags: Cardinal;
-  Handle: THandle;
-  Icon: TIcon;
-  I, Size: Integer;
+{ TBitmapImageImplementation }
+
+procedure TBitmapImageImplementation.Init(const AControl: TControl;
+  const AAutoSizeExtraWidth, AAutoSizeExtraHeight: Integer);
+begin
+  FControl := AControl;
+  AutoSizeExtraWidth := AAutoSizeExtraWidth;
+  AutoSizeExtraHeight := AAutoSizeExtraHeight;
+  Bitmap := TBitmap.Create;
+  Bitmap.OnChange := BitmapChanged;
+  BackColor := clNone;
+  ReplaceColor := clNone;
+  ReplaceWithColor := clNone;
+  StretchedBitmap := TBitmap.Create;
+end;
+
+procedure TBitmapImageImplementation.DeInit;
+begin
+  FreeAndNil(StretchedBitmap);
+  FreeAndNil(Bitmap);
+end;
+
+function TBitmapImageImplementation.InitializeFromIcon(const Instance: HINST; const Name: PChar; const BkColor: TColor; const AscendingTrySizes: array of Integer): Boolean;
 begin
 begin
   { Find the largest regular icon size smaller than the scaled image }
   { Find the largest regular icon size smaller than the scaled image }
-  Size := 0;
-  for I := Length(AscendingTrySizes)-1 downto 0 do begin
-    if (Width >= AscendingTrySizes[I]) and (Height >= AscendingTrySizes[I]) then begin
+  var Size := 0;
+  for var I := Length(AscendingTrySizes)-1 downto 0 do begin
+    if (FControl.Width >= AscendingTrySizes[I]) and (FControl.Height >= AscendingTrySizes[I]) then begin
       Size := AscendingTrySizes[I];
       Size := AscendingTrySizes[I];
       Break;
       Break;
     end;
     end;
   end;
   end;
   if Size = 0 then
   if Size = 0 then
-    Size := Min(Width, Height);
+    Size := Min(FControl.Width, FControl.Height);
 
 
   { Load the desired icon }
   { Load the desired icon }
-  Flags := LR_DEFAULTCOLOR;
+  var Flags := LR_DEFAULTCOLOR;
   if Instance = 0 then
   if Instance = 0 then
     Flags := Flags or LR_LOADFROMFILE;
     Flags := Flags or LR_LOADFROMFILE;
-  Handle := LoadImage(Instance, Name, IMAGE_ICON, Size, Size, Flags);
+  var Handle := LoadImage(Instance, Name, IMAGE_ICON, Size, Size, Flags);
   if Handle = 0 then
   if Handle = 0 then
     Handle := LoadImage(Instance, Name, IMAGE_ICON, 0, 0, Flags);
     Handle := LoadImage(Instance, Name, IMAGE_ICON, 0, 0, Flags);
   if Handle <> 0 then begin
   if Handle <> 0 then begin
-    Icon := TIcon.Create;
+    const Icon = TIcon.Create;
     try
     try
       Icon.Handle := Handle;
       Icon.Handle := Handle;
 
 
       { Set sizes (overrides any scaling) }
       { Set sizes (overrides any scaling) }
-      Width := Icon.Width;
-      Height := Icon.Height;
+      FControl.Width := Icon.Width;
+      FControl.Height := Icon.Height;
 
 
       { Draw icon into bitmap }
       { Draw icon into bitmap }
       Bitmap.Canvas.Brush.Color := BkColor;
       Bitmap.Canvas.Brush.Color := BkColor;
-      Bitmap.Width := Width;
-      Bitmap.Height := Height;
+      Bitmap.Width := FControl.Width;
+      Bitmap.Height := FControl.Height;
       Bitmap.Canvas.Draw(0, 0, Icon);
       Bitmap.Canvas.Draw(0, 0, Icon);
 
 
       Result := True;
       Result := True;
@@ -130,173 +173,213 @@ begin
     Result := False;
     Result := False;
 end;
 end;
 
 
+procedure TBitmapImageImplementation.BitmapChanged(Sender: TObject);
+begin
+  StretchedBitmapValid := False;
+  if AutoSize and (Bitmap.Width > 0) and (Bitmap.Height > 0) then
+    FControl.SetBounds(FControl.Left, FControl.Top, Bitmap.Width + AutoSizeExtraWidth,
+      Bitmap.Height + AutoSizeExtraHeight);
+  if (Bitmap.Width >= FControl.Width) and (Bitmap.Height >= FControl.Height) then
+    FControl.ControlStyle := FControl.ControlStyle + [csOpaque] - [csParentBackground]
+  else
+    FControl.ControlStyle := FControl.ControlStyle - [csOpaque] + [csParentBackground];
+  FControl.Invalidate;
+end;
+
+procedure TBitmapImageImplementation.SetAutoSize(Sender: TObject; Value: Boolean);
+begin
+  AutoSize := Value;
+  BitmapChanged(Sender);
+end;
+
+procedure TBitmapImageImplementation.SetBackColor(Sender: TObject; Value: TColor);
+begin
+  if BackColor <> Value then begin
+    BackColor := Value;
+    BitmapChanged(Sender);
+  end;
+end;
+
+procedure TBitmapImageImplementation.SetBitmap(Value: TBitmap);
+begin
+  Bitmap.Assign(Value);
+end;
+
+procedure TBitmapImageImplementation.SetCenter(Sender: TObject; Value: Boolean);
+begin
+  if Center <> Value then begin
+    Center := Value;
+    BitmapChanged(Sender);
+  end;
+end;
+
+procedure TBitmapImageImplementation.SetReplaceColor(Sender: TObject; Value: TColor);
+begin
+  if ReplaceColor <> Value then begin
+    ReplaceColor := Value;
+    BitmapChanged(Sender);
+  end;
+end;
+
+procedure TBitmapImageImplementation.SetReplaceWithColor(Sender: TObject; Value: TColor);
+begin
+  if ReplaceWithColor <> Value then begin
+    ReplaceWithColor := Value;
+    BitmapChanged(Sender);
+  end;
+end;
+
+procedure TBitmapImageImplementation.SetStretch(Sender: TObject; Value: Boolean);
+begin
+  if Stretch <> Value then begin
+    Stretch := Value;
+    StretchedBitmap.Assign(nil);
+    BitmapChanged(Sender);
+  end;
+end;
+
+function TBitmapImageImplementation.GetPalette: HPALETTE;
+begin
+  Result := Bitmap.Palette;
+end;
+
+procedure TBitmapImageImplementation.Paint(const Sender: TObject; const Canvas: TCanvas; var R: TRect);
+begin
+  const Is32bit = (Bitmap.PixelFormat = pf32bit) and
+    (Bitmap.AlphaFormat in [afDefined, afPremultiplied]);
+
+  var W, H: Integer;
+  var Bmp: TBitmap;
+  if Stretch then begin
+    W := R.Width;
+    H := R.Height;
+    Bmp := StretchedBitmap;
+    if not StretchedBitmapValid or (StretchedBitmap.Width <> W) or
+        (StretchedBitmap.Height <> H) then begin
+      StretchedBitmapValid := True;
+      if (Bitmap.Width = W) and (Bitmap.Height = H) then
+        StretchedBitmap.Assign(Bitmap)
+      else begin
+        StretchedBitmap.Assign(nil);
+        if not StretchBmp(Bitmap, StretchedBitmap, W, H, Is32bit) then begin
+          if Is32bit then begin
+            StretchedBitmapValid := False;
+            Bmp := Bitmap;
+          end else begin
+            StretchedBitmap.Palette := CopyPalette(Bitmap.Palette);
+            StretchedBitmap.Width := W;
+            StretchedBitmap.Height := H;
+            StretchedBitmap.Canvas.StretchDraw(Rect(0, 0, W, H), Bitmap);
+          end;
+        end;
+      end;
+    end;
+  end else begin
+    Bmp := Bitmap;
+    W := Bmp.Width;
+    H := Bmp.Height;
+  end;
+
+  if (BackColor <> clNone) and (Is32Bit or (Bmp.Width < FControl.Width) or (Bmp.Height < FControl.Height)) then begin
+    Canvas.Brush.Style := bsSolid;
+    Canvas.Brush.Color := BackColor;
+    Canvas.FillRect(R);
+  end;
+
+  if csDesigning in FControl.ComponentState then begin
+    Canvas.Pen.Style := psDash;
+    Canvas.Brush.Style := bsClear;
+    Canvas.Rectangle(0, 0, FControl.Width, FControl.Height);
+  end;
+
+  var X := R.Left;
+  var Y := R.Top;
+  if Center then begin
+    Inc(X, (R.Width - W) div 2);
+    if X < 0 then
+      X := 0;
+    Inc(Y, (R.Height - H) div 2);
+    if Y < 0 then
+      Y := 0;
+  end;
+
+  if not Is32bit and (ReplaceColor <> clNone) and (ReplaceWithColor <> clNone) then begin
+    Canvas.Brush.Color := ReplaceWithColor;
+    Canvas.BrushCopy(Rect(X, Y, X + W, Y + H), Bmp, Rect(0, 0, Bmp.Width, Bmp.Height), ReplaceColor);
+  end else
+    Canvas.Draw(X, Y, Bmp);
+
+  if Assigned(OnPaint) then
+    OnPaint(Sender, Canvas, R);
+end;
+
+{ TBitmapImage }
+
 constructor TBitmapImage.Create(AOwner: TComponent);
 constructor TBitmapImage.Create(AOwner: TComponent);
 begin
 begin
-  inherited Create(AOwner);
+  inherited;
   ControlStyle := ControlStyle + [csReplicatable];
   ControlStyle := ControlStyle + [csReplicatable];
-  FBackColor := clBtnFace;
-  FBitmap := TBitmap.Create;
-  FBitmap.OnChange := BitmapChanged;
-  FReplaceColor := clNone;
-  FReplaceWithColor := clNone;
-  FStretchedBitmap := TBitmap.Create;
-  Height := 105;
+  FImpl.Init(Self);
+  FImpl.BackColor := clBtnFace;
   Width := 105;
   Width := 105;
+  Height := 105;
 end;
 end;
 
 
 destructor TBitmapImage.Destroy;
 destructor TBitmapImage.Destroy;
 begin
 begin
-  FStretchedBitmap.Free;
-  FBitmap.Free;
-  inherited Destroy;
+  FImpl.DeInit;
+  inherited;
 end;
 end;
 
 
-procedure TBitmapImage.BitmapChanged(Sender: TObject);
+function TBitmapImage.InitializeFromIcon(const Instance: HINST; const Name: PChar; const BkColor: TColor; const AscendingTrySizes: array of Integer): Boolean;
 begin
 begin
-  FStretchedBitmapValid := False;
-  if FAutoSize and (FBitmap.Width > 0) and (FBitmap.Height > 0) then
-    SetBounds(Left, Top, FBitmap.Width, FBitmap.Height);
-  if (FBitmap.Width >= Width) and (FBitmap.Height >= Height) then
-    ControlStyle := ControlStyle + [csOpaque]
-  else
-    ControlStyle := ControlStyle - [csOpaque];
-  Invalidate;
+  Result := FImpl.InitializeFromIcon(HInstance, Name, BkColor, AscendingTrySizes);
 end;
 end;
 
 
 procedure TBitmapImage.SetAutoSize(Value: Boolean);
 procedure TBitmapImage.SetAutoSize(Value: Boolean);
 begin
 begin
-  FAutoSize := Value;
-  BitmapChanged(Self);
+  FImpl.SetAutoSize(Self, Value);
 end;
 end;
 
 
 procedure TBitmapImage.SetBackColor(Value: TColor);
 procedure TBitmapImage.SetBackColor(Value: TColor);
 begin
 begin
-  if FBackColor <> Value then begin
-    FBackColor := Value;
-    BitmapChanged(Self);
-  end;
+  FImpl.SetBackColor(Self, Value);
 end;
 end;
 
 
 procedure TBitmapImage.SetBitmap(Value: TBitmap);
 procedure TBitmapImage.SetBitmap(Value: TBitmap);
 begin
 begin
-  FBitmap.Assign(Value);
+  FImpl.SetBitmap(Value);
 end;
 end;
 
 
 procedure TBitmapImage.SetCenter(Value: Boolean);
 procedure TBitmapImage.SetCenter(Value: Boolean);
 begin
 begin
-  if FCenter <> Value then begin
-    FCenter := Value;
-    BitmapChanged(Self);
-  end;
+  FImpl.SetCenter(Self, Value);
 end;
 end;
 
 
 procedure TBitmapImage.SetReplaceColor(Value: TColor);
 procedure TBitmapImage.SetReplaceColor(Value: TColor);
 begin
 begin
-  if FReplaceColor <> Value then begin
-    FReplaceColor := Value;
-    BitmapChanged(Self);
-  end;
+  FImpl.SetReplaceColor(Self, Value);
 end;
 end;
 
 
 procedure TBitmapImage.SetReplaceWithColor(Value: TColor);
 procedure TBitmapImage.SetReplaceWithColor(Value: TColor);
 begin
 begin
-  if FReplaceWithColor <> Value then begin
-    FReplaceWithColor := Value;
-    BitmapChanged(Self);
-  end;
+  FImpl.SetReplaceWithColor(Self, Value);
 end;
 end;
 
 
 procedure TBitmapImage.SetStretch(Value: Boolean);
 procedure TBitmapImage.SetStretch(Value: Boolean);
 begin
 begin
-  if FStretch <> Value then begin
-    FStretch := Value;
-    FStretchedBitmap.Assign(nil);
-    BitmapChanged(Self);
-  end;
-end;
-
-function TBitmapImage.GetBitmap: TBitmap;
-begin
-  Result := FBitmap;
+  FImpl.SetStretch(Self, Value);
 end;
 end;
 
 
 function TBitmapImage.GetPalette: HPALETTE;
 function TBitmapImage.GetPalette: HPALETTE;
 begin
 begin
-  Result := FBitmap.Palette;
+  Result := FImpl.GetPalette;
 end;
 end;
 
 
 procedure TBitmapImage.Paint;
 procedure TBitmapImage.Paint;
-var
-  R: TRect;
-  Bmp: TBitmap;
-  X, Y, W, H: Integer;
-  Is32bit: Boolean;
 begin
 begin
-  with Canvas do begin
-    R := ClientRect;
-    Is32bit := (FBitmap.PixelFormat = pf32bit) and
-      (FBitmap.AlphaFormat in [afDefined, afPremultiplied]);
-
-    if Stretch then begin
-      W := R.Right;
-      H := R.Bottom;
-      Bmp := FStretchedBitmap;
-      if not FStretchedBitmapValid or (FStretchedBitmap.Width <> W) or
-         (FStretchedBitmap.Height <> H) then begin
-        FStretchedBitmapValid := True;
-        if (FBitmap.Width = W) and (FBitmap.Height = H) then
-          FStretchedBitmap.Assign(FBitmap)
-        else begin
-          FStretchedBitmap.Assign(nil);
-          if not StretchBmp(FBitmap, FStretchedBitmap, W, H, Is32bit) then begin
-            if Is32bit then begin
-              FStretchedBitmapValid := False;
-              Bmp := FBitmap;
-            end else begin
-              FStretchedBitmap.Palette := CopyPalette(FBitmap.Palette);
-              FStretchedBitmap.Width := W;
-              FStretchedBitmap.Height := H;
-              FStretchedBitmap.Canvas.StretchDraw(R, FBitmap);
-            end;
-          end;
-        end;
-      end;
-    end else begin
-      Bmp := FBitmap;
-      W := Bmp.Width;
-      H := Bmp.Height;
-    end;
-
-    if (FBackColor <> clNone) and (Is32Bit or (Bmp.Width < Width) or (Bmp.Height < Height)) then begin
-      Brush.Style := bsSolid;
-      Brush.Color := FBackColor;
-      FillRect(R);
-    end;
-
-    if csDesigning in ComponentState then begin
-      Pen.Style := psDash;
-      Brush.Style := bsClear;
-      Rectangle(0, 0, Width, Height);
-    end;
-
-    if Center then begin
-      X := R.Left + ((R.Right - R.Left) - W) div 2;
-      if X < 0 then
-        X := 0;
-      Y := R.Top + ((R.Bottom - R.Top) - H) div 2;
-      if Y < 0 then
-        Y := 0;
-    end else begin
-      X := 0;
-      Y := 0;
-    end;
-
-    if not Is32bit and (FReplaceColor <> clNone) and (FReplaceWithColor <> clNone) then begin
-      Brush.Color := FReplaceWithColor;
-      BrushCopy(Rect(X, Y, X + W, Y + H), Bmp, Rect(0, 0, Bmp.Width, Bmp.Height), FReplaceColor);
-    end else
-      Draw(X, Y, Bmp);
-  end;
+  var R := ClientRect;
+  FImpl.Paint(Self, Canvas, R);
 end;
 end;
 
 
 end.
 end.

+ 1 - 0
Components/Components.dpk

@@ -38,6 +38,7 @@ requires
 
 
 contains
 contains
   BidiCtrls in 'BidiCtrls.pas',
   BidiCtrls in 'BidiCtrls.pas',
+  BitmapButton in 'BitmapButton.pas',
   BitmapImage in 'BitmapImage.pas',
   BitmapImage in 'BitmapImage.pas',
   DropListBox in 'DropListBox.pas',
   DropListBox in 'DropListBox.pas',
   FolderTreeView in 'FolderTreeView.pas',
   FolderTreeView in 'FolderTreeView.pas',

+ 2 - 2
Components/NewProgressBar.pas

@@ -2,13 +2,13 @@ unit NewProgressBar;
 
 
 {
 {
   Inno Setup
   Inno Setup
-  Copyright (C) 1997-2024 Jordan Russell
+  Copyright (C) 1997-2025 Jordan Russell
   Portions by Martijn Laan
   Portions by Martijn Laan
   For conditions of distribution and use, see LICENSE.TXT.
   For conditions of distribution and use, see LICENSE.TXT.
 
 
   TNewProgressBar component - a smooth 32 bit TProgressBar
   TNewProgressBar component - a smooth 32 bit TProgressBar
 
 
-  Note: themed animated progress bars and don't immediately show changes.
+  Note: themed animated progress bars don't immediately show changes.
   This applies both to Position and State. For example if you set State while the
   This applies both to Position and State. For example if you set State while the
   progress bar is still moving towards a new Position, the new State doesnt show until
   progress bar is still moving towards a new Position, the new State doesnt show until
   the moving animation has finished.
   the moving animation has finished.

+ 36 - 14
Examples/CodeClasses.iss

@@ -27,11 +27,6 @@ begin
   MsgBox('You clicked the button!', mbInformation, mb_Ok);
   MsgBox('You clicked the button!', mbInformation, mb_Ok);
 end;
 end;
 
 
-procedure BitmapImageOnClick(Sender: TObject);
-begin
-  MsgBox('You clicked the image!', mbInformation, mb_Ok);
-end;
-
 procedure FormButtonOnClick(Sender: TObject);
 procedure FormButtonOnClick(Sender: TObject);
 var
 var
   Form: TSetupForm;
   Form: TSetupForm;
@@ -132,6 +127,7 @@ var
   CheckListBox, CheckListBox2: TNewCheckListBox;
   CheckListBox, CheckListBox2: TNewCheckListBox;
   FolderTreeView: TFolderTreeView;
   FolderTreeView: TFolderTreeView;
   BitmapImage, BitmapImage2, BitmapImage3: TBitmapImage;
   BitmapImage, BitmapImage2, BitmapImage3: TBitmapImage;
+  BitmapButton, BitmapButton2: TBitmapButton;
   BitmapFileName: String;
   BitmapFileName: String;
   RichEditViewer: TRichEditViewer;
   RichEditViewer: TRichEditViewer;
 begin
 begin
@@ -353,32 +349,58 @@ begin
   BitmapImage := TBitmapImage.Create(Page);
   BitmapImage := TBitmapImage.Create(Page);
   BitmapImage.AutoSize := True;
   BitmapImage.AutoSize := True;
   BitmapImage.Bitmap.LoadFromFile(BitmapFileName);
   BitmapImage.Bitmap.LoadFromFile(BitmapFileName);
-  BitmapImage.Cursor := crHand;
-  BitmapImage.OnClick := @BitmapImageOnClick;
   BitmapImage.Parent := Page.Surface;
   BitmapImage.Parent := Page.Surface;
 
 
   BitmapImage2 := TBitmapImage.Create(Page);
   BitmapImage2 := TBitmapImage.Create(Page);
-  BitmapImage2.BackColor := $400000;
+  BitmapImage2.BackColor := clNone;
   BitmapImage2.Bitmap := BitmapImage.Bitmap;
   BitmapImage2.Bitmap := BitmapImage.Bitmap;
   BitmapImage2.Center := True;
   BitmapImage2.Center := True;
   BitmapImage2.Left := BitmapImage.Width + 10;
   BitmapImage2.Left := BitmapImage.Width + 10;
-  BitmapImage2.Height := 2*BitmapImage.Height;
   BitmapImage2.Width := 2*BitmapImage.Width;
   BitmapImage2.Width := 2*BitmapImage.Width;
-  BitmapImage2.Cursor := crHand;
-  BitmapImage2.OnClick := @BitmapImageOnClick;
+  BitmapImage2.Height := 2*BitmapImage.Height;
   BitmapImage2.Parent := Page.Surface;
   BitmapImage2.Parent := Page.Surface;
 
 
   BitmapImage3 := TBitmapImage.Create(Page);
   BitmapImage3 := TBitmapImage.Create(Page);
   BitmapImage3.Bitmap := BitmapImage.Bitmap;
   BitmapImage3.Bitmap := BitmapImage.Bitmap;
   BitmapImage3.Stretch := True;
   BitmapImage3.Stretch := True;
   BitmapImage3.Left := 3*BitmapImage.Width + 20;
   BitmapImage3.Left := 3*BitmapImage.Width + 20;
-  BitmapImage3.Height := 4*BitmapImage.Height;
   BitmapImage3.Width := 4*BitmapImage.Width;
   BitmapImage3.Width := 4*BitmapImage.Width;
+  BitmapImage3.Height := 4*BitmapImage.Height;
   BitmapImage3.Anchors := [akLeft, akTop, akRight, akBottom];
   BitmapImage3.Anchors := [akLeft, akTop, akRight, akBottom];
-  BitmapImage3.Cursor := crHand;
-  BitmapImage3.OnClick := @BitmapImageOnClick;
   BitmapImage3.Parent := Page.Surface;
   BitmapImage3.Parent := Page.Surface;
 
 
+  { TBitmapButton - Always has a 2 pixel margin around the image, used to
+    display a focus rectangle. Other changes compared to TBitmapImage are:
+    • Has a Caption property which should always be set
+    • Center defaults to True
+    • BackColor defaults to clNone }
+
+  Page := CreateCustomPage(Page.ID, 'Custom wizard page controls', 'TBitmapButton (Press Alt to see focus rectangle)');
+  
+  BitmapButton := TBitmapButton.Create(Page);
+  BitmapButton.AutoSize := True;
+  BitmapButton.Bitmap := BitmapImage.Bitmap;
+  BitmapButton.Caption := 'Show Message'; { For accessibility }
+  BitmapButton.Hint := 'TBitmapButton is an accessible version of TBitmapImage';
+  BitmapButton.ShowHint := True;
+  BitmapButton.Width := 2*BitmapButton.Width;
+  BitmapButton.Cursor := crHand;
+  BitmapButton.OnClick := @ButtonOnClick;
+  BitmapButton.Parent := Page.Surface;
+
+  BitmapButton2 := TBitmapButton.Create(Page);
+  BitmapButton2.BackColor := $400000;
+  BitmapButton2.Bitmap := BitmapImage.Bitmap;
+  BitmapButton2.Caption := BitmapButton.Caption;
+  BitmapButton2.Hint := BitmapButton.Hint;
+  BitmapButton2.ShowHint := True;
+  BitmapButton2.Left := BitmapButton.Width + 10;
+  BitmapButton2.Width := 2*BitmapButton.Width;
+  BitmapButton2.Height := 2*BitmapButton.Height;
+  BitmapButton2.Cursor := crHand;
+  BitmapButton2.OnClick := @ButtonOnClick;
+  BitmapButton2.Parent := Page.Surface;
+
   { TRichViewer }
   { TRichViewer }
 
 
   Page := CreateCustomPage(Page.ID, 'Custom wizard page controls', 'TRichViewer');
   Page := CreateCustomPage(Page.ID, 'Custom wizard page controls', 'TRichViewer');

+ 14 - 0
ISHelp/isxclasses.pas

@@ -667,6 +667,20 @@ TStartMenuFolderTreeView = class(TCustomFolderTreeView)
   property OnRename: TFolderRenameEvent; read write;
   property OnRename: TFolderRenameEvent; read write;
 end;
 end;
 
 
+TBitmapButton = class(TCustomControl)
+  property Anchors: TAnchors; read write;
+  property AutoSize: Boolean; read write;
+  property BackColor: TColor; read write;
+  property Caption: Boolean; read write;
+  property Center: Boolean; read write;
+  property Bitmap: TBitmap; read write;
+  property ReplaceColor: TColor; read write;
+  property ReplaceWithColor: TColor; read write;
+  property Stretch: Boolean; read write;
+  property OnClick: TNotifyEvent; read write;
+  property OnDblClick: TNotifyEvent; read write;
+end;
+
 TBitmapImage = class(TGraphicControl)
 TBitmapImage = class(TGraphicControl)
   property Anchors: TAnchors; read write;
   property Anchors: TAnchors; read write;
   property AutoSize: Boolean; read write;
   property AutoSize: Boolean; read write;

+ 23 - 23
ISHelp/isxclasses_wordlists_generated.pas

@@ -16,29 +16,29 @@ var
 
 
   PascalTypes_Isxclasses: array of AnsiString = [
   PascalTypes_Isxclasses: array of AnsiString = [
     'HBITMAP', 'TAlign', 'TAlignment', 'TAlphaFormat', 'TAnchorKind', 'TAnchors', 'TBevel',
     'HBITMAP', 'TAlign', 'TAlignment', 'TAlphaFormat', 'TAnchorKind', 'TAnchors', 'TBevel',
-    'TBevelKind', 'TBevelShape', 'TBevelStyle', 'TBevelWidth', 'TBitmap', 'TBitmapImage',
-    'TBorderIcon', 'TBorderIcons', 'TBorderStyle', 'TBorderWidth', 'TBrush', 'TBrushStyle',
-    'TButton', 'TButtonControl', 'TCanvas', 'TCheckBox', 'TCheckBoxState', 'TCheckItemOperation',
-    'TCloseAction', 'TCloseEvent', 'TCloseQueryEvent', 'TColor', 'TComboBox', 'TComboBoxStyle',
-    'TComponent', 'TConstraintSize', 'TControl', 'TCursor', 'TCustomCheckBox', 'TCustomComboBox',
-    'TCustomControl', 'TCustomEdit', 'TCustomFolderTreeView', 'TCustomLabel', 'TCustomLinkLabel',
-    'TCustomListBox', 'TCustomMemo', 'TCustomPanel', 'TDownloadWizardPage', 'TDuplicates',
-    'TEdit', 'TEditCharCase', 'TEShiftState', 'TExtractionWizardPage', 'TFileStream', 'TFolderRenameEvent',
-    'TFolderTreeView', 'TFont', 'TFontStyle', 'TFontStyles', 'TForm', 'TFormBorderStyle',
-    'TFormStyle', 'TGraphic', 'TGraphicControl', 'TGraphicsObject', 'THandleStream', 'TInputDirWizardPage',
-    'TInputFileWizardPage', 'TInputOptionWizardPage', 'TInputQueryWizardPage', 'TKeyEvent',
-    'TKeyPressEvent', 'TLabel', 'TLinkLabel', 'TListBox', 'TListBoxStyle', 'TMemo', 'TNewButton',
-    'TNewCheckBox', 'TNewCheckListBox', 'TNewComboBox', 'TNewEdit', 'TNewLinkLabel', 'TNewListBox',
-    'TNewMemo', 'TNewNotebook', 'TNewNotebookPage', 'TNewProgressBar', 'TNewProgressBarState',
-    'TNewProgressBarStyle', 'TNewRadioButton', 'TNewStaticText', 'TNotifyEvent', 'TObject',
-    'TOutputMarqueeProgressWizardPage', 'TOutputMsgMemoWizardPage', 'TOutputMsgWizardPage',
-    'TOutputProgressWizardPage', 'TPanel', 'TPanelBevel', 'TPasswordEdit', 'TPen', 'TPenMode',
-    'TPenStyle', 'TPersistent', 'TPopupMode', 'TPosition', 'TRadioButton', 'TRichEditViewer',
-    'TScrollingWinControl', 'TScrollStyle', 'TSetupForm', 'TShiftState', 'TSizeConstraints',
-    'TStartMenuFolderTreeView', 'TStream', 'TStringList', 'TStrings', 'TStringStream',
-    'TSysLinkEvent', 'TSysLinkType', 'TUIStateForm', 'TUninstallProgressForm', 'TWinControl',
-    'TWizardForm', 'TWizardPage', 'TWizardPageButtonEvent', 'TWizardPageCancelEvent', 'TWizardPageNotifyEvent',
-    'TWizardPageShouldSkipEvent'
+    'TBevelKind', 'TBevelShape', 'TBevelStyle', 'TBevelWidth', 'TBitmap', 'TBitmapButton',
+    'TBitmapImage', 'TBorderIcon', 'TBorderIcons', 'TBorderStyle', 'TBorderWidth', 'TBrush',
+    'TBrushStyle', 'TButton', 'TButtonControl', 'TCanvas', 'TCheckBox', 'TCheckBoxState',
+    'TCheckItemOperation', 'TCloseAction', 'TCloseEvent', 'TCloseQueryEvent', 'TColor',
+    'TComboBox', 'TComboBoxStyle', 'TComponent', 'TConstraintSize', 'TControl', 'TCursor',
+    'TCustomCheckBox', 'TCustomComboBox', 'TCustomControl', 'TCustomEdit', 'TCustomFolderTreeView',
+    'TCustomLabel', 'TCustomLinkLabel', 'TCustomListBox', 'TCustomMemo', 'TCustomPanel',
+    'TDownloadWizardPage', 'TDuplicates', 'TEdit', 'TEditCharCase', 'TEShiftState', 'TExtractionWizardPage',
+    'TFileStream', 'TFolderRenameEvent', 'TFolderTreeView', 'TFont', 'TFontStyle', 'TFontStyles',
+    'TForm', 'TFormBorderStyle', 'TFormStyle', 'TGraphic', 'TGraphicControl', 'TGraphicsObject',
+    'THandleStream', 'TInputDirWizardPage', 'TInputFileWizardPage', 'TInputOptionWizardPage',
+    'TInputQueryWizardPage', 'TKeyEvent', 'TKeyPressEvent', 'TLabel', 'TLinkLabel', 'TListBox',
+    'TListBoxStyle', 'TMemo', 'TNewButton', 'TNewCheckBox', 'TNewCheckListBox', 'TNewComboBox',
+    'TNewEdit', 'TNewLinkLabel', 'TNewListBox', 'TNewMemo', 'TNewNotebook', 'TNewNotebookPage',
+    'TNewProgressBar', 'TNewProgressBarState', 'TNewProgressBarStyle', 'TNewRadioButton',
+    'TNewStaticText', 'TNotifyEvent', 'TObject', 'TOutputMarqueeProgressWizardPage', 'TOutputMsgMemoWizardPage',
+    'TOutputMsgWizardPage', 'TOutputProgressWizardPage', 'TPanel', 'TPanelBevel', 'TPasswordEdit',
+    'TPen', 'TPenMode', 'TPenStyle', 'TPersistent', 'TPopupMode', 'TPosition', 'TRadioButton',
+    'TRichEditViewer', 'TScrollingWinControl', 'TScrollStyle', 'TSetupForm', 'TShiftState',
+    'TSizeConstraints', 'TStartMenuFolderTreeView', 'TStream', 'TStringList', 'TStrings',
+    'TStringStream', 'TSysLinkEvent', 'TSysLinkType', 'TUIStateForm', 'TUninstallProgressForm',
+    'TWinControl', 'TWizardForm', 'TWizardPage', 'TWizardPageButtonEvent', 'TWizardPageCancelEvent',
+    'TWizardPageNotifyEvent', 'TWizardPageShouldSkipEvent'
   ];
   ];
 
 
   PascalEnumValues_Isxclasses: array of AnsiString = [
   PascalEnumValues_Isxclasses: array of AnsiString = [

+ 7 - 1
ISHelp/isxfunc.xml

@@ -1931,7 +1931,7 @@ end;</pre></example>
         <prototype>procedure MapArchiveExtensions(const DestExt, SourceExt: String);</prototype>
         <prototype>procedure MapArchiveExtensions(const DestExt, SourceExt: String);</prototype>
         <description><p>Allows files with a specified destination extension, such as .exe, to be treated as if they have a different source extension, such as .7z, for extraction purposes.</p>
         <description><p>Allows files with a specified destination extension, such as .exe, to be treated as if they have a different source extension, such as .7z, for extraction purposes.</p>
 <p>An exception will be raised if there was an error.</p></description>
 <p>An exception will be raised if there was an error.</p></description>
-        <remarks><p>Calls to this function are ignored if the <link topic="setup_archiveextraction">ArchiveExtraction</link> [Setup] section directive is set to <tt>basic</tt>.</p></remarks>
+        <remarks><p>Calls to this function are ignored if the <link topic="setup_archiveextraction">ArchiveExtraction</link> [Setup] section directive is set to <tt>basic</tt>. In this case files as always extracted as .7z, regardless of the extension.</p></remarks>
         <seealso><p><link topic="isxfunc_ExtractArchive">ExtractArchive</link><br/>
         <seealso><p><link topic="isxfunc_ExtractArchive">ExtractArchive</link><br/>
 <link topic="isxfunc_CreateExtractionPage">CreateExtractionPage</link></p></seealso>
 <link topic="isxfunc_CreateExtractionPage">CreateExtractionPage</link></p></seealso>
         <example><pre>
         <example><pre>
@@ -2818,6 +2818,12 @@ end;</pre></example>
         <prototype>function ScaleY(Y: Integer): Integer;</prototype>
         <prototype>function ScaleY(Y: Integer): Integer;</prototype>
         <description><p>Takes a Y coordinate or height and returns it scaled to fit the size of the current dialog font. If the dialog font is 8-point MS Sans Serif and the user is running Windows in 100% DPI (96 dpi), then Y is returned unchanged.</p></description>
         <description><p>Takes a Y coordinate or height and returns it scaled to fit the size of the current dialog font. If the dialog font is 8-point MS Sans Serif and the user is running Windows in 100% DPI (96 dpi), then Y is returned unchanged.</p></description>
       </function>
       </function>
+      <function>
+        <name>InitializeBitmapButtonFromIcon</name>
+        <prototype>function InitializeBitmapButtonFromIcon(const BitmapButton: TBitmapButton; const IconFilename: String; const BkColor: TColor; const AscendingTrySizes: TArrayOfInteger): Boolean;</prototype>
+        <description><p>Initializes the given bitmap button with an icon from the given icon file using the given background color for transparent parts.</p>
+<p>See <link topic="isxfunc_InitializeBitmapImageFromIcon">InitializeBitmapImageFromIcon</link> for more information.</p></description>
+      </function>
       <function>
       <function>
         <name>InitializeBitmapImageFromIcon</name>
         <name>InitializeBitmapImageFromIcon</name>
         <prototype>function InitializeBitmapImageFromIcon(const BitmapImage: TBitmapImage; const IconFilename: String; const BkColor: TColor; const AscendingTrySizes: TArrayOfInteger): Boolean;</prototype>
         <prototype>function InitializeBitmapImageFromIcon(const BitmapImage: TBitmapImage; const IconFilename: String; const BkColor: TColor; const AscendingTrySizes: TArrayOfInteger): Boolean;</prototype>

+ 3 - 0
Projects/Compil32.dpr

@@ -47,6 +47,8 @@ uses
   NewStaticText in '..\Components\NewStaticText.pas',
   NewStaticText in '..\Components\NewStaticText.pas',
   BidiUtils in '..\Components\BidiUtils.pas',
   BidiUtils in '..\Components\BidiUtils.pas',
   DropListBox in '..\Components\DropListBox.pas',
   DropListBox in '..\Components\DropListBox.pas',
+  BitmapButton in '..\Components\BitmapButton.pas',
+  BitmapImage in '..\Components\BitmapImage.pas',
   NewCheckListBox in '..\Components\NewCheckListBox.pas',
   NewCheckListBox in '..\Components\NewCheckListBox.pas',
   NewNotebook in '..\Components\NewNotebook.pas',
   NewNotebook in '..\Components\NewNotebook.pas',
   TaskbarProgressFunc in '..\Components\TaskbarProgressFunc.pas',
   TaskbarProgressFunc in '..\Components\TaskbarProgressFunc.pas',
@@ -73,6 +75,7 @@ uses
   ECDSA in '..\Components\ECDSA.pas',
   ECDSA in '..\Components\ECDSA.pas',
   ISSigFunc in '..\Components\ISSigFunc.pas',
   ISSigFunc in '..\Components\ISSigFunc.pas',
   StringScanner in '..\Components\StringScanner.pas',
   StringScanner in '..\Components\StringScanner.pas',
+  Resample in '..\Components\Resample.pas',
   VCL.Styles,
   VCL.Styles,
   VCL.Themes;
   VCL.Themes;
 
 

+ 3 - 0
Projects/Compil32.dproj

@@ -127,6 +127,8 @@
         <DCCReference Include="..\Components\NewStaticText.pas"/>
         <DCCReference Include="..\Components\NewStaticText.pas"/>
         <DCCReference Include="..\Components\BidiUtils.pas"/>
         <DCCReference Include="..\Components\BidiUtils.pas"/>
         <DCCReference Include="..\Components\DropListBox.pas"/>
         <DCCReference Include="..\Components\DropListBox.pas"/>
+        <DCCReference Include="..\Components\BitmapButton.pas"/>
+        <DCCReference Include="..\Components\BitmapImage.pas"/>
         <DCCReference Include="..\Components\NewCheckListBox.pas"/>
         <DCCReference Include="..\Components\NewCheckListBox.pas"/>
         <DCCReference Include="..\Components\NewNotebook.pas"/>
         <DCCReference Include="..\Components\NewNotebook.pas"/>
         <DCCReference Include="..\Components\TaskbarProgressFunc.pas"/>
         <DCCReference Include="..\Components\TaskbarProgressFunc.pas"/>
@@ -159,6 +161,7 @@
         <DCCReference Include="..\Components\ECDSA.pas"/>
         <DCCReference Include="..\Components\ECDSA.pas"/>
         <DCCReference Include="..\Components\ISSigFunc.pas"/>
         <DCCReference Include="..\Components\ISSigFunc.pas"/>
         <DCCReference Include="..\Components\StringScanner.pas"/>
         <DCCReference Include="..\Components\StringScanner.pas"/>
+        <DCCReference Include="..\Components\Resample.pas"/>
         <BuildConfiguration Include="Base">
         <BuildConfiguration Include="Base">
             <Key>Base</Key>
             <Key>Base</Key>
         </BuildConfiguration>
         </BuildConfiguration>

+ 1 - 0
Projects/Setup.dpr

@@ -75,6 +75,7 @@ uses
   BidiUtils in '..\Components\BidiUtils.pas',
   BidiUtils in '..\Components\BidiUtils.pas',
   PathFunc in '..\Components\PathFunc.pas',
   PathFunc in '..\Components\PathFunc.pas',
   BidiCtrls in '..\Components\BidiCtrls.pas',
   BidiCtrls in '..\Components\BidiCtrls.pas',
+  BitmapButton in '..\Components\BitmapButton.pas',
   BitmapImage in '..\Components\BitmapImage.pas',
   BitmapImage in '..\Components\BitmapImage.pas',
   FolderTreeView in '..\Components\FolderTreeView.pas',
   FolderTreeView in '..\Components\FolderTreeView.pas',
   NewCheckListBox in '..\Components\NewCheckListBox.pas',
   NewCheckListBox in '..\Components\NewCheckListBox.pas',

+ 1 - 0
Projects/Setup.dproj

@@ -148,6 +148,7 @@
         <DCCReference Include="..\Components\BidiUtils.pas"/>
         <DCCReference Include="..\Components\BidiUtils.pas"/>
         <DCCReference Include="..\Components\PathFunc.pas"/>
         <DCCReference Include="..\Components\PathFunc.pas"/>
         <DCCReference Include="..\Components\BidiCtrls.pas"/>
         <DCCReference Include="..\Components\BidiCtrls.pas"/>
+        <DCCReference Include="..\Components\BitmapButton.pas"/>
         <DCCReference Include="..\Components\BitmapImage.pas"/>
         <DCCReference Include="..\Components\BitmapImage.pas"/>
         <DCCReference Include="..\Components\FolderTreeView.pas"/>
         <DCCReference Include="..\Components\FolderTreeView.pas"/>
         <DCCReference Include="..\Components\NewCheckListBox.pas"/>
         <DCCReference Include="..\Components\NewCheckListBox.pas"/>

+ 20 - 1
Projects/Src/Compiler.ScriptClasses.pas

@@ -229,13 +229,31 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure RegisterBitmapImage_C(Cl: TPSPascalCompiler);
+procedure RegisterBitmapButton_C(Cl: TPSPascalCompiler);
 begin
 begin
   Cl.AddTypeS('TAlphaFormat', '(afIgnored, afDefined, afPremultiplied)');
   Cl.AddTypeS('TAlphaFormat', '(afIgnored, afDefined, afPremultiplied)');
   with Cl.FindClass('TBitmap') do
   with Cl.FindClass('TBitmap') do
   begin
   begin
     RegisterProperty('AlphaFormat', 'TAlphaFormat', iptrw);
     RegisterProperty('AlphaFormat', 'TAlphaFormat', iptrw);
   end;
   end;
+  with Cl.AddClassN(CL.FindClass('TCustomControl'),'TBitmapButton') do
+  begin
+    RegisterProperty('Anchors', 'TAnchors', iptrw);
+    RegisterProperty('AutoSize', 'Boolean', iptrw);
+    RegisterProperty('BackColor', 'TColor', iptrw);
+    RegisterProperty('Caption', 'String', iptrw);
+    RegisterProperty('Center', 'Boolean', iptrw);
+    RegisterProperty('Bitmap', 'TBitmap', iptrw);
+    RegisterProperty('ReplaceColor', 'TColor', iptrw);
+    RegisterProperty('ReplaceWithColor', 'TColor', iptrw);
+    RegisterProperty('Stretch', 'Boolean', iptrw);
+    RegisterProperty('OnClick', 'TNotifyEvent', iptrw);
+    RegisterProperty('OnDblClick', 'TNotifyEvent', iptrw);
+  end;
+end;
+
+procedure RegisterBitmapImage_C(Cl: TPSPascalCompiler);
+begin
   with Cl.AddClassN(CL.FindClass('TGraphicControl'),'TBitmapImage') do
   with Cl.AddClassN(CL.FindClass('TGraphicControl'),'TBitmapImage') do
   begin
   begin
     RegisterProperty('Anchors', 'TAnchors', iptrw);
     RegisterProperty('Anchors', 'TAnchors', iptrw);
@@ -663,6 +681,7 @@ begin
   RegisterCustomFolderTreeView_C(Cl);
   RegisterCustomFolderTreeView_C(Cl);
   RegisterFolderTreeView_C(Cl);
   RegisterFolderTreeView_C(Cl);
   RegisterStartMenuFolderTreeView_C(Cl);
   RegisterStartMenuFolderTreeView_C(Cl);
+  RegisterBitmapButton_C(Cl);
   RegisterBitmapImage_C(Cl);
   RegisterBitmapImage_C(Cl);
   RegisterBidiCtrls_C(Cl);
   RegisterBidiCtrls_C(Cl);
 
 

+ 39 - 28
Projects/Src/Compression.SevenZipDLLDecoder.pas

@@ -75,11 +75,10 @@ type
   TSequentialOutStream = class(TInterfacedObject, ISequentialOutStream)
   TSequentialOutStream = class(TInterfacedObject, ISequentialOutStream)
   private
   private
     FFile: TFile;
     FFile: TFile;
-    FOwnsFile: Boolean;
   protected
   protected
     function Write(data: Pointer; size: UInt32; processedSize: PUInt32): HRESULT; stdcall;
     function Write(data: Pointer; size: UInt32; processedSize: PUInt32): HRESULT; stdcall;
   public
   public
-    constructor Create(const AFile: TFile; const AOwnsFile: Boolean = True);
+    constructor Create(const AFileToBeDuplicated: TFile);
     destructor Destroy; override;
     destructor Destroy; override;
   end;
   end;
 
 
@@ -210,6 +209,7 @@ type
       const Password: String; const Index: UInt32; const DestF: TFile;
       const Password: String; const Index: UInt32; const DestF: TFile;
       const OnExtractToHandleProgress: TOnExtractToHandleProgress;
       const OnExtractToHandleProgress: TOnExtractToHandleProgress;
       const OnExtractToHandleProgressParam: Integer64);
       const OnExtractToHandleProgressParam: Integer64);
+    destructor Destroy; override;
   end;
   end;
 
 
 { Helper functions }
 { Helper functions }
@@ -274,11 +274,11 @@ begin
 end;
 end;
 
 
 function GetProperty(const InArchive: IInArchive; index: UInt32; propID: PROPID;
 function GetProperty(const InArchive: IInArchive; index: UInt32; propID: PROPID;
-  out value: Integer64): Boolean; overload;
+  out value: UInt64): Boolean; overload;
 begin
 begin
   var varValue: OleVariant;
   var varValue: OleVariant;
   Result := GetProperty(InArchive, index, propID, [varUInt64], varValue);
   Result := GetProperty(InArchive, index, propID, [varUInt64], varValue);
-  value := Integer64(UInt64(varValue));
+  value := varValue;
 end;
 end;
 
 
 function GetProperty(const InArchive: IInArchive; index: UInt32; propID: PROPID;
 function GetProperty(const InArchive: IInArchive; index: UInt32; propID: PROPID;
@@ -334,9 +334,11 @@ function TInStream.Seek(offset: Int64; seekOrigin: UInt32;
 begin
 begin
   try
   try
     case seekOrigin of
     case seekOrigin of
-      STREAM_SEEK_SET: FFile.Seek64(Integer64(offset));
-      STREAM_SEEK_CUR: FFile.Seek64(Integer64(Int64(FFile.Position) + offset));
-      STREAM_SEEK_END: FFile.Seek64(Integer64(Int64(FFile.Size) + offset));
+      STREAM_SEEK_SET: FFile.Seek(offset);
+      STREAM_SEEK_CUR: FFile.Seek(FFile.Position + offset);
+      STREAM_SEEK_END: FFile.Seek(FFile.Size + offset);
+    else
+      Exit(E_INVALIDARG);
     end;
     end;
     if newPosition <> nil then
     if newPosition <> nil then
       newPosition^ := UInt64(FFile.Position);
       newPosition^ := UInt64(FFile.Position);
@@ -351,17 +353,15 @@ end;
 
 
 { TSequentialOutStream }
 { TSequentialOutStream }
 
 
-constructor TSequentialOutStream.Create(const AFile: TFile; const AOwnsFile: Boolean);
+constructor TSequentialOutStream.Create(const AFileToBeDuplicated: TFile);
 begin
 begin
   inherited Create;
   inherited Create;
-  FFile := AFile;
-  FOwnsFile := AOwnsFile;
+  FFile := TFile.CreateDuplicate(AFileToBeDuplicated);
 end;
 end;
 
 
 destructor TSequentialOutStream.Destroy;
 destructor TSequentialOutStream.Destroy;
 begin
 begin
-  if FOwnsFile then
-    FFile.Free;
+  FFile.Free;
   inherited;
   inherited;
 end;
 end;
 
 
@@ -756,16 +756,21 @@ begin
            (ExistingFileAttr and FILE_ATTRIBUTE_READONLY <> 0) then
            (ExistingFileAttr and FILE_ATTRIBUTE_READONLY <> 0) then
           SetFileAttributesRedir(FDisableFsRedir, NewCurrent.ExpandedPath, ExistingFileAttr and not FILE_ATTRIBUTE_READONLY);
           SetFileAttributesRedir(FDisableFsRedir, NewCurrent.ExpandedPath, ExistingFileAttr and not FILE_ATTRIBUTE_READONLY);
         const DestF = TFileRedir.Create(FDisableFsRedir, NewCurrent.ExpandedPath, fdCreateAlways, faWrite, fsNone);
         const DestF = TFileRedir.Create(FDisableFsRedir, NewCurrent.ExpandedPath, fdCreateAlways, faWrite, fsNone);
-        var BytesLeft: Integer64;
-        if GetProperty(FInArchive, index, kpidSize, BytesLeft) then begin
-          { To avoid file system fragmentation, preallocate all of the bytes in the
-            destination file }
-          DestF.Seek64(BytesLeft);
-          DestF.Truncate;
-          DestF.Seek(0);
+        try
+          var BytesLeft: UInt64;
+          if GetProperty(FInArchive, index, kpidSize, BytesLeft) then begin
+            { To avoid file system fragmentation, preallocate all of the bytes in the
+              destination file }
+            DestF.Seek(Int64(BytesLeft));
+            DestF.Truncate;
+            DestF.Seek(0);
+          end;
+          { From IArchive.h: can also set outstream to nil to tell 7zip to skip the file }
+          outstream := TSequentialOutStream.Create(DestF);
+        finally
+          { TSequentialOutStream duplicates the TFile, so DestF is no longer needed }
+          DestF.Free;
         end;
         end;
-        { From IArchive.h: can also set outstream to nil to tell 7zip to skip the file }
-        outstream := TSequentialOutStream.Create(DestF);
         NewCurrent.outStream := outStream;
         NewCurrent.outStream := outStream;
       end;
       end;
     end;
     end;
@@ -852,11 +857,17 @@ constructor TArchiveExtractToHandleCallback.Create(const InArchive: IInArchive;
 begin
 begin
   inherited Create(InArchive, numItems, Password);
   inherited Create(InArchive, numItems, Password);
   FIndex := Index;
   FIndex := Index;
-  FDestF := DestF;
+  FDestF := TFile.CreateDuplicate(DestF);
   FOnExtractToHandleProgress := OnExtractToHandleProgress;
   FOnExtractToHandleProgress := OnExtractToHandleProgress;
   FOnExtractToHandleProgressParam := OnExtractToHandleProgressParam;
   FOnExtractToHandleProgressParam := OnExtractToHandleProgressParam;
 end;
 end;
 
 
+destructor TArchiveExtractToHandleCallback.Destroy;
+begin
+  FDestF.Free;
+  inherited;
+end;
+
 function TArchiveExtractToHandleCallback.GetIndices: TArchiveExtractBaseCallback.TArrayOfUInt32;
 function TArchiveExtractToHandleCallback.GetIndices: TArchiveExtractBaseCallback.TArrayOfUInt32;
 begin
 begin
   SetLength(Result, 1);
   SetLength(Result, 1);
@@ -874,15 +885,15 @@ begin
       GetProperty(FInArchive, index, kpidIsDir, IsDir);
       GetProperty(FInArchive, index, kpidIsDir, IsDir);
       if IsDir then
       if IsDir then
         OleError(E_INVALIDARG);
         OleError(E_INVALIDARG);
-      var BytesLeft: Integer64;
+      var BytesLeft: UInt64;
       if GetProperty(FInArchive, index, kpidSize, BytesLeft) then begin
       if GetProperty(FInArchive, index, kpidSize, BytesLeft) then begin
         { To avoid file system fragmentation, preallocate all of the bytes in the
         { To avoid file system fragmentation, preallocate all of the bytes in the
           destination file }
           destination file }
-        FDestF.Seek64(BytesLeft);
+        FDestF.Seek(Int64(BytesLeft));
         FDestF.Truncate;
         FDestF.Truncate;
         FDestF.Seek(0);
         FDestF.Seek(0);
       end;
       end;
-      outstream := TSequentialOutStream.Create(FDestF, False);
+      outstream := TSequentialOutStream.Create(FDestF);
     end;
     end;
     Result := S_OK;
     Result := S_OK;
   except
   except
@@ -1137,10 +1148,10 @@ begin
     FindData.dwFileAttributes := FindData.dwFileAttributes or Attrib;
     FindData.dwFileAttributes := FindData.dwFileAttributes or Attrib;
     GetProperty(InArchive, currentIndex, kpidCTime, FindData.ftCreationTime);
     GetProperty(InArchive, currentIndex, kpidCTime, FindData.ftCreationTime);
     GetProperty(InArchive, currentIndex, kpidMTime, FindData.ftLastWriteTime);
     GetProperty(InArchive, currentIndex, kpidMTime, FindData.ftLastWriteTime);
-    var Size: Integer64;
+    var Size: UInt64;
     GetProperty(InArchive, currentIndex, kpidSize, Size);
     GetProperty(InArchive, currentIndex, kpidSize, Size);
-    FindData.nFileSizeHigh := Size.Hi;
-    FindData.nFileSizeLow := Size.Lo;
+    FindData.nFileSizeHigh := Int64Rec(Size).Hi;
+    FindData.nFileSizeLow := Int64Rec(Size).Lo;
   end;
   end;
 end;
 end;
 
 

+ 9 - 9
Projects/Src/IDE.InputQueryMemoForm.dfm

@@ -27,15 +27,15 @@ object InputQueryMemoForm: TInputQueryMemoForm
     Caption = '...'
     Caption = '...'
     FocusControl = ValueControl
     FocusControl = ValueControl
   end
   end
-  object DocImage: TImage
-    Left = 8
-    Top = 115
-    Width = 16
-    Height = 16
+  object DocBitBtn: TBitmapButton
+    Left = 6
+    Top = 113
+    Width = 20
+    Height = 20
     Cursor = crHandPoint
     Cursor = crHandPoint
     Anchors = [akLeft, akBottom]
     Anchors = [akLeft, akBottom]
-    AutoSize = True
-    Transparent = True
+    Caption = 'Help'
+    TabOrder = 1
   end
   end
   object OKButton: TButton
   object OKButton: TButton
     Left = 421
     Left = 421
@@ -46,7 +46,7 @@ object InputQueryMemoForm: TInputQueryMemoForm
     Caption = 'OK'
     Caption = 'OK'
     Default = True
     Default = True
     ModalResult = 1
     ModalResult = 1
-    TabOrder = 1
+    TabOrder = 2
   end
   end
   object CancelButton: TButton
   object CancelButton: TButton
     Left = 501
     Left = 501
@@ -57,7 +57,7 @@ object InputQueryMemoForm: TInputQueryMemoForm
     Cancel = True
     Cancel = True
     Caption = 'Cancel'
     Caption = 'Cancel'
     ModalResult = 2
     ModalResult = 2
-    TabOrder = 2
+    TabOrder = 3
   end
   end
   object ValueControl: TMemo
   object ValueControl: TMemo
     Left = 279
     Left = 279

+ 12 - 12
Projects/Src/IDE.InputQueryMemoForm.pas

@@ -2,7 +2,7 @@ unit IDE.InputQueryMemoForm;
 
 
 {
 {
   Inno Setup
   Inno Setup
-  Copyright (C) 1997-2020 Jordan Russell
+  Copyright (C) 1997-2025 Jordan Russell
   Portions by Martijn Laan
   Portions by Martijn Laan
   For conditions of distribution and use, see LICENSE.TXT.
   For conditions of distribution and use, see LICENSE.TXT.
 
 
@@ -14,7 +14,7 @@ unit IDE.InputQueryMemoForm;
 interface
 interface
 
 
 uses
 uses
-  Classes, Controls, StdCtrls, UIStateForm, Vcl.ExtCtrls;
+  Classes, Controls, StdCtrls, UIStateForm, ExtCtrls, BitmapButton;
 
 
 type
 type
   TInputQueryMemoForm = class(TUIStateForm)
   TInputQueryMemoForm = class(TUIStateForm)
@@ -22,7 +22,7 @@ type
     CancelButton: TButton;
     CancelButton: TButton;
     PromptLabel: TLabel;
     PromptLabel: TLabel;
     ValueControl: TMemo;
     ValueControl: TMemo;
-    DocImage: TImage;
+    DocBitBtn: TBitmapButton;
     procedure FormCreate(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure ValueControlKeyPress(Sender: TObject; var Key: Char);
     procedure ValueControlKeyPress(Sender: TObject; var Key: Char);
     procedure ValueControlChange(Sender: TObject);
     procedure ValueControlChange(Sender: TObject);
@@ -36,16 +36,16 @@ type
     procedure SetPrompt(const APrompt: String);
     procedure SetPrompt(const APrompt: String);
     procedure SetValue(const AValue: String);
     procedure SetValue(const AValue: String);
     procedure UpdateImages;
     procedure UpdateImages;
-    procedure SetDocImageClick(const Value: TNotifyEvent);
+    procedure SetDocBitBtnClick(const Value: TNotifyEvent);
   public
   public
-    property DocImageClick: TNotifyEvent write SetDocImageClick;
+    property DocBitBtnClick: TNotifyEvent write SetDocBitBtnClick;
     property Prompt: String write SetPrompt;
     property Prompt: String write SetPrompt;
     property SingleLine: Boolean write FSingleLine;
     property SingleLine: Boolean write FSingleLine;
     property Value: String read GetValue write SetValue;
     property Value: String read GetValue write SetValue;
   end;
   end;
 
 
 function InputQueryMemo(const ACaption, APrompt: String; var AValue: String;
 function InputQueryMemo(const ACaption, APrompt: String; var AValue: String;
-  const ASingleLine: Boolean = False; const ADocImageClick: TNotifyEvent = nil): Boolean;
+  const ASingleLine: Boolean = False; const ADocBitBtnClick: TNotifyEvent = nil): Boolean;
 
 
 implementation
 implementation
 
 
@@ -56,14 +56,14 @@ uses
 {$R *.DFM}
 {$R *.DFM}
 
 
 function InputQueryMemo(const ACaption, APrompt: String; var AValue: String;
 function InputQueryMemo(const ACaption, APrompt: String; var AValue: String;
-  const ASingleLine: Boolean; const ADocImageClick: TNotifyEvent): Boolean;
+  const ASingleLine: Boolean; const ADocBitBtnClick: TNotifyEvent): Boolean;
 begin
 begin
   with TInputQueryMemoForm.Create(Application) do try
   with TInputQueryMemoForm.Create(Application) do try
     Caption := ACaption;
     Caption := ACaption;
     Prompt := APrompt;
     Prompt := APrompt;
     Value := AValue;
     Value := AValue;
     SingleLine := ASingleLine;
     SingleLine := ASingleLine;
-    DocImageClick := ADocImageClick;
+    DocBitBtnClick := ADocBitBtnClick;
     if ShowModal = mrOk then begin
     if ShowModal = mrOk then begin
       AValue := Value;
       AValue := Value;
       Result := True;
       Result := True;
@@ -92,10 +92,10 @@ begin
   Result := ValueControl.Text;
   Result := ValueControl.Text;
 end;
 end;
 
 
-procedure TInputQueryMemoForm.SetDocImageClick(const Value: TNotifyEvent);
+procedure TInputQueryMemoForm.SetDocBitBtnClick(const Value: TNotifyEvent);
 begin
 begin
-  DocImage.OnClick := Value;
-  DocImage.Visible := Assigned(DocImage.OnClick);
+  DocBitBtn.OnClick := Value;
+  DocBitBtn.Visible := Assigned(DocBitBtn.OnClick);
 end;
 end;
 
 
 procedure TInputQueryMemoForm.SetPrompt(const APrompt: String);
 procedure TInputQueryMemoForm.SetPrompt(const APrompt: String);
@@ -149,7 +149,7 @@ procedure TInputQueryMemoForm.UpdateImages;
 begin
 begin
  { After a DPI change the button's Width and Height isn't yet updated, so calculate it ourselves }
  { After a DPI change the button's Width and Height isn't yet updated, so calculate it ourselves }
   var WH := MulDiv(16, CurrentPPI, 96);
   var WH := MulDiv(16, CurrentPPI, 96);
-  DocImage.Picture.Graphic:= GetImage(MainForm.HelpButton, WH);
+  DocBitBtn.Bitmap.Assign(GetImage(MainForm.HelpButton, WH));
 end;
 end;
 
 
 end.
 end.

+ 23 - 18
Projects/Src/IDE.MainForm.dfm

@@ -373,33 +373,38 @@ object MainForm: TMainForm
     TabOrder = 1
     TabOrder = 1
     Visible = False
     Visible = False
     StyleName = 'Windows'
     StyleName = 'Windows'
-    object UpdatePanelClosePaintBox: TPaintBox
+    object UpdatePanelCloseBitBtn: TBitmapButton
       AlignWithMargins = True
       AlignWithMargins = True
-      Left = 330
-      Top = 10
-      Width = 21
-      Height = 21
-      Margins.Top = 10
-      Margins.Right = 10
-      Margins.Bottom = 10
+      Left = 328
+      Top = 8
+      Width = 25
+      Height = 25
+      Margins.Top = 8
+      Margins.Right = 8
+      Margins.Bottom = 8
       Align = alRight
       Align = alRight
-      OnClick = UpdatePanelClosePaintBoxClick
-      OnPaint = UpdatePanelClosePaintBoxPaint
+      Caption = 'Close Banner'
+      TabOrder = 1
+      OnClick = UpdatePanelCloseBitBtnClick
+      OnPaint = UpdatePanelCloseBitBtnPaint
     end
     end
-    object UpdatePanelDonateImage: TImage
+    object UpdatePanelDonateBitBtn: TBitmapButton
       AlignWithMargins = True
       AlignWithMargins = True
-      Left = 303
-      Top = 10
-      Width = 21
-      Height = 21
+      Left = 300
+      Top = 8
+      Width = 25
+      Height = 25
       Cursor = crHandPoint
       Cursor = crHandPoint
-      Margins.Top = 10
-      Margins.Bottom = 10
+      Margins.Top = 8
+      Margins.Right = 0
+      Margins.Bottom = 8
       Align = alRight
       Align = alRight
+      Caption = 'Donate'
       Center = True
       Center = True
       ParentShowHint = False
       ParentShowHint = False
       ShowHint = True
       ShowHint = True
-      OnClick = UpdatePanelDonateImageClick
+      TabOrder = 2
+      OnClick = UpdatePanelDonateBitBtnClick
     end
     end
     object UpdateLinkLabel: TLinkLabel
     object UpdateLinkLabel: TLinkLabel
       Left = 13
       Left = 13

+ 21 - 20
Projects/Src/IDE.MainForm.pas

@@ -26,7 +26,7 @@ uses
   Generics.Collections, UIStateForm, StdCtrls, ExtCtrls, Menus, Buttons, ComCtrls, CommCtrl,
   Generics.Collections, UIStateForm, StdCtrls, ExtCtrls, Menus, Buttons, ComCtrls, CommCtrl,
   ScintInt, ScintEdit, IDE.ScintStylerInnoSetup, NewTabSet, ModernColors, IDE.IDEScintEdit,
   ScintInt, ScintEdit, IDE.ScintStylerInnoSetup, NewTabSet, ModernColors, IDE.IDEScintEdit,
   Shared.DebugStruct, Shared.CompilerInt.Struct, NewUxTheme, ImageList, ImgList, ToolWin, IDE.HelperFunc,
   Shared.DebugStruct, Shared.CompilerInt.Struct, NewUxTheme, ImageList, ImgList, ToolWin, IDE.HelperFunc,
-  VirtualImageList, BaseImageCollection;
+  VirtualImageList, BaseImageCollection, BitmapButton;
 
 
 const
 const
   WM_StartCommandLineCompile = WM_USER + $1000;
   WM_StartCommandLineCompile = WM_USER + $1000;
@@ -263,8 +263,8 @@ type
     EFindRegEx: TMenuItem;
     EFindRegEx: TMenuItem;
     UpdatePanel: TPanel;
     UpdatePanel: TPanel;
     UpdateLinkLabel: TLinkLabel;
     UpdateLinkLabel: TLinkLabel;
-    UpdatePanelClosePaintBox: TPaintBox;
-    UpdatePanelDonateImage: TImage;
+    UpdatePanelCloseBitBtn: TBitmapButton;
+    UpdatePanelDonateBitBtn: TBitmapButton;
     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
     procedure FExitClick(Sender: TObject);
     procedure FExitClick(Sender: TObject);
     procedure FOpenMainFileClick(Sender: TObject);
     procedure FOpenMainFileClick(Sender: TObject);
@@ -389,9 +389,9 @@ type
     procedure EFindRegExClick(Sender: TObject);
     procedure EFindRegExClick(Sender: TObject);
     procedure UpdateLinkLabelLinkClick(Sender: TObject; const Link: string;
     procedure UpdateLinkLabelLinkClick(Sender: TObject; const Link: string;
       LinkType: TSysLinkType);
       LinkType: TSysLinkType);
-    procedure UpdatePanelClosePaintBoxPaint(Sender: TObject);
-    procedure UpdatePanelClosePaintBoxClick(Sender: TObject);
-    procedure UpdatePanelDonateImageClick(Sender: TObject);
+    procedure UpdatePanelCloseBitBtnPaint(Sender: TObject; Canvas: TCanvas; var ARect: TRect);
+    procedure UpdatePanelCloseBitBtnClick(Sender: TObject);
+    procedure UpdatePanelDonateBitBtnClick(Sender: TObject);
   private
   private
     { Private declarations }
     { Private declarations }
     FMemos: TList<TIDEScintEdit>;                      { FMemos[0] is the main memo and FMemos[1] the preprocessor output memo - also see MemosTabSet comment above }
     FMemos: TList<TIDEScintEdit>;                      { FMemos[0] is the main memo and FMemos[1] the preprocessor output memo - also see MemosTabSet comment above }
@@ -1015,7 +1015,7 @@ begin
 
 
   ToolBarPanel.ParentBackground := False;
   ToolBarPanel.ParentBackground := False;
   UpdatePanel.ParentBackground := False;
   UpdatePanel.ParentBackground := False;
-  UpdatePanelDonateImage.Hint := RemoveAccelChar(HDonate.Caption);
+  UpdatePanelDonateBitBtn.Hint := RemoveAccelChar(HDonate.Caption);
 
 
   UpdateImages;
   UpdateImages;
 
 
@@ -1033,6 +1033,7 @@ begin
   FHiddenFiles := TStringList.Create(dupError, True, True);
   FHiddenFiles := TStringList.Create(dupError, True, True);
   FActiveMemo := FMainMemo;
   FActiveMemo := FMainMemo;
   FActiveMemo.Visible := True;
   FActiveMemo.Visible := True;
+  ActiveControl := FActiveMemo;
   FErrorMemo := FMainMemo;
   FErrorMemo := FMainMemo;
   FStepMemo := FMainMemo;
   FStepMemo := FMainMemo;
   UpdateMarginsAndSquigglyAndCaretWidths;
   UpdateMarginsAndSquigglyAndCaretWidths;
@@ -1326,8 +1327,12 @@ begin
       if ControlToAdd <> nil then
       if ControlToAdd <> nil then
         AddControlToArray(ControlToAdd, Controls, NControls);
         AddControlToArray(ControlToAdd, Controls, NControls);
     end;
     end;
-    if UpdatePanel.Visible and FUpdatePanelMessages[UpdateLinkLabel.Tag].HasLink then
-      AddControlToArray(UpdateLinkLabel, Controls, NControls);
+    if UpdatePanel.Visible then begin
+      if FUpdatePanelMessages[UpdateLinkLabel.Tag].HasLink then
+        AddControlToArray(UpdateLinkLabel, Controls, NControls);
+      AddControlToArray(UpdatePanelDonateBitBtn, Controls, NControls);
+      AddControlToArray(UpdatePanelCloseBitBtn, Controls, NControls);
+    end;
 
 
     { Now move focus to next }
     { Now move focus to next }
     if NControls > 1 then begin
     if NControls > 1 then begin
@@ -1671,9 +1676,6 @@ begin
     to the form's height decreasing }
     to the form's height decreasing }
   if StatusPanel.Visible then
   if StatusPanel.Visible then
     UpdateStatusPanelHeight(StatusPanel.Height);
     UpdateStatusPanelHeight(StatusPanel.Height);
-  { Violently resizing the form leaves UpdatePanelDonateImage and UpdatePanelPaintBox artifacts
-    under and over UpdateLinkLabel. Invalidating it prevents this. }
-  UpdateLinkLabel.Invalidate;
 end;
 end;
 
 
 procedure TMainForm.WndProc(var Message: TMessage);
 procedure TMainForm.WndProc(var Message: TMessage);
@@ -4238,7 +4240,7 @@ begin
   var Images := ImagesModule.LightToolBarImageCollection;
   var Images := ImagesModule.LightToolBarImageCollection;
 
 
   var Image := Images.GetSourceImage(Images.GetIndexByName('heart-filled'), WH, WH);
   var Image := Images.GetSourceImage(Images.GetIndexByName('heart-filled'), WH, WH);
-  UpdatePanelDonateImage.Picture.Graphic:= Image;
+  UpdatePanelDonateBitBtn.Bitmap.Assign(Image);
 end;
 end;
 
 
 procedure TMainForm.UpdateOutputTabSetListsItemHeightAndDebugTimeWidth;
 procedure TMainForm.UpdateOutputTabSetListsItemHeightAndDebugTimeWidth;
@@ -8090,10 +8092,10 @@ begin
   end else
   end else
     Handled := False;
     Handled := False;
   if Handled then
   if Handled then
-    UpdatePanelClosePaintBoxClick(Sender);
+    UpdatePanelCloseBitBtnClick(Sender);
 end;
 end;
 
 
-procedure TMainForm.UpdatePanelClosePaintBoxClick(Sender: TObject);
+procedure TMainForm.UpdatePanelCloseBitBtnClick(Sender: TObject);
 begin
 begin
   var MessageToHideIndex := UpdateLinkLabel.Tag;
   var MessageToHideIndex := UpdateLinkLabel.Tag;
   var Ini := TConfigIniFile.Create;
   var Ini := TConfigIniFile.Create;
@@ -8106,20 +8108,19 @@ begin
   UpdateUpdatePanel;
   UpdateUpdatePanel;
 end;
 end;
 
 
-procedure TMainForm.UpdatePanelDonateImageClick(Sender: TObject);
+procedure TMainForm.UpdatePanelDonateBitBtnClick(Sender: TObject);
 begin
 begin
   HDonate.Click;
   HDonate.Click;
 end;
 end;
 
 
-procedure TMainForm.UpdatePanelClosePaintBoxPaint(Sender: TObject);
+procedure TMainForm.UpdatePanelCloseBitBtnPaint(Sender: TObject; Canvas: TCanvas; var ARect: TRect);
 const
 const
   MENU_SYSTEMCLOSE = 17;
   MENU_SYSTEMCLOSE = 17;
   MSYSC_NORMAL = 1;
   MSYSC_NORMAL = 1;
 begin
 begin
-  var Canvas := UpdatePanelClosePaintBox.Canvas;
-  var R := TRect.Create(0, 0, UpdatePanelClosePaintBox.Width, UpdatePanelClosePaintBox.Height);
+  var R := ARect;
   if FMenuThemeData <> 0 then begin
   if FMenuThemeData <> 0 then begin
-    var Offset := MulDiv(1, CurrentPPI, 96);
+    var Offset := MulDiv(2, CurrentPPI, 96);
     Inc(R.Left, Offset);
     Inc(R.Left, Offset);
     DrawThemeBackground(FMenuThemeData, Canvas.Handle, MENU_SYSTEMCLOSE, MSYSC_NORMAL, R, nil);
     DrawThemeBackground(FMenuThemeData, Canvas.Handle, MENU_SYSTEMCLOSE, MSYSC_NORMAL, R, nil);
   end else begin
   end else begin

+ 8 - 16
Projects/Src/IDE.RegistryDesignerForm.dfm

@@ -18,15 +18,14 @@ object RegistryDesignerForm: TRegistryDesignerForm
     496
     496
     347)
     347)
   TextHeight = 13
   TextHeight = 13
-  object AppRegistryMinVerDocImage: TImage
-    Left = 406
-    Top = 170
-    Width = 16
-    Height = 16
+  object AppRegistryMinVerDocBitBtn: TBitmapButton
+    Left = 404
+    Top = 168
+    Width = 20
+    Height = 20
     Anchors = [akTop, akRight]
     Anchors = [akTop, akRight]
-    AutoSize = True
-    Transparent = True
-    ExplicitLeft = 414
+    Caption = 'Help'
+    TabOrder = 9
   end
   end
   object Panel1: TPanel
   object Panel1: TPanel
     Left = 0
     Left = 0
@@ -35,9 +34,7 @@ object RegistryDesignerForm: TRegistryDesignerForm
     Height = 42
     Height = 42
     Align = alBottom
     Align = alBottom
     BevelOuter = bvNone
     BevelOuter = bvNone
-    TabOrder = 9
-    ExplicitTop = 320
-    ExplicitWidth = 500
+    TabOrder = 10
     DesignSize = (
     DesignSize = (
       496
       496
       42)
       42)
@@ -61,7 +58,6 @@ object RegistryDesignerForm: TRegistryDesignerForm
       ModalResult = 1
       ModalResult = 1
       TabOrder = 0
       TabOrder = 0
       OnClick = InsertButtonClick
       OnClick = InsertButtonClick
-      ExplicitLeft = 330
     end
     end
     object CancelButton: TButton
     object CancelButton: TButton
       Left = 406
       Left = 406
@@ -73,7 +69,6 @@ object RegistryDesignerForm: TRegistryDesignerForm
       Caption = 'Cancel'
       Caption = 'Cancel'
       ModalResult = 2
       ModalResult = 2
       TabOrder = 1
       TabOrder = 1
-      ExplicitLeft = 410
     end
     end
     object PrivilegesRequiredLabel: TNewStaticText
     object PrivilegesRequiredLabel: TNewStaticText
       Left = 8
       Left = 8
@@ -101,7 +96,6 @@ object RegistryDesignerForm: TRegistryDesignerForm
     Height = 21
     Height = 21
     Anchors = [akLeft, akTop, akRight]
     Anchors = [akLeft, akTop, akRight]
     TabOrder = 1
     TabOrder = 1
-    ExplicitWidth = 392
   end
   end
   object AppRegistryFileButton: TButton
   object AppRegistryFileButton: TButton
     Left = 406
     Left = 406
@@ -111,7 +105,6 @@ object RegistryDesignerForm: TRegistryDesignerForm
     Anchors = [akTop, akRight]
     Anchors = [akTop, akRight]
     Caption = '&Browse...'
     Caption = '&Browse...'
     TabOrder = 2
     TabOrder = 2
-    ExplicitLeft = 414
   end
   end
   object AppRegistrySettingsLabel: TNewStaticText
   object AppRegistrySettingsLabel: TNewStaticText
     Left = 8
     Left = 8
@@ -165,6 +158,5 @@ object RegistryDesignerForm: TRegistryDesignerForm
     Height = 21
     Height = 21
     Anchors = [akLeft, akTop, akRight]
     Anchors = [akLeft, akTop, akRight]
     TabOrder = 8
     TabOrder = 8
-    ExplicitWidth = 140
   end
   end
 end
 end

+ 4 - 4
Projects/Src/IDE.RegistryDesignerForm.pas

@@ -2,7 +2,7 @@ unit IDE.RegistryDesignerForm;
 
 
 {
 {
   Inno Setup
   Inno Setup
-  Copyright (C) 1997-2024 Jordan Russell
+  Copyright (C) 1997-2025 Jordan Russell
   Portions by Martijn Laan
   Portions by Martijn Laan
   For conditions of distribution and use, see LICENSE.TXT.
   For conditions of distribution and use, see LICENSE.TXT.
 
 
@@ -16,7 +16,7 @@ interface
 uses
 uses
   SysUtils, Classes,
   SysUtils, Classes,
   Forms, Controls, StdCtrls, ExtCtrls,
   Forms, Controls, StdCtrls, ExtCtrls,
-  IDE.Wizard.WizardFormRegistryHelper, NewStaticText;
+  IDE.Wizard.WizardFormRegistryHelper, NewStaticText, BitmapButton;
 
 
 type
 type
   TRegistryDesignerForm = class(TForm)
   TRegistryDesignerForm = class(TForm)
@@ -34,7 +34,7 @@ type
     AppRegistryMinVerCheck: TCheckBox;
     AppRegistryMinVerCheck: TCheckBox;
     AppRegistryMinVerEdit: TEdit;
     AppRegistryMinVerEdit: TEdit;
     PrivilegesRequiredLabel: TNewStaticText;
     PrivilegesRequiredLabel: TNewStaticText;
-    AppRegistryMinVerDocImage: TImage;
+    AppRegistryMinVerDocBitBtn: TBitmapButton;
     procedure InsertButtonClick(Sender: TObject);
     procedure InsertButtonClick(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure FormDestroy(Sender: TObject);
     procedure FormDestroy(Sender: TObject);
@@ -74,7 +74,7 @@ begin
   FRegistryHelper := TWizardFormRegistryHelper.Create(Self, AppRegistryFileEdit,
   FRegistryHelper := TWizardFormRegistryHelper.Create(Self, AppRegistryFileEdit,
     AppRegistryFileButton, AppRegistryUninsDeleteKeyCheck,
     AppRegistryFileButton, AppRegistryUninsDeleteKeyCheck,
     AppRegistryUninsDeleteKeyIfEmptyCheck, AppRegistryUninsDeleteValueCheck,
     AppRegistryUninsDeleteKeyIfEmptyCheck, AppRegistryUninsDeleteValueCheck,
-    AppRegistryMinVerCheck, AppRegistryMinVerEdit, AppRegistryMinVerDocImage);
+    AppRegistryMinVerCheck, AppRegistryMinVerEdit, AppRegistryMinVerDocBitBtn);
 end;
 end;
 
 
 procedure TRegistryDesignerForm.FormDestroy(Sender: TObject);
 procedure TRegistryDesignerForm.FormDestroy(Sender: TObject);

+ 3 - 3
Projects/Src/IDE.SignToolsForm.pas

@@ -32,7 +32,7 @@ type
     procedure SignToolsListBoxDblClick(Sender: TObject);
     procedure SignToolsListBoxDblClick(Sender: TObject);
   private
   private
     FSignTools: TStringList;
     FSignTools: TStringList;
-    procedure CommandDocImageClick(Sender: TObject);
+    procedure CommandDocBitBtnClick(Sender: TObject);
     procedure UpdateSignTools;
     procedure UpdateSignTools;
     procedure UpdateSignToolsButtons;
     procedure UpdateSignToolsButtons;
     procedure SetSignTools(SignTools: TStringList);
     procedure SetSignTools(SignTools: TStringList);
@@ -91,7 +91,7 @@ begin
   SendMessage(Handle, WM_SETICON, ICON_BIG, 0);
   SendMessage(Handle, WM_SETICON, ICON_BIG, 0);
 end;
 end;
 
 
-procedure TSignToolsForm.CommandDocImageClick(Sender: TObject);
+procedure TSignToolsForm.CommandDocBitBtnClick(Sender: TObject);
 begin
 begin
   if Assigned(HtmlHelp) then
   if Assigned(HtmlHelp) then
     HtmlHelp(GetDesktopWindow, PChar(GetHelpFile), HH_DISPLAY_TOPIC, Cardinal(PChar('topic_setup_signtool.htm')));
     HtmlHelp(GetDesktopWindow, PChar(GetHelpFile), HH_DISPLAY_TOPIC, Cardinal(PChar('topic_setup_signtool.htm')));
@@ -128,7 +128,7 @@ begin
       end;
       end;
     end;
     end;
 
 
-    if InputQueryMemo(Caption, 'Command of the Sign Tool:', SignToolCommand, True, CommandDocImageClick) then begin
+    if InputQueryMemo(Caption, 'Command of the Sign Tool:', SignToolCommand, True, CommandDocBitBtnClick) then begin
       if SignToolCommand = '' then begin
       if SignToolCommand = '' then begin
         AppMessageBox(PChar('Invalid command.'), PChar(Caption), MB_OK or MB_ICONSTOP);
         AppMessageBox(PChar('Invalid command.'), PChar(Caption), MB_OK or MB_ICONSTOP);
         Exit;
         Exit;

+ 170 - 172
Projects/Src/IDE.StartupForm.dfm

@@ -18,30 +18,28 @@ object StartupForm: TStartupForm
     579
     579
     419)
     419)
   TextHeight = 13
   TextHeight = 13
-  object DonateImage: TImage
-    Left = 8
-    Top = 383
-    Width = 62
-    Height = 31
+  object DonateBitBtn: TBitmapButton
+    Left = 6
+    Top = 381
+    Width = 66
+    Height = 35
     Cursor = crHandPoint
     Cursor = crHandPoint
-    Hint = 'Support Inno Setup - Thank you!'
     Anchors = [akLeft, akBottom]
     Anchors = [akLeft, akBottom]
-    AutoSize = True
+    Caption = 'Donate'
     ParentShowHint = False
     ParentShowHint = False
-    Picture.Data = {
-      07544269746D6170F60B0000424DF60B00000000000036040000280000003E00
-      00001F0000000100080000000000C0070000C40E0000C40E0000000100000001
-      000000000000663300006F3F0F004D36220070401000794C1D0073482400794D
-      200082582C0081573200835930008C643B00996633009F6F3E008C664000926E
-      4E009F70400095704900967350009E7D5800A5784A00A6794D00AC815500AC83
-      5900A0806000A8896700A2836800B28A6100B38C6600B8936C00A98D7000B195
-      7500B2997F00BE9D7800BAA18300BFA08000B8A08800BCA58F00BDA79400BBBB
-      BB00C4A68300C6A98D00CAAE8E00C4AD9200C5B29F00CCB29900D1B79A00CAB7
-      A400CDBAA100CFBFAF00D2BCA500D7C0A500D6C6AF00D3C4B400D9C5B200DDCA
-      B100D9CCBF00E0D2BE00E3D3BC00DAD5D100E2D9CF00E5D9CC00E9DCC800E9DE
-      CD00E5DCD200E9E1D700ECE5DF00F0E5D300F3EBDB00F6EEDF00E9E9E900F2EC
-      E500F4F1EE00F5F2EF00FCF7EA00F9F5F200FFFFFF0000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
+    Bitmap.Data = {
+      F60B0000424DF60B00000000000036040000280000003E0000001F0000000100
+      080000000000C0070000C40E0000C40E00000001000000010000000000006633
+      00006F3F0F004D36220070401000794C1D0073482400794D200082582C008157
+      3200835930008C643B00996633009F6F3E008C664000926E4E009F7040009570
+      4900967350009E7D5800A5784A00A6794D00AC815500AC835900A0806000A889
+      6700A2836800B28A6100B38C6600B8936C00A98D7000B1957500B2997F00BE9D
+      7800BAA18300BFA08000B8A08800BCA58F00BDA79400BBBBBB00C4A68300C6A9
+      8D00CAAE8E00C4AD9200C5B29F00CCB29900D1B79A00CAB7A400CDBAA100CFBF
+      AF00D2BCA500D7C0A500D6C6AF00D3C4B400D9C5B200DDCAB100D9CCBF00E0D2
+      BE00E3D3BC00DAD5D100E2D9CF00E5D9CC00E9DCC800E9DECD00E5DCD200E9E1
+      D700ECE5DF00F0E5D300F3EBDB00F6EEDF00E9E9E900F2ECE500F4F1EE00F5F2
+      EF00FCF7EA00F9F5F200FFFFFF00000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
@@ -63,99 +61,99 @@ object StartupForm: TStartupForm
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
-      0000060603030303030303030303030303030303030303030303030303030303
+      0000000000000000000000000000000000000000000000000000060603030303
       0303030303030303030303030303030303030303030303030303030303030303
       0303030303030303030303030303030303030303030303030303030303030303
-      0000094135272727272727272727272727272727272727272727272727272727
-      2727272727272727272727272727272727272727272727272727272727272603
-      00000F4C48464646464646464646464646464646464646464646464646464646
-      4646464646464646464646464646464646464646464646464646464646413506
-      00001A4C4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A
-      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4C4C06
-      00001A4C4C4C4C4C4C4C4C4C4C4C4C000000004C4C4C0000004C4C004C4C4C00
-      4C4C004C4C4C004C4C4C004C4C4C000000004C4C4C4C4C4C4C4C4C4C4C483B06
-      00001A4C4A4A4A4A4A4A4A4A4A4A4A004A4A4A004A004A4A4A004A004A4A0000
-      4A4A004A4A4A004A4A4A004A4A4A004A4A4A4A4A4A4A4A4A4A4A4A4A4A483B06
-      00001A4C4C4C4C4C4C4C4C4C4C4C4C004C4C4C004C004C4C4C004C004C004C00
-      4C4C00000000004C4C4C004C4C4C0000004C4C4C4C4C4C4C4C4C4C4C4C483B06
-      00001A4C4A4A4A4A4A4A4A4A4A4A4A004A4A4A004A004A4A4A004A00004A4A00
-      4A4A004A4A4A004A4A4A004A4A4A004A4A4A4A4A4A4A4A4A4A4A4A4A4A483B06
-      00001A4C4C4C4C4C4C4C4C4C4C4C4C000000004C4C4C0000004C4C004C4C4C00
-      4C4C4C0000004C4C00000000004C000000004C4C4C4C4C4C4C4C4C4C4C483B06
-      00001A4C4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A
-      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A483B06
-      00001A4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C
-      4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C483B06
-      00001A4C4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A
-      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A483B06
-      00001A4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C312025494C4C
-      4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C483B06
-      00001A4C4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A1F0101114A4A
-      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A483B06
-      00001A4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C070101384C
-      4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C483B06
-      00001A4C4A4A4A4A4A4A4A4A4A4A4A4A4A4A3F34394A4A4A4A4A4A300101054A
-      4A4A4A4A4A4A4A4A4A4A4A4A4A3E3A454A4A4A4A4A4A4A4A4A4A4A4A4A483B06
-      00001A4C4C4C4C4C01010E4C4C4C4C4C4C2C0101010E01010A4C4C3801010120
-      4C4C360C0C2D4C4C4C4C4C4C230C0C0C1C0C0C293D0C0C324C4C4C4C4C483B06
-      00001A4C4A4A4A4A020101444A4A4A4A4A02010108080101013F4A1F01010102
-      3F4A3A0C0C164A4A4A4A4A3E0C0C0C1B140C0C16430C0C1D4A4A4A4A4A483B06
-      00001A4C4C4C4C4C0E0101314C4C4C4C4C070101494C1E0101314C1801010101
-      124C4C0C0C0C4B4C4C4C4C470C0C174C4C170C0C4B100C104C4C4C4C4C483B06
-      00001A4C4A4A4A4A1F0101050B111F394A2201010519130101194A0B01010501
-      01344A1B0C0C161B282E434A1B0C0C162A1B0C0C371D0C0C434A4A4A4A483B06
-      00001A4C4C4C4C4C38010101010101010E49310E01010101010A4C0401043801
-      01074C2D0C0C0C0C0C0C0C294B2D150C0C0C0C0C292D0C0C364C4C4C4C483B06
-      00001A4C4A4A4A4A4A01010119190201010844394A3F340501014401010B4A11
-      01011F3A0C0C0D2A210C0C0C2843434A3A370C0C1B3A0C0C214A4A4A4A483B06
-      00001A4C4C4C4C4C4C0E0101384C490401012001040E070101013801011E4C42
-      040104400C0C0C4C4C3D0C0C0C2D0C171C100C0C1C4C0C0C174C4C4C4C483B06
-      00001A4C4A4A4A4A4A1901011F4A4A0801012B05010101010222340101224A4A
-      1F010111160C0C3E4A450C0C0C3E0C0C0C0C0C143A4A160C0C454A4A4A483B06
-      00001A4C4C4C4C4C4C310101040E0A010101384C4C3C38424C4C4C38384C4C4C
-      4C3C3838290C0C151C150C0C0C4C4C4B3D3D474C4C4C290C0C3D4C4C4C483B06
-      00001A4C4A4A4A4A4A4401010101010101134A4A4A4A4A4A4A4A4A4A4A4A4A4A
-      4A4A4A4A370C0C0C0C0C0C0C334A4A4A4A4A4A4A4A4A370C0C2A3A4A4A483B06
-      00001A4C4C4C4C4C4C4C3120202020253C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C
-      4C4C4C4C4B2D2D2D2D2D36474C4C4C4C4C4C4C4C4C4C4C322D323D4C4C483B06
-      00001A4C4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A
-      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4C4606
-      0000244C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C
-      4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C06
-      0000244A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A
-      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A09
-      0000262F26262626262626262626262626262626262626262626262626262626
-      2626262626262626262626262626262626262626262626262626262626241A0F
-      0000}
+      0303030303030303030303030303030303030303030303030000094135272727
+      2727272727272727272727272727272727272727272727272727272727272727
+      27272727272727272727272727272727272727272727260300000F4C48464646
+      4646464646464646464646464646464646464646464646464646464646464646
+      46464646464646464646464646464646464646464641350600001A4C4A4A4A4A
+      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A
+      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4C4C0600001A4C4C4C4C4C
+      4C4C4C4C4C4C4C000000004C4C4C0000004C4C004C4C4C004C4C004C4C4C004C
+      4C4C004C4C4C000000004C4C4C4C4C4C4C4C4C4C4C483B0600001A4C4A4A4A4A
+      4A4A4A4A4A4A4A004A4A4A004A004A4A4A004A004A4A00004A4A004A4A4A004A
+      4A4A004A4A4A004A4A4A4A4A4A4A4A4A4A4A4A4A4A483B0600001A4C4C4C4C4C
+      4C4C4C4C4C4C4C004C4C4C004C004C4C4C004C004C004C004C4C00000000004C
+      4C4C004C4C4C0000004C4C4C4C4C4C4C4C4C4C4C4C483B0600001A4C4A4A4A4A
+      4A4A4A4A4A4A4A004A4A4A004A004A4A4A004A00004A4A004A4A004A4A4A004A
+      4A4A004A4A4A004A4A4A4A4A4A4A4A4A4A4A4A4A4A483B0600001A4C4C4C4C4C
+      4C4C4C4C4C4C4C000000004C4C4C0000004C4C004C4C4C004C4C4C0000004C4C
+      00000000004C000000004C4C4C4C4C4C4C4C4C4C4C483B0600001A4C4A4A4A4A
+      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A
+      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A483B0600001A4C4C4C4C4C
+      4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C
+      4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C483B0600001A4C4A4A4A4A
+      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A
+      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A483B0600001A4C4C4C4C4C
+      4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C312025494C4C4C4C4C4C4C4C4C4C
+      4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C483B0600001A4C4A4A4A4A
+      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A1F0101114A4A4A4A4A4A4A4A4A4A
+      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A483B0600001A4C4C4C4C4C
+      4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C070101384C4C4C4C4C4C4C4C4C
+      4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C483B0600001A4C4A4A4A4A
+      4A4A4A4A4A4A4A4A4A4A3F34394A4A4A4A4A4A300101054A4A4A4A4A4A4A4A4A
+      4A4A4A4A4A3E3A454A4A4A4A4A4A4A4A4A4A4A4A4A483B0600001A4C4C4C4C4C
+      01010E4C4C4C4C4C4C2C0101010E01010A4C4C38010101204C4C360C0C2D4C4C
+      4C4C4C4C230C0C0C1C0C0C293D0C0C324C4C4C4C4C483B0600001A4C4A4A4A4A
+      020101444A4A4A4A4A02010108080101013F4A1F010101023F4A3A0C0C164A4A
+      4A4A4A3E0C0C0C1B140C0C16430C0C1D4A4A4A4A4A483B0600001A4C4C4C4C4C
+      0E0101314C4C4C4C4C070101494C1E0101314C1801010101124C4C0C0C0C4B4C
+      4C4C4C470C0C174C4C170C0C4B100C104C4C4C4C4C483B0600001A4C4A4A4A4A
+      1F0101050B111F394A2201010519130101194A0B0101050101344A1B0C0C161B
+      282E434A1B0C0C162A1B0C0C371D0C0C434A4A4A4A483B0600001A4C4C4C4C4C
+      38010101010101010E49310E01010101010A4C040104380101074C2D0C0C0C0C
+      0C0C0C294B2D150C0C0C0C0C292D0C0C364C4C4C4C483B0600001A4C4A4A4A4A
+      4A01010119190201010844394A3F340501014401010B4A1101011F3A0C0C0D2A
+      210C0C0C2843434A3A370C0C1B3A0C0C214A4A4A4A483B0600001A4C4C4C4C4C
+      4C0E0101384C490401012001040E070101013801011E4C42040104400C0C0C4C
+      4C3D0C0C0C2D0C171C100C0C1C4C0C0C174C4C4C4C483B0600001A4C4A4A4A4A
+      4A1901011F4A4A0801012B05010101010222340101224A4A1F010111160C0C3E
+      4A450C0C0C3E0C0C0C0C0C143A4A160C0C454A4A4A483B0600001A4C4C4C4C4C
+      4C310101040E0A010101384C4C3C38424C4C4C38384C4C4C4C3C3838290C0C15
+      1C150C0C0C4C4C4B3D3D474C4C4C290C0C3D4C4C4C483B0600001A4C4A4A4A4A
+      4A4401010101010101134A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A370C0C0C
+      0C0C0C0C334A4A4A4A4A4A4A4A4A370C0C2A3A4A4A483B0600001A4C4C4C4C4C
+      4C4C3120202020253C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4B2D2D2D
+      2D2D36474C4C4C4C4C4C4C4C4C4C4C322D323D4C4C483B0600001A4C4A4A4A4A
+      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A
+      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4C46060000244C4C4C4C4C
+      4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C
+      4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C060000244A4A4A4A4A
+      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A
+      4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A090000262F26262626
+      2626262626262626262626262626262626262626262626262626262626262626
+      262626262626262626262626262626262626262626241A0F0000}
     ShowHint = True
     ShowHint = True
-    OnClick = DonateImageClick
+    TabOrder = 4
+    OnClick = DonateBitBtnClick
   end
   end
-  object MailingListImage: TImage
-    Left = 78
-    Top = 383
-    Width = 62
-    Height = 31
+  object MailingListBitBtn: TBitmapButton
+    Left = 76
+    Top = 381
+    Width = 66
+    Height = 35
     Cursor = crHandPoint
     Cursor = crHandPoint
     Hint = 'Be notified by e-mail of new Inno Setup releases'
     Hint = 'Be notified by e-mail of new Inno Setup releases'
     Anchors = [akLeft, akBottom]
     Anchors = [akLeft, akBottom]
-    AutoSize = True
+    Caption = 'Subscribe'
     ParentShowHint = False
     ParentShowHint = False
-    Picture.Data = {
-      07544269746D6170F60B0000424DF60B00000000000036040000280000003E00
-      00001F0000000100080000000000C0070000C40E0000C40E0000000100000001
-      0000000000005D2E03005F2F0200512C0A00532C0900542D0800602F0100612F
-      0100622F0000632F000063330200643000006432010066320000673300006936
-      03006A3603006E3A0700663B0F006B3A09006D3A08006F3B08006E3C0A006F3D
-      0C00703C0800713D0B00713F0D00723E0C00733F0C004D36220074400D007541
-      0F007A461300734824007F5B37008E5B2A008F5B29008F5D2B008E5E2E008F5E
-      2D00905E2C00915E2C0081573200875D3200805B3600815B3600845C34008C5E
-      300093602E008D633A0091643700926436009364360095653500966534009765
-      34009865330090643800926E4E00B3815000B4815000B7855300B4855400B588
-      5B00BA8B5B00A2836800D19F6E00DBAD7E00DDAD7C00B8A08800BDA79400BBBB
-      BB00E1B58A00E3B68900CAB7A400D3BBA200D4BBA100D7C1AA00DBC3AA00D3C4
-      B400DFCFBB00DAD5D100E0D4C300E6DFCF00E9E0CF00E8E1D100E9E1D100E9E1
-      D700E9E9E900F2F0E300F1F0E400FCF7E500FCF8E200FCF8E400F4F1EE00F5F5
-      ED00F6F6EF00FCF7E900F8F8F200F9F9F200FCFCF600FDFDF600FEFEF900FFFF
-      FA00FFFFFE000000000000000000000000000000000000000000000000000000
+    Bitmap.Data = {
+      F60B0000424DF60B00000000000036040000280000003E0000001F0000000100
+      080000000000C0070000C40E0000C40E00000001000000010000000000005D2E
+      03005F2F0200512C0A00532C0900542D0800602F0100612F0100622F0000632F
+      00006333020064300000643201006632000067330000693603006A3603006E3A
+      0700663B0F006B3A09006D3A08006F3B08006E3C0A006F3D0C00703C0800713D
+      0B00713F0D00723E0C00733F0C004D36220074400D0075410F007A4613007348
+      24007F5B37008E5B2A008F5B29008F5D2B008E5E2E008F5E2D00905E2C00915E
+      2C0081573200875D3200805B3600815B3600845C34008C5E300093602E008D63
+      3A00916437009264360093643600956535009665340097653400986533009064
+      3800926E4E00B3815000B4815000B7855300B4855400B5885B00BA8B5B00A283
+      6800D19F6E00DBAD7E00DDAD7C00B8A08800BDA79400BBBBBB00E1B58A00E3B6
+      8900CAB7A400D3BBA200D4BBA100D7C1AA00DBC3AA00D3C4B400DFCFBB00DAD5
+      D100E0D4C300E6DFCF00E9E0CF00E8E1D100E9E1D100E9E1D700E9E9E900F2F0
+      E300F1F0E400FCF7E500FCF8E200FCF8E400F4F1EE00F5F5ED00F6F6EF00FCF7
+      E900F8F8F200F9F9F200FCFCF600FDFDF600FEFEF900FFFFFA00FFFFFE000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
@@ -174,71 +172,72 @@ object StartupForm: TStartupForm
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
-      000021211D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D
+      000000000000000000000000000000000000000000000000000021211D1D1D1D
       1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D
       1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D
-      00002A574F474747474747474747474747474747474747474747474747474747
-      474747474747474747474747474747474747474747474747474747474747461D
-      00003A685E585858585858585858585858585858585858585858585858585858
-      5858585858585858585858585858585858585858585858585858585858574F21
-      0000416861616161616161616161616161616161616161616161616161616161
-      6161616161616161616161616161616161616161616161616161616161686821
-      0000416868680000000068686800000068680000000068680000000068686800
-      00006868006868680068000000000068000000006868000000000068685E5121
-      0000416861616161616100610061616100610061616100616161616100610061
-      61610061006161610061616100616161006161610061006161616161615E5121
-      0000416868686800000068680068686800680000000068686800000068680068
-      68686868000000006868686800686868000000006868000000006868685E5121
-      0000416861610061616161610061616100610061616100610061616161610061
-      61610061006161610061616100616161006161610061006161616161615E5121
-      0000416868686800000000680068686800680000000068686800000000686800
-      00006868000000006868000000000068000000006868000000000068685E5121
-      0000416861616161616161616161616161616161616161616161616161616161
-      61616161616161616161616161616161616161616161616161616161615E5121
-      0000416868686868686868686868686868686868686868686868686868686868
-      68686868686868686868686868686868686868686868686868686868685E5121
-      0000416861616161616161616161616161616161616161616161616161616161
-      61616161616161616161616161616161616161616161616161616161615E5121
-      0000416868686868686868686868686868686868686868686867676767676767
-      67676767676767676768686868686868686868686868686868686868685E5121
-      00004168616161616161616161616161616161616161615D1A09090909080809
-      09090909090909091C5C616161616161616161616161616161616161615E5121
-      0000416868686868686868686868686868686868686868121437363331313235
-      3838383838383838181C676868686868686868686868686868686868685E5121
-      0000416861616161616161616161616161616161616161052B67686868686867
-      676767676767676729095C6161616161616161616161616161616161615E5121
-      0000416868686868686868686868686868686868686868042D68686868685F4D
-      424D6068686868672909676868686868686868686868686868686868685E5121
-      000041686161616161616161616161616161616161616105226868686752240B
-      0B0925526768686729095D6161616161616161616161616161616161615E5121
-      0000416868686868686868686868686868686868686868052C68686448130F3D
-      4E3E1014496468672909676868686868686868686868686868686868685E5121
-      0000416861616161616161616161616161616161616161032E68633F0A174B66
-      68664C190E40626727075D6161616161616161616161616161616161615E5121
-      00004168686868686868686868686868686868686868680326532F0723556868
-      68686856240930542907676868686868686868686868686868686868685E5121
-      0000416861616161616161616161616161616161616161011F200C3B5A686868
-      68686868593C0D201F095D6161616161616161616161616161616161615E5121
-      0000416868686868686868686868686868686868686868080B15436568686868
-      68686868686544150909676868686868686868686868686868686868685E5121
-      000041686161616161616161616161616161616161615B081E50666868686868
-      68686868686866501B095D6161616161616161616161616161616161615E5121
-      0000416868686868686868686868686868686868686868072867686868686868
-      68686868686867672909676868686868686868686868686868686868685E5121
-      000041686161616161616161616161616161616161615B161135393932323334
-      3333333436373838111B5D6161616161616161616161616161616161615E5121
-      0000416868686868686868686868686868686868686868671C08060602060606
-      070707070909090B1E67686868686868686868686868686868686868685E5121
-      0000416861616161616161616161616161616161616161615B5B5B5D5D5B5B5B
-      5B5B5B5B5B5B5D5D5D6161616161616161616161616161616161616161685821
-      0000456868686868686868686868686868686868686868686868686868686868
-      6868686868686868686868686868686868686868686868686868686868686821
-      0000456161616161616161616161616161616161616161616161616161616161
-      616161616161616161616161616161616161616161616161616161616161612A
-      0000464A46464646464646464646464646464646464646464646464646464646
-      464646464646464646464646464646464646464646464646464646464645413A
-      0000}
+      1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D00002A574F474747
+      4747474747474747474747474747474747474747474747474747474747474747
+      47474747474747474747474747474747474747474747461D00003A685E585858
+      5858585858585858585858585858585858585858585858585858585858585858
+      585858585858585858585858585858585858585858574F210000416861616161
+      6161616161616161616161616161616161616161616161616161616161616161
+      6161616161616161616161616161616161616161616868210000416868680000
+      0000686868000000686800000000686800000000686868000000686800686868
+      0068000000000068000000006868000000000068685E51210000416861616161
+      6161006100616161006100616161006161616161006100616161006100616161
+      0061616100616161006161610061006161616161615E51210000416868686800
+      0000686800686868006800000000686868000000686800686868686800000000
+      6868686800686868000000006868000000006868685E51210000416861610061
+      6161616100616161006100616161006100616161616100616161006100616161
+      0061616100616161006161610061006161616161615E51210000416868686800
+      0000006800686868006800000000686868000000006868000000686800000000
+      6868000000000068000000006868000000000068685E51210000416861616161
+      6161616161616161616161616161616161616161616161616161616161616161
+      6161616161616161616161616161616161616161615E51210000416868686868
+      6868686868686868686868686868686868686868686868686868686868686868
+      6868686868686868686868686868686868686868685E51210000416861616161
+      6161616161616161616161616161616161616161616161616161616161616161
+      6161616161616161616161616161616161616161615E51210000416868686868
+      6868686868686868686868686868686868676767676767676767676767676767
+      6768686868686868686868686868686868686868685E51210000416861616161
+      6161616161616161616161616161615D1A090909090808090909090909090909
+      1C5C616161616161616161616161616161616161615E51210000416868686868
+      6868686868686868686868686868681214373633313132353838383838383838
+      181C676868686868686868686868686868686868685E51210000416861616161
+      616161616161616161616161616161052B676868686868676767676767676767
+      29095C6161616161616161616161616161616161615E51210000416868686868
+      686868686868686868686868686868042D68686868685F4D424D606868686867
+      2909676868686868686868686868686868686868685E51210000416861616161
+      61616161616161616161616161616105226868686752240B0B09255267686867
+      29095D6161616161616161616161616161616161615E51210000416868686868
+      686868686868686868686868686868052C68686448130F3D4E3E101449646867
+      2909676868686868686868686868686868686868685E51210000416861616161
+      616161616161616161616161616161032E68633F0A174B6668664C190E406267
+      27075D6161616161616161616161616161616161615E51210000416868686868
+      6868686868686868686868686868680326532F07235568686868685624093054
+      2907676868686868686868686868686868686868685E51210000416861616161
+      616161616161616161616161616161011F200C3B5A68686868686868593C0D20
+      1F095D6161616161616161616161616161616161615E51210000416868686868
+      686868686868686868686868686868080B154365686868686868686868654415
+      0909676868686868686868686868686868686868685E51210000416861616161
+      61616161616161616161616161615B081E506668686868686868686868686650
+      1B095D6161616161616161616161616161616161615E51210000416868686868
+      6868686868686868686868686868680728676868686868686868686868686767
+      2909676868686868686868686868686868686868685E51210000416861616161
+      61616161616161616161616161615B1611353939323233343333333436373838
+      111B5D6161616161616161616161616161616161615E51210000416868686868
+      686868686868686868686868686868671C08060602060606070707070909090B
+      1E67686868686868686868686868686868686868685E51210000416861616161
+      616161616161616161616161616161615B5B5B5D5D5B5B5B5B5B5B5B5B5B5D5D
+      5D61616161616161616161616161616161616161616858210000456868686868
+      6868686868686868686868686868686868686868686868686868686868686868
+      6868686868686868686868686868686868686868686868210000456161616161
+      6161616161616161616161616161616161616161616161616161616161616161
+      61616161616161616161616161616161616161616161612A0000464A46464646
+      4646464646464646464646464646464646464646464646464646464646464646
+      46464646464646464646464646464646464646464645413A0000}
     ShowHint = True
     ShowHint = True
-    OnClick = MailingListImageClick
+    TabOrder = 5
+    OnClick = MailingListBitBtnClick
   end
   end
   object OKButton: TButton
   object OKButton: TButton
     Left = 418
     Left = 418
@@ -352,9 +351,8 @@ object StartupForm: TStartupForm
     Top = 390
     Top = 390
     Width = 260
     Width = 260
     Height = 17
     Height = 17
-    TabStop = False
     Anchors = [akLeft, akRight, akBottom]
     Anchors = [akLeft, akRight, akBottom]
     Caption = '&Don'#39't show this dialog again'
     Caption = '&Don'#39't show this dialog again'
-    TabOrder = 4
+    TabOrder = 6
   end
   end
 end
 end

+ 9 - 9
Projects/Src/IDE.StartupForm.pas

@@ -2,7 +2,7 @@ unit IDE.StartupForm;
 
 
 {
 {
   Inno Setup
   Inno Setup
-  Copyright (C) 1997-2024 Jordan Russell
+  Copyright (C) 1997-2025 Jordan Russell
   Portions by Martijn Laan
   Portions by Martijn Laan
   For conditions of distribution and use, see LICENSE.TXT.
   For conditions of distribution and use, see LICENSE.TXT.
 
 
@@ -13,7 +13,7 @@ interface
 
 
 uses
 uses
   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
-  UIStateForm, StdCtrls, ExtCtrls;
+  UIStateForm, StdCtrls, ExtCtrls, BitmapButton;
 
 
 type
 type
   TStartupFormResult = (srNone, srEmpty, srWizard, srOpenFile, srOpenDialog,
   TStartupFormResult = (srNone, srEmpty, srWizard, srOpenFile, srOpenDialog,
@@ -31,8 +31,8 @@ type
     StartupCheck: TCheckBox;
     StartupCheck: TCheckBox;
     NewImage: TImage;
     NewImage: TImage;
     OpenImage: TImage;
     OpenImage: TImage;
-    DonateImage: TImage;
-    MailingListImage: TImage;
+    DonateBitBtn: TBitmapButton;
+    MailingListBitBtn: TBitmapButton;
     procedure RadioButtonClick(Sender: TObject);
     procedure RadioButtonClick(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure DblClick_(Sender: TObject);
     procedure DblClick_(Sender: TObject);
@@ -40,8 +40,8 @@ type
     procedure OKButtonClick(Sender: TObject);
     procedure OKButtonClick(Sender: TObject);
     procedure FormAfterMonitorDpiChanged(Sender: TObject; OldDPI,
     procedure FormAfterMonitorDpiChanged(Sender: TObject; OldDPI,
       NewDPI: Integer);
       NewDPI: Integer);
-    procedure DonateImageClick(Sender: TObject);
-    procedure MailingListImageClick(Sender: TObject);
+    procedure DonateBitBtnClick(Sender: TObject);
+    procedure MailingListBitBtnClick(Sender: TObject);
   private
   private
     FResult: TStartupFormResult;
     FResult: TStartupFormResult;
     FResultMainFileName: TFileName;
     FResultMainFileName: TFileName;
@@ -101,7 +101,7 @@ begin
   InitFormFont(Self);
   InitFormFont(Self);
   InitFormTheme(Self);
   InitFormTheme(Self);
 
 
-  DonateImage.Hint := MainForm.UpdatePanelDonateImage.Hint;
+  DonateBitBtn.Hint := MainForm.UpdatePanelDonateBitBtn.Hint;
 
 
   UpdateImages;
   UpdateImages;
 
 
@@ -152,12 +152,12 @@ begin
   OpenRadioButton.Checked := True;
   OpenRadioButton.Checked := True;
 end;
 end;
 
 
-procedure TStartupForm.DonateImageClick(Sender: TObject);
+procedure TStartupForm.DonateBitBtnClick(Sender: TObject);
 begin
 begin
   OpenDonateSite;
   OpenDonateSite;
 end;
 end;
 
 
-procedure TStartupForm.MailingListImageClick(Sender: TObject);
+procedure TStartupForm.MailingListBitBtnClick(Sender: TObject);
 begin
 begin
   OpenMailingListSite;
   OpenMailingListSite;
 end;
 end;

+ 7 - 7
Projects/Src/IDE.Wizard.WizardForm.dfm

@@ -1054,14 +1054,14 @@ object WizardForm: TWizardForm
           DesignSize = (
           DesignSize = (
             485
             485
             245)
             245)
-          object AppRegistryMinVerDocImage: TImage
-            Left = 360
-            Top = 161
-            Width = 16
-            Height = 16
+          object AppRegistryMinVerDocBitBtn: TBitmapButton
+            Left = 358
+            Top = 159
+            Width = 20
+            Height = 20
             Anchors = [akTop, akRight]
             Anchors = [akTop, akRight]
-            AutoSize = True
-            Transparent = True
+            Caption = 'Help'
+            TabOrder = 9
           end
           end
           object AppRegistryFileLabel: TNewStaticText
           object AppRegistryFileLabel: TNewStaticText
             Left = 36
             Left = 36

+ 3 - 3
Projects/Src/IDE.Wizard.WizardForm.pas

@@ -14,7 +14,7 @@ interface
 uses
 uses
   Windows, Forms, Classes, Graphics, StdCtrls, ExtCtrls, Controls, Dialogs, pngimage,
   Windows, Forms, Classes, Graphics, StdCtrls, ExtCtrls, Controls, Dialogs, pngimage,
   UIStateForm, NewStaticText, DropListBox, NewCheckListBox, NewNotebook,
   UIStateForm, NewStaticText, DropListBox, NewCheckListBox, NewNotebook,
-  IDE.Wizard.WizardFormFilesHelper, IDE.Wizard.WizardFormRegistryHelper;
+  IDE.Wizard.WizardFormFilesHelper, IDE.Wizard.WizardFormRegistryHelper, BitmapButton;
 
 
 type
 type
   TWizardPage = (wpWelcome, wpAppInfo, wpAppDir, wpAppFiles, wpAppAssoc, wpAppIcons,
   TWizardPage = (wpWelcome, wpAppInfo, wpAppDir, wpAppFiles, wpAppAssoc, wpAppIcons,
@@ -139,7 +139,7 @@ type
     AppRegistryUninsDeleteValueCheck: TCheckBox;
     AppRegistryUninsDeleteValueCheck: TCheckBox;
     AppRegistryMinVerCheck: TCheckBox;
     AppRegistryMinVerCheck: TCheckBox;
     AppRegistryMinVerEdit: TEdit;
     AppRegistryMinVerEdit: TEdit;
-    AppRegistryMinVerDocImage: TImage;
+    AppRegistryMinVerDocBitBtn: TBitmapButton;
     WelcomeImageDark: TImage;
     WelcomeImageDark: TImage;
     InnerImageDark: TImage;
     InnerImageDark: TImage;
     procedure FormCreate(Sender: TObject);
     procedure FormCreate(Sender: TObject);
@@ -289,7 +289,7 @@ begin
   FRegistryHelper := TWizardFormRegistryHelper.Create(Self, AppRegistryFileEdit,
   FRegistryHelper := TWizardFormRegistryHelper.Create(Self, AppRegistryFileEdit,
     AppRegistryFileButton, AppRegistryUninsDeleteKeyCheck,
     AppRegistryFileButton, AppRegistryUninsDeleteKeyCheck,
     AppRegistryUninsDeleteKeyIfEmptyCheck, AppRegistryUninsDeleteValueCheck,
     AppRegistryUninsDeleteKeyIfEmptyCheck, AppRegistryUninsDeleteValueCheck,
-    AppRegistryMinVerCheck, AppRegistryMinVerEdit, AppRegistryMinVerDocImage);
+    AppRegistryMinVerCheck, AppRegistryMinVerEdit, AppRegistryMinVerDocBitBtn);
 
 
   FLanguages := TStringList.Create;
   FLanguages := TStringList.Create;
   FLanguages.Sorted := True;
   FLanguages.Sorted := True;

+ 12 - 12
Projects/Src/IDE.Wizard.WizardFormRegistryHelper.pas

@@ -2,7 +2,7 @@ unit IDE.Wizard.WizardFormRegistryHelper;
 
 
 {
 {
   Inno Setup
   Inno Setup
-  Copyright (C) 1997-2024 Jordan Russell
+  Copyright (C) 1997-2025 Jordan Russell
   Portions by Martijn Laan
   Portions by Martijn Laan
   For conditions of distribution and use, see LICENSE.TXT.
   For conditions of distribution and use, see LICENSE.TXT.
 
 
@@ -12,7 +12,7 @@ unit IDE.Wizard.WizardFormRegistryHelper;
 interface
 interface
 
 
 uses
 uses
-  Forms, StdCtrls, ExtCtrls;
+  Forms, StdCtrls, ExtCtrls, BitmapButton;
 
 
 type
 type
   TPrivilegesRequired = (prAdmin, prLowest, prDynamic);
   TPrivilegesRequired = (prAdmin, prLowest, prDynamic);
@@ -24,7 +24,7 @@ type
       FUninsDeleteKeyCheck, FUninsDeleteKeyIfEmptyCheck,
       FUninsDeleteKeyCheck, FUninsDeleteKeyIfEmptyCheck,
       FUninsDeleteValueCheck, FMinVerCheck: TCheckBox;
       FUninsDeleteValueCheck, FMinVerCheck: TCheckBox;
       FMinVerEdit: TEdit;
       FMinVerEdit: TEdit;
-      FMinVerDocImage: TImage;
+      FMinVerDocBitBtn: TBitmapButton;
       FPrivilegesRequired: TPrivilegesRequired;
       FPrivilegesRequired: TPrivilegesRequired;
       procedure SetPrivilegesRequired(const Value: TPrivilegesRequired);
       procedure SetPrivilegesRequired(const Value: TPrivilegesRequired);
       procedure UpdateImages;
       procedure UpdateImages;
@@ -32,12 +32,12 @@ type
       procedure FileButtonClick(Sender: TObject);
       procedure FileButtonClick(Sender: TObject);
       procedure UninsDeleteKeyIfEmptyCheckClick(Sender: TObject);
       procedure UninsDeleteKeyIfEmptyCheckClick(Sender: TObject);
       procedure MinVerCheckClick(Sender: TObject);
       procedure MinVerCheckClick(Sender: TObject);
-      procedure MinVerDocImageClick(Sender: TObject);
+      procedure MinVerDocBitBtnClick(Sender: TObject);
     public
     public
       constructor Create(const Form: TForm; const FileEdit: TEdit;
       constructor Create(const Form: TForm; const FileEdit: TEdit;
         const FileButton: TButton; const UninsDeleteKeyCheck,
         const FileButton: TButton; const UninsDeleteKeyCheck,
         UninsDeleteKeyIfEmptyCheck, UninsDeleteValueCheck, MinVerCheck: TCheckBox;
         UninsDeleteKeyIfEmptyCheck, UninsDeleteValueCheck, MinVerCheck: TCheckBox;
-        const MinVerEdit: TEdit; const MinVerDocImage: TImage);
+        const MinVerEdit: TEdit; const MinVerDocBitBtn: TBitmapButton);
       procedure AddScript(var Registry: String; const AllowException: Boolean);
       procedure AddScript(var Registry: String; const AllowException: Boolean);
       property PrivilegesRequired: TPrivilegesRequired write SetPrivilegesRequired;
       property PrivilegesRequired: TPrivilegesRequired write SetPrivilegesRequired;
     end;
     end;
@@ -67,13 +67,13 @@ procedure TWizardFormRegistryHelper.UpdateImages;
 begin
 begin
  { After a DPI change the button's Width and Height isn't yet updated, so calculate it ourselves }
  { After a DPI change the button's Width and Height isn't yet updated, so calculate it ourselves }
   var WH := MulDiv(16, FForm.CurrentPPI, 96);
   var WH := MulDiv(16, FForm.CurrentPPI, 96);
-  FMinVerDocImage.Picture.Graphic:= GetImage(MainForm.HelpButton, WH);
+  FMinVerDocBitBtn.Bitmap.Assign(GetImage(MainForm.HelpButton, WH));
 end;
 end;
 
 
 constructor TWizardFormRegistryHelper.Create(const Form: TForm;
 constructor TWizardFormRegistryHelper.Create(const Form: TForm;
   const FileEdit: TEdit; const FileButton: TButton; const UninsDeleteKeyCheck,
   const FileEdit: TEdit; const FileButton: TButton; const UninsDeleteKeyCheck,
   UninsDeleteKeyIfEmptyCheck, UninsDeleteValueCheck, MinVerCheck: TCheckBox;
   UninsDeleteKeyIfEmptyCheck, UninsDeleteValueCheck, MinVerCheck: TCheckBox;
-  const MinVerEdit: TEdit; const MinVerDocImage: TImage);
+  const MinVerEdit: TEdit; const MinVerDocBitBtn: TBitmapButton);
 begin
 begin
   FForm := Form;
   FForm := Form;
   FFileEdit := FileEdit;
   FFileEdit := FileEdit;
@@ -82,14 +82,14 @@ begin
   FUninsDeleteValueCheck := UninsDeleteValueCheck;
   FUninsDeleteValueCheck := UninsDeleteValueCheck;
   FMinVerCheck := MinVerCheck;
   FMinVerCheck := MinVerCheck;
   FMinVerEdit := MinVerEdit;
   FMinVerEdit := MinVerEdit;
-  FMinVerDocImage := MinVerDocImage;
+  FMinVerDocBitBtn := MinVerDocBitBtn;
 
 
   FileButton.OnClick := FileButtonClick;
   FileButton.OnClick := FileButtonClick;
   UninsDeleteKeyIfEmptyCheck.OnClick := UninsDeleteKeyIfEmptyCheckClick;
   UninsDeleteKeyIfEmptyCheck.OnClick := UninsDeleteKeyIfEmptyCheckClick;
   MinVerCheck.OnClick := MinVerCheckClick;
   MinVerCheck.OnClick := MinVerCheckClick;
   MinVerCheck.OnClick(nil);
   MinVerCheck.OnClick(nil);
-  MinVerDocImage.OnClick := MinVerDocImageClick;
-  MinVerDocImage.Cursor := crHandPoint;
+  MinVerDocBitBtn.OnClick := MinVerDocBitBtnClick;
+  MinVerDocBitBtn.Cursor := crHandPoint;
 
 
   TryEnableAutoCompleteFileSystem(FileEdit.Handle);
   TryEnableAutoCompleteFileSystem(FileEdit.Handle);
 
 
@@ -119,12 +119,12 @@ end;
 procedure TWizardFormRegistryHelper.MinVerCheckClick(Sender: TObject);
 procedure TWizardFormRegistryHelper.MinVerCheckClick(Sender: TObject);
 begin
 begin
   FMinVerEdit.Enabled := FMinVerCheck.Checked;
   FMinVerEdit.Enabled := FMinVerCheck.Checked;
-  FMinVerDocImage.Visible := FMinVerCheck.Checked;
+  FMinVerDocBitBtn.Visible := FMinVerCheck.Checked;
   if FMinVerEdit.Enabled then
   if FMinVerEdit.Enabled then
     FForm.ActiveControl := FMinVerEdit;
     FForm.ActiveControl := FMinVerEdit;
 end;
 end;
 
 
-procedure TWizardFormRegistryHelper.MinVerDocImageClick(Sender: TObject);
+procedure TWizardFormRegistryHelper.MinVerDocBitBtnClick(Sender: TObject);
 begin
 begin
   if Assigned(HtmlHelp) then
   if Assigned(HtmlHelp) then
     HtmlHelp(GetDesktopWindow, PChar(GetHelpFile), HH_DISPLAY_TOPIC, Cardinal(PChar('topic_winvernotes.htm')));
     HtmlHelp(GetDesktopWindow, PChar(GetHelpFile), HH_DISPLAY_TOPIC, Cardinal(PChar('topic_winvernotes.htm')));

+ 8 - 2
Projects/Src/Setup.ScriptClasses.pas

@@ -25,7 +25,7 @@ uses
   uPSR_stdctrls, uPSR_extctrls, uPSR_comobj,
   uPSR_stdctrls, uPSR_extctrls, uPSR_comobj,
   NewStaticText, NewCheckListBox, NewProgressBar, RichEditViewer,
   NewStaticText, NewCheckListBox, NewProgressBar, RichEditViewer,
   ExtCtrls, UIStateForm, Setup.SetupForm, Setup.MainForm, Setup.WizardForm, Shared.SetupTypes, PasswordEdit,
   ExtCtrls, UIStateForm, Setup.SetupForm, Setup.MainForm, Setup.WizardForm, Shared.SetupTypes, PasswordEdit,
-  FolderTreeView, BitmapImage, NewNotebook, Setup.ScriptDlg, BidiCtrls,
+  FolderTreeView, BitmapButton, BitmapImage, NewNotebook, Setup.ScriptDlg, BidiCtrls,
   Setup.UninstallProgressForm;
   Setup.UninstallProgressForm;
 
 
 type
 type
@@ -138,12 +138,17 @@ end;
 procedure TBitmapAlphaFormat_W(Self: TBitmap; const T: TAlphaFormat); begin Self.AlphaFormat := T; end;
 procedure TBitmapAlphaFormat_W(Self: TBitmap; const T: TAlphaFormat); begin Self.AlphaFormat := T; end;
 procedure TBitmapAlphaFormat_R(Self: TBitmap; var T: TAlphaFormat); begin T := Self.AlphaFormat; end;
 procedure TBitmapAlphaFormat_R(Self: TBitmap; var T: TAlphaFormat); begin T := Self.AlphaFormat; end;
 
 
-procedure RegisterBitmapImage_R(Cl: TPSRuntimeClassImporter);
+procedure RegisterBitmapButton_R(Cl: TPSRuntimeClassImporter);
 begin
 begin
   with Cl.FindClass('TBitmap') do
   with Cl.FindClass('TBitmap') do
   begin
   begin
     RegisterPropertyHelper(@TBitmapAlphaFormat_R, @TBitmapAlphaFormat_W, 'AlphaFormat');
     RegisterPropertyHelper(@TBitmapAlphaFormat_R, @TBitmapAlphaFormat_W, 'AlphaFormat');
   end;
   end;
+  Cl.Add(TBitmapButton);
+end;
+
+procedure RegisterBitmapImage_R(Cl: TPSRuntimeClassImporter);
+begin
   Cl.Add(TBitmapImage);
   Cl.Add(TBitmapImage);
 end;
 end;
 
 
@@ -431,6 +436,7 @@ begin
     RegisterCustomFolderTreeView_R(Cl);
     RegisterCustomFolderTreeView_R(Cl);
     RegisterFolderTreeView_R(Cl);
     RegisterFolderTreeView_R(Cl);
     RegisterStartMenuFolderTreeView_R(Cl);
     RegisterStartMenuFolderTreeView_R(Cl);
+    RegisterBitmapButton_R(Cl);
     RegisterBitmapImage_R(Cl);
     RegisterBitmapImage_R(Cl);
     RegisterBidiCtrls_R(Cl);
     RegisterBidiCtrls_R(Cl);
 
 

+ 6 - 1
Projects/Src/Setup.ScriptFunc.pas

@@ -21,7 +21,7 @@ implementation
 uses
 uses
   Windows,
   Windows,
   Forms, SysUtils, Classes, Graphics, ActiveX, Generics.Collections,
   Forms, SysUtils, Classes, Graphics, ActiveX, Generics.Collections,
-  uPSUtils, PathFunc, ISSigFunc, ECDSA, BrowseFunc, MD5, SHA1, SHA256, BitmapImage, PSStackHelper,
+  uPSUtils, PathFunc, ISSigFunc, ECDSA, BrowseFunc, MD5, SHA1, SHA256, BitmapButton, BitmapImage, PSStackHelper,
   Shared.Struct, Setup.ScriptDlg, Setup.MainFunc, Shared.CommonFunc.Vcl,
   Shared.Struct, Setup.ScriptDlg, Setup.MainFunc, Shared.CommonFunc.Vcl,
   Shared.CommonFunc, Shared.FileClass, SetupLdrAndSetup.RedirFunc,
   Shared.CommonFunc, Shared.FileClass, SetupLdrAndSetup.RedirFunc,
   Setup.Install, SetupLdrAndSetup.InstFunc, Setup.InstFunc, Setup.InstFunc.Ole,
   Setup.Install, SetupLdrAndSetup.InstFunc, Setup.InstFunc, Setup.InstFunc.Ole,
@@ -1814,6 +1814,11 @@ var
       if ErrorCode <> 0 then
       if ErrorCode <> 0 then
         raise Exception.Create(Win32ErrorString(ErrorCode));
         raise Exception.Create(Win32ErrorString(ErrorCode));
     end);
     end);
+    RegisterScriptFunc('INITIALIZEBITMAPBUTTONFROMICON', procedure(const Caller: TPSExec; const OrgName: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
+    begin
+      var AscendingTrySizes := Stack.GetIntArray(PStart-4);
+      Stack.SetBool(PStart, TBitmapButton(Stack.GetClass(PStart-1)).InitializeFromIcon(0, PChar(Stack.GetString(PStart-2)), Stack.GetInt(PStart-3), AscendingTrySizes));
+    end);
     RegisterScriptFunc('INITIALIZEBITMAPIMAGEFROMICON', procedure(const Caller: TPSExec; const OrgName: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     RegisterScriptFunc('INITIALIZEBITMAPIMAGEFROMICON', procedure(const Caller: TPSExec; const OrgName: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     begin
     begin
       var AscendingTrySizes := Stack.GetIntArray(PStart-4);
       var AscendingTrySizes := Stack.GetIntArray(PStart-4);

+ 12 - 0
Projects/Src/Shared.FileClass.pas

@@ -58,6 +58,7 @@ type
     constructor Create(const AFilename: String;
     constructor Create(const AFilename: String;
       ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
       ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
       ASharing: TFileSharing);
       ASharing: TFileSharing);
+    constructor CreateDuplicate(const ASourceFile: TFile);
     constructor CreateWithExistingHandle(const AHandle: THandle);
     constructor CreateWithExistingHandle(const AHandle: THandle);
     destructor Destroy; override;
     destructor Destroy; override;
     function Read(var Buffer; Count: Cardinal): Cardinal; override;
     function Read(var Buffer; Count: Cardinal): Cardinal; override;
@@ -217,6 +218,17 @@ begin
   FHandleCreated := True;
   FHandleCreated := True;
 end;
 end;
 
 
+constructor TFile.CreateDuplicate(const ASourceFile: TFile);
+begin
+  inherited Create;
+  var LHandle: THandle;
+  if not DuplicateHandle(GetCurrentProcess, ASourceFile.Handle,
+     GetCurrentProcess, @LHandle, 0, False, DUPLICATE_SAME_ACCESS) then
+    RaiseLastError;
+  FHandle := LHandle;  { assign only on success }
+  FHandleCreated := True;
+end;
+
 constructor TFile.CreateWithExistingHandle(const AHandle: THandle);
 constructor TFile.CreateWithExistingHandle(const AHandle: THandle);
 begin
 begin
   inherited Create;
   inherited Create;

+ 1 - 0
Projects/Src/Shared.ScriptFunc.pas

@@ -539,6 +539,7 @@ initialization
     'function CreateCallback(Method: AnyMethod): Longword;',
     'function CreateCallback(Method: AnyMethod): Longword;',
     'function IsDotNetInstalled(const MinVersion: TDotNetVersion; const MinServicePack: Cardinal): Boolean;',
     'function IsDotNetInstalled(const MinVersion: TDotNetVersion; const MinServicePack: Cardinal): Boolean;',
     'function IsMsiProductInstalled(const UpgradeCode: String; const PackedMinVersion: Int64): Boolean;',
     'function IsMsiProductInstalled(const UpgradeCode: String; const PackedMinVersion: Int64): Boolean;',
+    'function InitializeBitmapButtonFromIcon(const BitmapButton: TBitmapButton; const IconFilename: String; const BkColor: TColor; const AscendingTrySizes: TArrayOfInteger): Boolean;',
     'function InitializeBitmapImageFromIcon(const BitmapImage: TBitmapImage; const IconFilename: String; const BkColor: TColor; const AscendingTrySizes: TArrayOfInteger): Boolean;',
     'function InitializeBitmapImageFromIcon(const BitmapImage: TBitmapImage; const IconFilename: String; const BkColor: TColor; const AscendingTrySizes: TArrayOfInteger): Boolean;',
     'procedure Extract7ZipArchive(const ArchiveFileName, DestDir: String; const FullPaths: Boolean; const OnExtractionProgress: TOnExtractionProgress);',
     'procedure Extract7ZipArchive(const ArchiveFileName, DestDir: String; const FullPaths: Boolean; const OnExtractionProgress: TOnExtractionProgress);',
     'procedure ExtractArchive(const ArchiveFilename, DestDir, Password: String; const FullPaths: Boolean; const OnExtractionProgress: TOnExtractionProgress);',
     'procedure ExtractArchive(const ArchiveFilename, DestDir, Password: String; const FullPaths: Boolean; const OnExtractionProgress: TOnExtractionProgress);',

+ 6 - 4
README.md

@@ -84,6 +84,7 @@ the following component units, which can be found in the [Components]
 directory.
 directory.
 
 
 - BidiCtrls
 - BidiCtrls
+- BitmapButton
 - BitmapImage
 - BitmapImage
 - FolderTreeView
 - FolderTreeView
 - NewCheckListBox
 - NewCheckListBox
@@ -158,18 +159,19 @@ How do the projects link together?
 Source code tips
 Source code tips
 ----------------
 ----------------
 
 
-- When building the projects in Debug mode it outputs to [Projects\Bin] and when
-  debugging it will run from within this directory. To prepare this directory
+- When building the projects in Debug mode, it outputs to [Projects\Bin] and when
+  debugging, it will run from within this directory. To prepare this directory
   with some extra files you must run **Projects\Bin\synch-isfiles.bat**. Running
   with some extra files you must run **Projects\Bin\synch-isfiles.bat**. Running
   the aforementioned **build.bat** or **build-ce.bat** first is not necessary.
   the aforementioned **build.bat** or **build-ce.bat** first is not necessary.
 
 
-- When debugging the Setup project you should first build all projects in Debug
+- When debugging the Setup project, you should first build all projects in Debug
   mode, then run the Compil32 project and compile the Debug.iss script which
   mode, then run the Compil32 project and compile the Debug.iss script which
   should open automatically, and finally open and run the Setup project.
   should open automatically, and finally open and run the Setup project.
   This way you can simulate an actual installation while running under the
   This way you can simulate an actual installation while running under the
   Delphi debugger.
   Delphi debugger.
   
   
-- When building the projects in Release mode it outputs to [Files].
+- When building the projects in Release mode, it outputs to [Files]. Before
+  running Compil32, ensure that all .issig files are up to date.
   
   
 - All of the forms in the Setup project have Scaled set to False. This is
 - All of the forms in the Setup project have Scaled set to False. This is
   because they dynamically scale themselves at run-time by calling a function
   because they dynamically scale themselves at run-time by calling a function

+ 29 - 25
isdonateandmail.iss

@@ -7,18 +7,20 @@ Source: "ismail.bmp"; Flags: dontcopy noencryption
 
 
 [CustomMessages]
 [CustomMessages]
 ; No need to localize: The IS website is in English only
 ; No need to localize: The IS website is in English only
+IsDonateAndMailDonateCaption=Donate
 IsDonateAndMailDonateHint=Support Inno Setup - Thank you!
 IsDonateAndMailDonateHint=Support Inno Setup - Thank you!
+IsDonateAndMailMailCaption=Subscribe
 IsDonateAndMailMailHint=Be notified by e-mail of new Inno Setup releases
 IsDonateAndMailMailHint=Be notified by e-mail of new Inno Setup releases
 
 
 [Code]
 [Code]
-procedure DonateImageOnClick(Sender: TObject);
+procedure DonateBitmapButtonOnClick(Sender: TObject);
 var
 var
   ErrorCode: Integer;
   ErrorCode: Integer;
 begin
 begin
   ShellExecAsOriginalUser('open', 'https://jrsoftware.org/isdonate.php', '', '', SW_SHOWNORMAL, ewNoWait, ErrorCode);
   ShellExecAsOriginalUser('open', 'https://jrsoftware.org/isdonate.php', '', '', SW_SHOWNORMAL, ewNoWait, ErrorCode);
 end;
 end;
 
 
-procedure MailImageOnClick(Sender: TObject);
+procedure MailBitmapButtonOnClick(Sender: TObject);
 var
 var
   ErrorCode: Integer;
   ErrorCode: Integer;
 begin
 begin
@@ -29,7 +31,7 @@ end;
 procedure IsDonateAndMailInitializeWizard;
 procedure IsDonateAndMailInitializeWizard;
 var
 var
   ImageFileName: String;
   ImageFileName: String;
-  DonateImage, MailImage: TBitmapImage;
+  DonateBitmapButton, MailBitmapButton: TBitmapButton;
   BevelTop: Integer;
   BevelTop: Integer;
 begin
 begin
   if WizardSilent then
   if WizardSilent then
@@ -38,31 +40,33 @@ begin
   ImageFileName := ExpandConstant('{tmp}\isdonate.bmp');
   ImageFileName := ExpandConstant('{tmp}\isdonate.bmp');
   ExtractTemporaryFile(ExtractFileName(ImageFileName));
   ExtractTemporaryFile(ExtractFileName(ImageFileName));
 
 
-  DonateImage := TBitmapImage.Create(WizardForm);
-  DonateImage.AutoSize := True;
-  DonateImage.Bitmap.LoadFromFile(ImageFileName);
-  DonateImage.Hint := CustomMessage('IsDonateAndMailDonateHint');
-  DonateImage.ShowHint := True;
-  DonateImage.Anchors := [akLeft, akBottom];
+  DonateBitmapButton := TBitmapButton.Create(WizardForm);
+  DonateBitmapButton.AutoSize := True;
+  DonateBitmapButton.Bitmap.LoadFromFile(ImageFileName);
+  DonateBitmapButton.Caption := CustomMessage('IsDonateAndMailDonateCaption');
+  DonateBitmapButton.Hint := CustomMessage('IsDonateAndMailDonateHint');
+  DonateBitmapButton.ShowHint := True;
+  DonateBitmapButton.Anchors := [akLeft, akBottom];
   BevelTop := WizardForm.Bevel.Top;
   BevelTop := WizardForm.Bevel.Top;
-  DonateImage.Top := BevelTop + (WizardForm.ClientHeight - BevelTop - DonateImage.Bitmap.Height) div 2;
-  DonateImage.Left := DonateImage.Top - BevelTop;
-  DonateImage.Cursor := crHand;
-  DonateImage.OnClick := @DonateImageOnClick;
-  DonateImage.Parent := WizardForm;
+  DonateBitmapButton.Top := BevelTop + (WizardForm.ClientHeight - BevelTop - DonateBitmapButton.Bitmap.Height) div 2;
+  DonateBitmapButton.Left := DonateBitmapButton.Top - BevelTop;
+  DonateBitmapButton.Cursor := crHand;
+  DonateBitmapButton.OnClick := @DonateBitmapButtonOnClick;
+  DonateBitmapButton.Parent := WizardForm;
 
 
   ImageFileName := ExpandConstant('{tmp}\ismail.bmp');
   ImageFileName := ExpandConstant('{tmp}\ismail.bmp');
   ExtractTemporaryFile(ExtractFileName(ImageFileName));
   ExtractTemporaryFile(ExtractFileName(ImageFileName));
 
 
-  MailImage := TBitmapImage.Create(WizardForm);
-  MailImage.AutoSize := True;
-  MailImage.Bitmap.LoadFromFile(ImageFileName);
-  MailImage.Hint := CustomMessage('IsDonateAndMailMailHint');
-  MailImage.ShowHint := True;
-  MailImage.Anchors := [akLeft, akBottom];
-  MailImage.Top := DonateImage.Top
-  MailImage.Left := DonateImage.Left + DonateImage.Width + ScaleX(8);
-  MailImage.Cursor := crHand;
-  MailImage.OnClick := @MailImageOnClick;
-  MailImage.Parent := WizardForm;
+  MailBitmapButton := TBitmapButton.Create(WizardForm);
+  MailBitmapButton.AutoSize := True;
+  MailBitmapButton.Bitmap.LoadFromFile(ImageFileName);
+  MailBitmapButton.Caption := CustomMessage('IsDonateAndMailMailCaption');
+  MailBitmapButton.Hint := CustomMessage('IsDonateAndMailMailHint');
+  MailBitmapButton.ShowHint := True;
+  MailBitmapButton.Anchors := [akLeft, akBottom];
+  MailBitmapButton.Top := DonateBitmapButton.Top
+  MailBitmapButton.Left := DonateBitmapButton.Left + DonateBitmapButton.Width + ScaleX(4);
+  MailBitmapButton.Cursor := crHand;
+  MailBitmapButton.OnClick := @MailBitmapButtonOnClick;
+  MailBitmapButton.Parent := WizardForm;
 end;
 end;

+ 3 - 1
whatsnew.htm

@@ -212,6 +212,7 @@ issigtool --key-file="MyKey.ispublickey" verify "MyProg.dll"</code></pre>
           The <i>Highlight occurrences of current selection</i> option (which is enabled by default) still does.</li>
           The <i>Highlight occurrences of current selection</i> option (which is enabled by default) still does.</li>
       <li>Dark mode is now supported throughout.</li>
       <li>Dark mode is now supported throughout.</li>
       <li>Improved support for high-contrast themes.</li>
       <li>Improved support for high-contrast themes.</li>
+      <li>Improved support for screen readers.</li>
     </ul>
     </ul>
   </li>
   </li>
   <li><tt>[Files]</tt> section parameter <tt>Excludes</tt> can now be combined with the <tt>external</tt> flag.</li>
   <li><tt>[Files]</tt> section parameter <tt>Excludes</tt> can now be combined with the <tt>external</tt> flag.</li>
@@ -227,8 +228,9 @@ issigtool --key-file="MyKey.ispublickey" verify "MyProg.dll"</code></pre>
   </li>
   </li>
   <li>Pascal Scripting changes:
   <li>Pascal Scripting changes:
     <ul>
     <ul>
+      <li>Added new <tt>TBitmapButton</tt> support class which works just like <tt>TBitmapImage</tt>, but is accessible by keyboard and compatible with screen readers. Make sure to set the <tt>Caption</tt> property, even if it isn't visible. See updated example script <i>CodeClasses.iss</i> for an example.</li>
+      <li>Added new <tt>InitializeBitmapButtonFromIcon</tt> and <tt>GetSHA256OfStream</tt> support functions.</li>
       <li>Added new <tt>LastBaseNameOrUrl</tt> property to support class <tt>TDownloadWizardPage</tt>. See updated example script <i>CodeDownloadFiles.iss</i> for an example.</li>
       <li>Added new <tt>LastBaseNameOrUrl</tt> property to support class <tt>TDownloadWizardPage</tt>. See updated example script <i>CodeDownloadFiles.iss</i> for an example.</li>
-      <li>Added new <tt>GetSHA256OfStream</tt> support function.</li>
       <li><i>Fix:</i> Event function <tt>CurPageChanged</tt> is now always only triggered when the current page actually changes. Before it was called twice in a row for <tt>wpPreparing</tt> when the script had a <tt>PrepareToInstall</tt> event function which returned a non empty string to instruct Setup to stop.</li>
       <li><i>Fix:</i> Event function <tt>CurPageChanged</tt> is now always only triggered when the current page actually changes. Before it was called twice in a row for <tt>wpPreparing</tt> when the script had a <tt>PrepareToInstall</tt> event function which returned a non empty string to instruct Setup to stop.</li>
     </ul>
     </ul>
   </li>
   </li>