浏览代码

Added support for multiple wizard images, selecting best match at run time.

Martijn Laan 7 年之前
父节点
当前提交
342d78bddd
共有 3 个文件被更改,包括 113 次插入50 次删除
  1. 53 25
      Projects/Compile.pas
  2. 29 11
      Projects/Main.pas
  3. 31 14
      Projects/Wizard.pas

+ 53 - 25
Projects/Compile.pas

@@ -501,6 +501,7 @@ type
     procedure WriteDebugEntry(Kind: TDebugEntryKind; Index: Integer);
     procedure WriteDebugEntry(Kind: TDebugEntryKind; Index: Integer);
     procedure WriteCompiledCodeText(const CompiledCodeText: Ansistring);
     procedure WriteCompiledCodeText(const CompiledCodeText: Ansistring);
     procedure WriteCompiledCodeDebugInfo(const CompiledCodeDebugInfo: AnsiString);
     procedure WriteCompiledCodeDebugInfo(const CompiledCodeDebugInfo: AnsiString);
+    function CreateMemoryStreamsFromFiles(const AFiles: String): TList;
   public
   public
     AppData: Longint;
     AppData: Longint;
     CallbackProc: TCompilerCallbackProc;
     CallbackProc: TCompilerCallbackProc;
@@ -701,6 +702,39 @@ begin
   end;
   end;
 end;
 end;
 
 
+function ExtractStr(var S: String; const Separator: Char): String;
+var
+  I: Integer;
+begin
+  repeat
+    I := PathPos(Separator, S);
+    if I = 0 then I := Length(S)+1;
+    Result := Trim(Copy(S, 1, I-1));
+    S := Trim(Copy(S, I+1, Maxint));
+  until (Result <> '') or (S = '');
+end;
+
+function TSetupCompiler.CreateMemoryStreamsFromFiles(const AFiles: String): TList;
+var
+  S, Filename: String;
+begin
+  Result := TList.Create;
+  try
+    S := AFiles;
+    while True do begin
+      Filename := ExtractStr(S, ',');
+      if Filename = '' then
+        Break;
+      Filename := PrependSourceDirName(Filename);
+      AddStatus(Format(SCompilerStatusReadingInFile, [FileName]));
+      Result.Add(CreateMemoryStreamFromFile(FileName));
+    end;
+  except
+    Result.Free;
+    raise Exception.CreateFmt(SCompilerReadError, [Filename, GetExceptMessage]);
+  end;
+end;
+
 function FileSizeAndCRCIs(const Filename: String; const Size: Cardinal;
 function FileSizeAndCRCIs(const Filename: String; const Size: Cardinal;
   const CRC: Longint): Boolean;
   const CRC: Longint): Boolean;
 var
 var
@@ -2949,18 +2983,6 @@ begin
   end;
   end;
 end;
 end;
 
 
-function ExtractStr(var S: String; const Separator: Char): String;
-var
-  I: Integer;
-begin
-  repeat
-    I := PathPos(Separator, S);
-    if I = 0 then I := Length(S)+1;
-    Result := Trim(Copy(S, 1, I-1));
-    S := Trim(Copy(S, I+1, Maxint));
-  until (Result <> '') or (S = '');
-end;
-
 function ExtractFlag(var S: String; const FlagStrs: array of PChar): Integer;
 function ExtractFlag(var S: String; const FlagStrs: array of PChar): Integer;
 var
 var
   I: Integer;
   I: Integer;
@@ -7661,8 +7683,8 @@ var
   SetupFile: TFile;
   SetupFile: TFile;
   ExeFile: TFile;
   ExeFile: TFile;
   LicenseText, InfoBeforeText, InfoAfterText: AnsiString;
   LicenseText, InfoBeforeText, InfoAfterText: AnsiString;
-  WizardImage: TMemoryStream;
-  WizardSmallImage: TMemoryStream;
+  WizardImages: TList;
+  WizardSmallImages: TList;
   DecompressorDLL, DecryptionDLL: TMemoryStream;
   DecompressorDLL, DecryptionDLL: TMemoryStream;
 
 
   SetupLdrOffsetTable: TSetupLdrOffsetTable;
   SetupLdrOffsetTable: TSetupLdrOffsetTable;
@@ -7764,8 +7786,12 @@ var
         SECompressedBlockWrite(W, UninstallRunEntries[J]^, SizeOf(TSetupRunEntry),
         SECompressedBlockWrite(W, UninstallRunEntries[J]^, SizeOf(TSetupRunEntry),
           SetupRunEntryStrings, SetupRunEntryAnsiStrings);
           SetupRunEntryStrings, SetupRunEntryAnsiStrings);
 
 
-      WriteStream(WizardImage, W);
-      WriteStream(WizardSmallImage, W);
+      W.Write(WizardImages.Count, SizeOf(LongInt));
+      for J := 0 to WizardImages.Count-1 do
+        WriteStream(WizardImages[J], W);
+      W.Write(WizardSmallImages.Count, SizeOf(LongInt));
+      for J := 0 to WizardSmallImages.Count-1 do
+        WriteStream(WizardSmallImages[J], W);
       if SetupHeader.CompressMethod in [cmZip, cmBzip] then
       if SetupHeader.CompressMethod in [cmZip, cmBzip] then
         WriteStream(DecompressorDLL, W);
         WriteStream(DecompressorDLL, W);
       if shEncryptionUsed in SetupHeader.Options then
       if shEncryptionUsed in SetupHeader.Options then
@@ -8360,8 +8386,8 @@ begin
   InitPreprocessor;
   InitPreprocessor;
   InitLZMADLL;
   InitLZMADLL;
 
 
-  WizardImage := nil;
-  WizardSmallImage := nil;
+  WizardImages := nil;
+  WizardSmallImages := nil;
   SetupE32 := nil;
   SetupE32 := nil;
   DecompressorDLL := nil;
   DecompressorDLL := nil;
   DecryptionDLL := nil;
   DecryptionDLL := nil;
@@ -8636,12 +8662,10 @@ begin
     { Read wizard image }
     { Read wizard image }
     LineNumber := SetupDirectiveLines[ssWizardImageFile];
     LineNumber := SetupDirectiveLines[ssWizardImageFile];
     AddStatus(Format(SCompilerStatusReadingFile, ['WizardImageFile']));
     AddStatus(Format(SCompilerStatusReadingFile, ['WizardImageFile']));
-    AddStatus(Format(SCompilerStatusReadingInFile, [PrependSourceDirName(WizardImageFile)]));
-    WizardImage := CreateMemoryStreamFromFile(PrependSourceDirName(WizardImageFile));
+    WizardImages := CreateMemoryStreamsFromFiles(WizardImageFile);
     LineNumber := SetupDirectiveLines[ssWizardSmallImageFile];
     LineNumber := SetupDirectiveLines[ssWizardSmallImageFile];
     AddStatus(Format(SCompilerStatusReadingFile, ['WizardSmallImageFile']));
     AddStatus(Format(SCompilerStatusReadingFile, ['WizardSmallImageFile']));
-    AddStatus(Format(SCompilerStatusReadingInFile, [PrependSourceDirName(WizardSmallImageFile)]));
-    WizardSmallImage := CreateMemoryStreamFromFile(PrependSourceDirName(WizardSmallImageFile));
+    WizardSmallImages := CreateMemoryStreamsFromFiles(WizardSmallImageFile);
     LineNumber := 0;
     LineNumber := 0;
 
 
     { Prepare Setup executable & signed uninstaller data }
     { Prepare Setup executable & signed uninstaller data }
@@ -8654,7 +8678,7 @@ begin
     { Read languages:
     { Read languages:
 
 
       Non Unicode:
       Non Unicode:
-      
+
       1. Read Default.isl messages:
       1. Read Default.isl messages:
 
 
       ReadDefaultMessages calls EnumMessages for Default.isl's [Messages], with Ext set to -2.
       ReadDefaultMessages calls EnumMessages for Default.isl's [Messages], with Ext set to -2.
@@ -9014,8 +9038,12 @@ begin
     DecryptionDLL.Free;
     DecryptionDLL.Free;
     DecompressorDLL.Free;
     DecompressorDLL.Free;
     SetupE32.Free;
     SetupE32.Free;
-    WizardSmallImage.Free;
-    WizardImage.Free;
+    for I := WizardSmallImages.Count-1 downto 0 do
+      TStream(WizardSmallImages[I]).Free;
+    WizardSmallImages.Free;
+    for I := WizardImages.Count-1 downto 0 do
+      TStream(WizardImages[I]).Free;
+    WizardImages.Free;
     FreeListItems(LanguageEntries, SetupLanguageEntryStrings, SetupLanguageEntryAnsiStrings);
     FreeListItems(LanguageEntries, SetupLanguageEntryStrings, SetupLanguageEntryAnsiStrings);
     FreeListItems(CustomMessageEntries, SetupCustomMessageEntryStrings, SetupCustomMessageEntryAnsiStrings);
     FreeListItems(CustomMessageEntries, SetupCustomMessageEntryStrings, SetupCustomMessageEntryAnsiStrings);
     FreeListItems(PermissionEntries, SetupPermissionEntryStrings, SetupPermissionEntryAnsiStrings);
     FreeListItems(PermissionEntries, SetupPermissionEntryStrings, SetupPermissionEntryAnsiStrings);

+ 29 - 11
Projects/Main.pas

@@ -131,8 +131,8 @@ var
   SetupHeader: TSetupHeader;
   SetupHeader: TSetupHeader;
   LangOptions: TSetupLanguageEntry;
   LangOptions: TSetupLanguageEntry;
   Entries: array[TEntryType] of TList;
   Entries: array[TEntryType] of TList;
-  WizardImage: TBitmap;
-  WizardSmallImage: TBitmap;
+  WizardImages: TList;
+  WizardSmallImages: TList;
   CloseApplicationsFilterList: TStringList;
   CloseApplicationsFilterList: TStringList;
 
 
   { User options }
   { User options }
@@ -2551,7 +2551,7 @@ var
     end;
     end;
   end;
   end;
 
 
-  procedure ReadWizardImage(var WizardImage: TBitmap; const R: TCompressedBlockReader);
+  function ReadWizardImage(const R: TCompressedBlockReader): TBitmap;
   var
   var
     MemStream: TMemoryStream;
     MemStream: TMemoryStream;
   begin
   begin
@@ -2559,9 +2559,9 @@ var
     try
     try
       ReadFileIntoStream(MemStream, R);
       ReadFileIntoStream(MemStream, R);
       MemStream.Seek(0, soFromBeginning);
       MemStream.Seek(0, soFromBeginning);
-      WizardImage := TAlphaBitmap.Create;
-      TAlphaBitmap(WizardImage).AlphaFormat := TAlphaFormat(SetupHeader.WizardImageAlphaFormat);
-      WizardImage.LoadFromStream(MemStream);
+      Result := TAlphaBitmap.Create;
+      TAlphaBitmap(Result).AlphaFormat := TAlphaFormat(SetupHeader.WizardImageAlphaFormat);
+      Result.LoadFromStream(MemStream);
     finally
     finally
       MemStream.Free;
       MemStream.Free;
     end;
     end;
@@ -2739,7 +2739,7 @@ var
 var
 var
   ParamName, ParamValue: String;
   ParamName, ParamValue: String;
   StartParam: Integer;
   StartParam: Integer;
-  I: Integer;
+  I, N: Integer;
   IsRespawnedProcess, EnableLogging, WantToSuppressMsgBoxes, Res: Boolean;
   IsRespawnedProcess, EnableLogging, WantToSuppressMsgBoxes, Res: Boolean;
   DebugWndValue: HWND;
   DebugWndValue: HWND;
   LogFilename: String;
   LogFilename: String;
@@ -3021,8 +3021,13 @@ begin
           Integer(@PSetupRunEntry(nil).OnlyBelowVersion));
           Integer(@PSetupRunEntry(nil).OnlyBelowVersion));
 
 
         { Wizard image }
         { Wizard image }
-        ReadWizardImage(WizardImage, Reader);
-        ReadWizardImage(WizardSmallImage, Reader);
+
+        Reader.Read(N, SizeOf(LongInt));
+        for I := 0 to N-1 do
+          WizardImages.Add(ReadWizardImage(Reader));
+        Reader.Read(N, SizeOf(LongInt));
+        for I := 0 to N-1 do
+          WizardSmallImages.Add(ReadWizardImage(Reader));
         { Decompressor DLL }
         { Decompressor DLL }
         DecompressorDLL := nil;
         DecompressorDLL := nil;
         if SetupHeader.CompressMethod in [cmZip, cmBzip] then begin
         if SetupHeader.CompressMethod in [cmZip, cmBzip] then begin
@@ -4357,6 +4362,18 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure FreeWizardImages;
+var
+  I: Integer;
+begin
+  for I := WizardImages.Count-1 downto 0 do
+    TBitmap(WizardImages[I]).Free;
+  FreeAndNil(WizardImages);
+  for I := WizardSmallImages.Count-1 downto 0 do
+    TBitmap(WizardSmallImages[I]).Free;
+  FreeAndNil(WizardSmallImages);
+end;
+
 initialization
 initialization
   IsNT := UsingWinNT;
   IsNT := UsingWinNT;
   InitIsWin64AndProcessorArchitecture;
   InitIsWin64AndProcessorArchitecture;
@@ -4374,12 +4391,13 @@ initialization
   DeleteFilesAfterInstallList := TStringList.Create;
   DeleteFilesAfterInstallList := TStringList.Create;
   DeleteDirsAfterInstallList := TStringList.Create;
   DeleteDirsAfterInstallList := TStringList.Create;
   CloseApplicationsFilterList := TStringList.Create;
   CloseApplicationsFilterList := TStringList.Create;
+  WizardImages := TList.Create;
+  WizardSmallImages := TList.Create;
   SHGetKnownFolderPathFunc := GetProcAddress(SafeLoadLibrary(AddBackslash(GetSystemDir) + shell32,
   SHGetKnownFolderPathFunc := GetProcAddress(SafeLoadLibrary(AddBackslash(GetSystemDir) + shell32,
     SEM_NOOPENFILEERRORBOX), 'SHGetKnownFolderPath');
     SEM_NOOPENFILEERRORBOX), 'SHGetKnownFolderPath');
 
 
 finalization
 finalization
-  FreeAndNil(WizardImage);
-  FreeAndNil(WizardSmallImage);
+  FreeWizardImages;
   FreeAndNil(CloseApplicationsFilterList);
   FreeAndNil(CloseApplicationsFilterList);
   FreeAndNil(DeleteDirsAfterInstallList);
   FreeAndNil(DeleteDirsAfterInstallList);
   FreeAndNil(DeleteFilesAfterInstallList);
   FreeAndNil(DeleteFilesAfterInstallList);

+ 31 - 14
Projects/Wizard.pas

@@ -664,6 +664,23 @@ constructor TWizardForm.Create(AOwner: TComponent);
     end;
     end;
   end;
   end;
 
 
+  function SelectBestImage(WizardImages: TList; TargetWidth, TargetHeight: Integer): TBitmap;
+  var
+    TargetArea, Difference, SmallestDifference, I: Integer;
+  begin
+    { Find the image with the smallest area difference compared to the target area. }
+    TargetArea := TargetWidth*TargetHeight;
+    SmallestDifference := -1;
+    Result := nil;
+    for I := 0 to WizardImages.Count-1 do begin
+      Difference := Abs(TargetArea-TBitmap(WizardImages[I]).Width*TBitmap(WizardImages[I]).Height);
+      if (SmallestDifference = -1) or (Difference < SmallestDifference) then begin
+        Result := WizardImages[I];
+        SmallestDifference := Difference;
+      end;
+    end;
+  end;
+
 var
 var
   X, W1, W2: Integer;
   X, W1, W2: Integer;
   SystemMenu: HMENU;
   SystemMenu: HMENU;
@@ -686,22 +703,22 @@ begin
 {$IFDEF IS_D7}
 {$IFDEF IS_D7}
   MainPanel.ParentBackground := False;
   MainPanel.ParentBackground := False;
 {$ENDIF}
 {$ENDIF}
-
   { Prior to scaling the form, shrink WizardSmallBitmapImage if it's currently
   { Prior to scaling the form, shrink WizardSmallBitmapImage if it's currently
     larger than WizardSmallImage. This way, stretching will not occur if the
     larger than WizardSmallImage. This way, stretching will not occur if the
     user specifies a smaller-than-default image and WizardImageStretch=yes,
     user specifies a smaller-than-default image and WizardImageStretch=yes,
     except if the form has to be scaled (e.g. due to Large Fonts). }
     except if the form has to be scaled (e.g. due to Large Fonts). }
-  I := WizardSmallBitmapImage.Height - WizardSmallImage.Height;
-  if I > 0 then begin
-    WizardSmallBitmapImage.Height := WizardSmallBitmapImage.Height - I;
-    WizardSmallBitmapImage.Top := WizardSmallBitmapImage.Top + (I div 2);
-  end;
-  I := WizardSmallBitmapImage.Width - WizardSmallImage.Width;
-  if I > 0 then begin
-    WizardSmallBitmapImage.Width := WizardSmallBitmapImage.Width - I;
-    WizardSmallBitmapImage.Left := WizardSmallBitmapImage.Left + (I div 2);
+  if WizardSmallImages.Count = 1 then begin
+    I := WizardSmallBitmapImage.Height - TBitmap(WizardSmallImages[0]).Height;
+    if I > 0 then begin
+      WizardSmallBitmapImage.Height := WizardSmallBitmapImage.Height - I;
+      WizardSmallBitmapImage.Top := WizardSmallBitmapImage.Top + (I div 2);
+    end;
+    I := WizardSmallBitmapImage.Width - TBitmap(WizardSmallImages[0]).Width;
+    if I > 0 then begin
+      WizardSmallBitmapImage.Width := WizardSmallBitmapImage.Width - I;
+      WizardSmallBitmapImage.Left := WizardSmallBitmapImage.Left + (I div 2);
+    end;
   end;
   end;
-
   InitializeFont;
   InitializeFont;
   if shWindowVisible in SetupHeader.Options then
   if shWindowVisible in SetupHeader.Options then
     CenterInsideControl(MainForm, True)
     CenterInsideControl(MainForm, True)
@@ -746,13 +763,13 @@ begin
   BackButton.Left := X;
   BackButton.Left := X;
 
 
   { Initialize images }
   { Initialize images }
-  WizardBitmapImage.Bitmap := WizardImage;
+  WizardBitmapImage.Bitmap := SelectBestImage(WizardImages, WizardBitmapImage.Width, WizardBitmapImage.Height);
   WizardBitmapImage.Center := True;
   WizardBitmapImage.Center := True;
   WizardBitmapImage.Stretch := (shWizardImageStretch in SetupHeader.Options);
   WizardBitmapImage.Stretch := (shWizardImageStretch in SetupHeader.Options);
-  WizardBitmapImage2.Bitmap := WizardImage;
+  WizardBitmapImage2.Bitmap := WizardBitmapImage.Bitmap;
   WizardBitmapImage2.Center := True;
   WizardBitmapImage2.Center := True;
   WizardBitmapImage2.Stretch := (shWizardImageStretch in SetupHeader.Options);
   WizardBitmapImage2.Stretch := (shWizardImageStretch in SetupHeader.Options);
-  WizardSmallBitmapImage.Bitmap := WizardSmallImage;
+  WizardSmallBitmapImage.Bitmap := SelectBestImage(WizardSmallImages, WizardSmallBitmapImage.Width, WizardSmallBitmapImage.Height);
   WizardSmallBitmapImage.Stretch := (shWizardImageStretch in SetupHeader.Options);
   WizardSmallBitmapImage.Stretch := (shWizardImageStretch in SetupHeader.Options);
   PreparingErrorBitmapImage.Bitmap.Handle := LoadBitmap(HInstance, 'STOPIMAGE');
   PreparingErrorBitmapImage.Bitmap.Handle := LoadBitmap(HInstance, 'STOPIMAGE');
   PreparingErrorBitmapImage.ReplaceColor := clSilver;
   PreparingErrorBitmapImage.ReplaceColor := clSilver;