IDE.Wizard.WizardForm.pas 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233
  1. unit IDE.Wizard.WizardForm;
  2. {
  3. Inno Setup
  4. Copyright (C) 1997-2025 Jordan Russell
  5. Portions by Martijn Laan
  6. For conditions of distribution and use, see LICENSE.TXT.
  7. Compiler IDE Script Wizard form
  8. }
  9. interface
  10. uses
  11. Windows, Forms, Classes, Graphics, StdCtrls, ExtCtrls, Controls, Dialogs, pngimage,
  12. UIStateForm, NewStaticText, DropListBox, NewCheckListBox, NewNotebook,
  13. IDE.Wizard.WizardFormFilesHelper, IDE.Wizard.WizardFormRegistryHelper, BitmapButton,
  14. Vcl.BaseImageCollection, Vcl.ImageCollection, BitmapImage;
  15. type
  16. TWizardPage = (wpWelcome, wpAppInfo, wpAppDir, wpAppFiles, wpAppAssoc, wpAppIcons,
  17. wpAppDocs, wpPrivilegesRequired, wpAppRegistry, wpLanguages, wpCompiler,
  18. wpWizardStyle, wpISPP, wpFinished);
  19. TWizardFormResult = (wrNone, wrEmpty, wrComplete);
  20. TWizardForm = class(TUIStateForm)
  21. CancelButton: TButton;
  22. NextButton: TButton;
  23. BackButton: TButton;
  24. OuterNotebook: TNewNotebook;
  25. InnerNotebook: TNewNotebook;
  26. WelcomePage: TNewNotebookPage;
  27. MainPage: TNewNotebookPage;
  28. AppInfoPage: TNewNotebookPage;
  29. AppDirPage: TNewNotebookPage;
  30. AppFilesPage: TNewNotebookPage;
  31. AppIconsPage: TNewNotebookPage;
  32. AppDocsPage: TNewNotebookPage;
  33. PrivilegesRequiredPage: TNewNotebookPage;
  34. AppRegistryPage: TNewNotebookPage;
  35. LanguagesPage: TNewNotebookPage;
  36. CompilerPage: TNewNotebookPage;
  37. ISPPPage: TNewNotebookPage;
  38. FinishedPage: TNewNotebookPage;
  39. Bevel: TBevel;
  40. WelcomeImage: TBitmapImage;
  41. WelcomeLabel1: TNewStaticText;
  42. PnlMain: TPanel;
  43. Bevel1: TBevel;
  44. PageNameLabel: TNewStaticText;
  45. PageDescriptionLabel: TNewStaticText;
  46. InnerImage: TBitmapImage;
  47. FinishedLabel: TNewStaticText;
  48. FinishedImage: TBitmapImage;
  49. WelcomeLabel2: TNewStaticText;
  50. EmptyCheck: TCheckBox;
  51. WelcomeLabel3: TNewStaticText;
  52. AppNameLabel: TNewStaticText;
  53. AppNameEdit: TEdit;
  54. AppVersionLabel: TNewStaticText;
  55. AppVersionEdit: TEdit;
  56. AppDirNameLabel: TNewStaticText;
  57. AppRootDirComboBox: TComboBox;
  58. AppRootDirEdit: TEdit;
  59. AppDirNameEdit: TEdit;
  60. NotDisableDirPageCheck: TCheckBox;
  61. AppRootDirLabel: TNewStaticText;
  62. AppPublisherLabel: TNewStaticText;
  63. AppPublisherEdit: TEdit;
  64. OtherLabel: TNewStaticText;
  65. NotCreateAppDirCheck: TCheckBox;
  66. AppFilesLabel: TNewStaticText;
  67. AppFilesListBox: TDropListBox;
  68. AppFilesAddButton: TButton;
  69. AppFilesEditButton: TButton;
  70. AppFilesRemoveButton: TButton;
  71. AppURLLabel: TNewStaticText;
  72. AppURLEdit: TEdit;
  73. AppExeLabel: TNewStaticText;
  74. AppExeEdit: TEdit;
  75. AppExeRunCheck: TCheckBox;
  76. AppExeButton: TButton;
  77. AppGroupNameLabel: TNewStaticText;
  78. AppGroupNameEdit: TEdit;
  79. NotDisableProgramGroupPageCheck: TCheckBox;
  80. AllowNoIconsCheck: TCheckBox;
  81. AppExeIconsLabel: TNewStaticText;
  82. DesktopIconCheck: TCheckBox;
  83. CreateUninstallIconCheck: TCheckBox;
  84. CreateURLIconCheck: TCheckBox;
  85. AppLicenseFileLabel: TNewStaticText;
  86. AppLicenseFileEdit: TEdit;
  87. AppLicenseFileButton: TButton;
  88. AppInfoBeforeFileLabel: TNewStaticText;
  89. AppInfoBeforeFileEdit: TEdit;
  90. AppInfoBeforeFileButton: TButton;
  91. AppInfoAfterFileLabel: TNewStaticText;
  92. AppInfoAfterFileEdit: TEdit;
  93. AppInfoAfterFileButton: TButton;
  94. RequiredLabel1: TNewStaticText;
  95. RequiredLabel2: TNewStaticText;
  96. AppFilesAddDirButton: TButton;
  97. ISPPCheck: TCheckBox;
  98. ISPPLabel: TLabel;
  99. OutputDirLabel: TNewStaticText;
  100. OutputDirEdit: TEdit;
  101. OutputBaseFileNameLabel: TNewStaticText;
  102. OutputBaseFileNameEdit: TEdit;
  103. SetupIconFileLabel: TNewStaticText;
  104. SetupIconFileEdit: TEdit;
  105. PasswordLabel: TNewStaticText;
  106. PasswordEdit: TEdit;
  107. SetupIconFileButton: TButton;
  108. EncryptionCheck: TCheckBox;
  109. OutputDirButton: TButton;
  110. LanguagesLabel: TNewStaticText;
  111. LanguagesList: TNewCheckListBox;
  112. AllLanguagesButton: TButton;
  113. NoLanguagesButton: TButton;
  114. NoAppExeCheck: TCheckBox;
  115. UseAutoProgramsCheck: TCheckBox;
  116. PrivilegesRequiredLabel: TNewStaticText;
  117. PrivilegesRequiredAdminRadioButton: TRadioButton;
  118. PrivilegesRequiredLowestRadioButton: TRadioButton;
  119. PrivilegesRequiredOverridesAllowedCommandLineCheckbox: TCheckBox;
  120. PrivilegesRequiredOverridesAllowedDialogCheckbox: TCheckBox;
  121. AppAssocPage: TNewNotebookPage;
  122. AppAssocNameEdit: TEdit;
  123. AppAssocNameLabel: TNewStaticText;
  124. CreateAssocCheck: TCheckBox;
  125. AppAssocExtLabel: TNewStaticText;
  126. AppAssocExtEdit: TEdit;
  127. AppRegistryFileLabel: TNewStaticText;
  128. AppRegistryFileEdit: TEdit;
  129. AppRegistryFileButton: TButton;
  130. AppRegistrySettingsLabel: TNewStaticText;
  131. AppRegistryUninsDeleteKeyCheck: TCheckBox;
  132. AppRegistryUninsDeleteKeyIfEmptyCheck: TCheckBox;
  133. AppRegistryUninsDeleteValueCheck: TCheckBox;
  134. AppRegistryMinVerCheck: TCheckBox;
  135. AppRegistryMinVerEdit: TEdit;
  136. AppRegistryMinVerDocBitBtn: TBitmapButton;
  137. WelcomeImageDark: TBitmapImage;
  138. InnerImageDark: TBitmapImage;
  139. AppFilesAddDownloadButton: TButton;
  140. WizardStylePage: TNewNotebookPage;
  141. WizardStyleLabel: TNewStaticText;
  142. WizardStyleMainComboBox: TComboBox;
  143. WizardStyleDarkComboBox: TComboBox;
  144. WizardStyleSubStyleComboBox: TComboBox;
  145. WizardStyleImageCollection: TImageCollection;
  146. WizardStyleImage: TBitmapButton;
  147. WizardStyleImage2: TBitmapImage;
  148. WizardStyleImageTimer: TTimer;
  149. procedure FormCreate(Sender: TObject);
  150. procedure FormShow(Sender: TObject);
  151. procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  152. procedure FormDestroy(Sender: TObject);
  153. procedure NextButtonClick(Sender: TObject);
  154. procedure BackButtonClick(Sender: TObject);
  155. procedure FileButtonClick(Sender: TObject);
  156. procedure AppRootDirComboBoxChange(Sender: TObject);
  157. procedure NotCreateAppDirCheckClick(Sender: TObject);
  158. procedure AppExeButtonClick(Sender: TObject);
  159. procedure NotDisableProgramGroupPageCheckClick(Sender: TObject);
  160. procedure PasswordEditChange(Sender: TObject);
  161. procedure OutputDirButtonClick(Sender: TObject);
  162. procedure AllLanguagesButtonClick(Sender: TObject);
  163. procedure NoLanguagesButtonClick(Sender: TObject);
  164. procedure NoAppExeCheckClick(Sender: TObject);
  165. procedure UseAutoProgramsCheckClick(Sender: TObject);
  166. procedure PrivilegesRequiredOverridesAllowedDialogCheckboxClick(Sender: TObject);
  167. procedure CreateAssocCheckClick(Sender: TObject);
  168. procedure WizardStyleComboBoxChange(Sender: TObject);
  169. procedure WizardStyleImageTimerTimer(Sender: TObject);
  170. procedure WizardStyleImageClick(Sender: TObject);
  171. private
  172. FCurPage: TWizardPage;
  173. FWizardName: String;
  174. FFilesHelper: TWizardFormFilesHelper;
  175. FRegistryHelper: TWizardFormRegistryHelper;
  176. FLanguages: TStringList;
  177. FResult: TWizardFormResult;
  178. FResultScript: String;
  179. function FixLabel(const S: String): String;
  180. procedure SetWizardName(const WizardName: String);
  181. procedure CurPageChanged;
  182. function SkipCurPage: Boolean;
  183. procedure UpdateAppExeControls;
  184. procedure UpdateAppAssocControls;
  185. procedure UpdateAppIconsControls;
  186. procedure UpdateWizardStyleImages;
  187. procedure WizardStyleImagePreviewKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  188. procedure WizardStyleImagePreviewImageClick(Sender: TObject);
  189. function GetWizardStyle: String;
  190. procedure GenerateScript;
  191. public
  192. property WizardName: String write SetWizardName;
  193. property Result: TWizardFormResult read FResult;
  194. property ResultScript: String read FResultScript;
  195. end;
  196. implementation
  197. {$R *.DFM}
  198. uses
  199. SysUtils, ShlObj, ActiveX, UITypes,
  200. PathFunc, BrowseFunc,
  201. Shared.CommonFunc.Vcl, Shared.CommonFunc, Shared.FileClass, Shared.LicenseFunc,
  202. IDE.HelperFunc, IDE.Messages, IDE.Wizard.WizardFileForm;
  203. type
  204. TConstant = record
  205. Constant, Description: String;
  206. end;
  207. const
  208. NotebookPages: array[TWizardPage, 0..1] of Integer =
  209. ((0, -1), (1, 0), (1, 1), (1, 2),
  210. (1, 3), (1, 4), (1, 5), (1, 6),
  211. (1, 7), (1, 8), (1, 9), (1, 10), (1, 11), (2, -1));
  212. PageCaptions: array[TWizardPage] of String =
  213. (SWizardWelcome, SWizardAppInfo, SWizardAppDir, SWizardAppFiles, SWizardAppAssoc,
  214. SWizardAppIcons, SWizardAppDocs, SWizardPrivilegesRequired, SWizardAppRegistry,
  215. SWizardLanguages, SWizardCompiler, SWizardWizardStyle, SWizardISPP, SWizardFinished);
  216. PageDescriptions: array[TWizardPage] of String =
  217. ('', SWizardAppInfo2, SWizardAppDir2, SWizardAppFiles2, SWizardAppAssoc2,
  218. SWizardAppIcons2, SWizardAppDocs2, SWizardPrivilegesRequired2, SWizardAppRegistry2,
  219. SWizardLanguages2, SWizardCompiler2, SWizardWizardStyle2, SWizardISPP2, '');
  220. RequiredLabelVisibles: array[TWizardPage] of Boolean =
  221. (False, True, True, True, True, True, False, True, False, True, False, False, False, False);
  222. AppRootDirs: array[0..0] of TConstant =
  223. (
  224. ( Constant: '{autopf}'; Description: 'Program Files folder')
  225. );
  226. LanguagesDefaultIsl = 'Default.isl';
  227. LanguagesDefaultIslDescription = 'English';
  228. EnabledColors: array[Boolean] of TColor = (clBtnFace, clWindow);
  229. function EscapeAmpersands(const S: String): String;
  230. begin
  231. Result := S;
  232. StringChangeEx(Result, '&', '&&', True);
  233. end;
  234. function TWizardForm.FixLabel(const S: String): String;
  235. begin
  236. Result := S;
  237. {don't localize these}
  238. StringChange(Result, '[name]', FWizardName);
  239. end;
  240. procedure TWizardForm.SetWizardName(const WizardName: String);
  241. begin
  242. FWizardName := WizardName;
  243. end;
  244. { --- }
  245. procedure TWizardForm.FormCreate(Sender: TObject);
  246. procedure AddLanguages(const Extension: String);
  247. var
  248. SearchRec: TSearchRec;
  249. begin
  250. if FindFirst(PathExtractPath(NewParamStr(0)) + 'Languages\*.' + Extension, faAnyFile, SearchRec) = 0 then begin
  251. repeat
  252. FLanguages.Add(SearchRec.Name);
  253. until FindNext(SearchRec) <> 0;
  254. FindClose(SearchRec);
  255. end;
  256. end;
  257. procedure MakeBold(const Ctl: TNewStaticText);
  258. begin
  259. Ctl.Font.Style := [fsBold];
  260. end;
  261. function SpaceLanguageName(const LanguageName: String): String;
  262. var
  263. I: Integer;
  264. begin
  265. Result := '';
  266. for I := 1 to Length(LanguageName) do begin
  267. if (I <> 1) and CharInSet(LanguageName[I], ['A'..'Z']) then
  268. Result := Result + ' ';
  269. Result := Result + LanguageName[I];
  270. end;
  271. end;
  272. var
  273. I: Integer;
  274. begin
  275. FResult := wrNone;
  276. FWizardName := SWizardDefaultName;
  277. FFilesHelper := TWizardFormFilesHelper.Create(Self,
  278. NotCreateAppDirCheck, AppFilesListBox, AppFilesAddButton, AppFilesAddDirButton,
  279. AppFilesAddDownloadButton, AppFilesEditButton, AppFilesRemoveButton);
  280. FRegistryHelper := TWizardFormRegistryHelper.Create(Self, AppRegistryFileEdit,
  281. AppRegistryFileButton, AppRegistryUninsDeleteKeyCheck,
  282. AppRegistryUninsDeleteKeyIfEmptyCheck, AppRegistryUninsDeleteValueCheck,
  283. AppRegistryMinVerCheck, AppRegistryMinVerEdit, AppRegistryMinVerDocBitBtn);
  284. FLanguages := TStringList.Create;
  285. FLanguages.Sorted := True;
  286. FLanguages.Duplicates := dupIgnore; { Some systems also return .islu files when searching for *.isl }
  287. AddLanguages('isl');
  288. AddLanguages('islu');
  289. FLanguages.Sorted := False;
  290. FLanguages.Insert(0, LanguagesDefaultIsl);
  291. InitFormFont(Self);
  292. if not InitFormTheme(Self) then
  293. OuterNotebook.Color := InitFormThemeGetBkColor(True);
  294. if FontExists('Segoe UI') then begin
  295. WelcomeLabel1.Font.Name := 'Segoe UI';
  296. WelcomeLabel1.Font.Size := 14;
  297. end;
  298. MakeBold(PageNameLabel);
  299. MakeBold(RequiredLabel1);
  300. MakeBold(AppNameLabel);
  301. MakeBold(AppVersionLabel);
  302. MakeBold(AppRootDirLabel);
  303. MakeBold(AppDirNameLabel);
  304. MakeBold(AppExeLabel);
  305. MakeBold(AppAssocNameLabel);
  306. MakeBold(AppAssocExtLabel);
  307. MakeBold(AppGroupNameLabel);
  308. MakeBold(PrivilegesRequiredLabel);
  309. MakeBold(LanguagesLabel);
  310. if InitFormThemeIsDark then begin
  311. WelcomeImage.Bitmap := WelcomeImageDark.Bitmap;
  312. InnerImage.Bitmap := InnerImageDark.Bitmap;
  313. end;
  314. FinishedImage.Bitmap := WelcomeImage.Bitmap;
  315. RequiredLabel2.Left := RequiredLabel1.Left + RequiredLabel1.Width;
  316. { See Setup.WizardForm }
  317. if IsCustomStyleActive then
  318. BackButton.Left := BackButton.Left - 2;
  319. { AppInfo }
  320. AppNameEdit.Text := 'My Program';
  321. AppVersionEdit.Text := '1.5';
  322. AppPublisherEdit.Text := 'My Company, Inc.';
  323. AppURLEdit.Text := 'https://www.example.com/';
  324. { AppDir }
  325. for I := Low(AppRootDirs) to High(AppRootDirs) do
  326. AppRootDirComboBox.Items.Add(AppRootDirs[I].Description);
  327. AppRootDirComboBox.Items.Add('(Custom)');
  328. AppRootDirComboBox.ItemIndex := 0;
  329. AppRootDirEdit.Enabled := False;
  330. AppRootDirEdit.Color := clBtnFace;
  331. NotDisableDirPageCheck.Checked := True;
  332. { AppFiles }
  333. AppExeEdit.Text := PathExtractPath(NewParamStr(0)) + 'Examples\MyProg-x64.exe';
  334. AppExeRunCheck.Checked := True;
  335. { AppAssoc }
  336. CreateAssocCheck.Checked := True;
  337. AppAssocExtEdit.Text := '.myp';
  338. { AppIcons }
  339. UseAutoProgramsCheck.Checked := True;
  340. NotDisableProgramGroupPageCheck.Checked := True;
  341. DesktopIconCheck.Checked := True;
  342. { PrivilegesRequired }
  343. PrivilegesRequiredAdminRadioButton.Checked := True;
  344. { Languages }
  345. for I := 0 to FLanguages.Count-1 do begin
  346. if FLanguages[I] <> LanguagesDefaultIsl then
  347. LanguagesList.AddCheckBox(SpaceLanguageName(PathChangeExt(FLanguages[I], '')), '', 0, False, True, False, True, TObject(I))
  348. else
  349. LanguagesList.AddCheckBox(LanguagesDefaultIslDescription, '', 0, True, True, False, True, TObject(I));
  350. end;
  351. { Compiler }
  352. OutputBaseFileNameEdit.Text := 'mysetup';
  353. EncryptionCheck.Checked := True;
  354. EncryptionCheck.Enabled := False;
  355. { ISPP }
  356. ISPPLabel.Caption := FixLabel(SWizardISPPLabel);
  357. ISPPCheck.Caption := SWizardISPPCheck;
  358. ISPPCheck.Checked := ISPPInstalled;
  359. FCurPage := Low(TWizardPage);
  360. CurPageChanged;
  361. end;
  362. procedure TWizardForm.FormShow(Sender: TObject);
  363. begin
  364. Caption := FWizardName;
  365. WelcomeLabel1.Caption := FixLabel(WelcomeLabel1.Caption);
  366. FinishedLabel.Caption := FixLabel(FinishedLabel.Caption);
  367. end;
  368. procedure TWizardForm.FormCloseQuery(Sender: TObject;
  369. var CanClose: Boolean);
  370. begin
  371. if ModalResult = mrCancel then
  372. CanClose := MsgBox(FixLabel(SWizardCancelMessage), FWizardName, mbConfirmation, MB_YESNO) = idYes;
  373. end;
  374. procedure TWizardForm.FormDestroy(Sender: TObject);
  375. begin
  376. FLanguages.Free;
  377. FRegistryHelper.Free;
  378. FFilesHelper.Free;
  379. end;
  380. { --- }
  381. procedure TWizardForm.CurPageChanged;
  382. { Call this whenever the current page is changed }
  383. begin
  384. OuterNotebook.ActivePage := OuterNotebook.Pages[NotebookPages[FCurPage, 0]];
  385. if NotebookPages[FCurPage, 1] <> -1 then
  386. InnerNotebook.ActivePage := InnerNotebook.Pages[NotebookPages[FCurPage, 1]];
  387. { Set button visibility and captions }
  388. BackButton.Visible := not (FCurPage = wpWelcome);
  389. if FCurPage = wpFinished then
  390. NextButton.Caption := SWizardFinishButton
  391. else
  392. NextButton.Caption := SWizardNextButton;
  393. RequiredLabel1.Visible := RequiredLabelVisibles[FCurPage];
  394. RequiredLabel2.Visible := RequiredLabel1.Visible;
  395. { Set the Caption to match the current page's title }
  396. PageNameLabel.Caption := PageCaptions[FCurPage];
  397. PageDescriptionLabel.Caption := PageDescriptions[FCurPage];
  398. { Adjust focus }
  399. case FCurPage of
  400. wpAppInfo: ActiveControl := AppNameEdit;
  401. wpAppDir:
  402. begin
  403. if AppRootDirComboBox.Enabled then
  404. ActiveControl := AppRootDirComboBox
  405. else
  406. ActiveControl := NotCreateAppDirCheck;
  407. end;
  408. wpAppFiles:
  409. begin
  410. if AppExeEdit.Enabled then
  411. ActiveControl := AppExeEdit
  412. else
  413. ActiveControl := AppFilesListBox;
  414. end;
  415. wpAppAssoc: ActiveControl := CreateAssocCheck;
  416. wpAppIcons:
  417. begin
  418. if UseAutoProgramsCheck.Enabled then
  419. ActiveControl := UseAutoProgramsCheck
  420. else
  421. ActiveControl := AppGroupNameEdit;
  422. end;
  423. wpAppDocs: ActiveControl := AppLicenseFileEdit;
  424. wpPrivilegesRequired:
  425. begin
  426. if PrivilegesRequiredAdminRadioButton.Checked then
  427. ActiveControl := PrivilegesRequiredAdminRadioButton
  428. else
  429. ActiveControl := PrivilegesRequiredLowestRadioButton;
  430. end;
  431. wpAppRegistry: ActiveControl := AppRegistryFileEdit;
  432. wpLanguages: ActiveControl := LanguagesList;
  433. wpCompiler: ActiveControl := OutputDirEdit;
  434. wpWizardStyle:
  435. begin
  436. ActiveControl := WizardStyleMainComboBox;
  437. UpdateWizardStyleImages;
  438. end;
  439. wpISPP: ActiveControl := ISPPCheck;
  440. end;
  441. end;
  442. function TWizardForm.SkipCurPage: Boolean;
  443. begin
  444. if ((FCurPage = wpAppAssoc) and not CreateAssocCheck.Enabled) or
  445. ((FCurPage = wpAppIcons) and NotCreateAppDirCheck.Checked) or
  446. ((FCurPage = wpLanguages) and not (FLanguages.Count > 1)) or
  447. ((FCurPage = wpISPP) and not ISPPInstalled) or
  448. (not (FCurPage in [wpWelcome, wpFinished]) and EmptyCheck.Checked) then
  449. Result := True
  450. else
  451. Result := False;
  452. end;
  453. procedure TWizardForm.NextButtonClick(Sender: TObject);
  454. function CheckAppInfoPage: Boolean;
  455. begin
  456. Result := False;
  457. if AppNameEdit.Text = '' then begin
  458. MsgBox(SWizardAppNameError, '', mbError, MB_OK);
  459. ActiveControl := AppNameEdit;
  460. end else if AppVersionEdit.Text = '' then begin
  461. MsgBox(SWizardAppVersionError, '', mbError, MB_OK);
  462. ActiveControl := AppVersionEdit;
  463. end else
  464. Result := True;
  465. end;
  466. function CheckAppDirPage: Boolean;
  467. begin
  468. Result := False;
  469. if not NotCreateAppDirCheck.Checked and
  470. (AppRootDirComboBox.ItemIndex = AppRootDirComboBox.Items.Count-1) and
  471. (AppRootDirEdit.Text = '') then begin
  472. MsgBox(SWizardAppRootDirError, '', mbError, MB_OK);
  473. ActiveControl := AppRootDirEdit;
  474. end else if not NotCreateAppDirCheck.Checked and (AppDirNameEdit.Text = '') then begin
  475. MsgBox(SWizardAppDirNameError, '', mbError, MB_OK);
  476. ActiveControl := AppDirNameEdit;
  477. end else
  478. Result := True;
  479. end;
  480. function CheckAppFilesPage: Boolean;
  481. begin
  482. Result := False;
  483. if AppExeEdit.Enabled and (AppExeEdit.Text = '') then begin
  484. MsgBox(SWizardAppExeError, '', mbError, MB_OK);
  485. ActiveControl := AppExeEdit;
  486. end else
  487. Result := True;
  488. end;
  489. function CheckAppIconsPage: Boolean;
  490. begin
  491. Result := False;
  492. if AppGroupNameEdit.Text = '' then begin
  493. MsgBox(SWizardAppGroupNameError, '', mbError, MB_OK);
  494. ActiveControl := AppGroupNameEdit;
  495. end else
  496. Result := True;
  497. end;
  498. function CheckLanguagesPage: Boolean;
  499. var
  500. I: Integer;
  501. begin
  502. Result := False;
  503. for I := 0 to LanguagesList.Items.Count-1 do begin
  504. if LanguagesList.Checked[I] then begin
  505. Result := True;
  506. Exit;
  507. end;
  508. end;
  509. MsgBox(SWizardLanguagesSelError, '', mbError, MB_OK);
  510. ActiveControl := LanguagesList;
  511. end;
  512. begin
  513. case FCurPage of
  514. wpAppInfo: if not CheckAppInfoPage then Exit;
  515. wpAppDir: if not CheckAppDirPage then Exit;
  516. wpAppFiles: if not CheckAppFilesPage then Exit;
  517. wpAppIcons: if not CheckAppIconsPage then Exit;
  518. wpLanguages: if not CheckLanguagesPage then Exit;
  519. end;
  520. repeat
  521. if FCurPage = wpAppAssoc then begin
  522. if (AppAssocExtEdit.Text <> '') and (AppAssocExtEdit.Text[1] <> '.') then
  523. AppAssocExtEdit.Text := '.' + AppAssocExtEdit.Text;
  524. end else if FCurPage = wpPrivilegesRequired then begin
  525. if not PrivilegesRequiredOverridesAllowedCommandLineCheckbox.Checked then begin
  526. if PrivilegesRequiredAdminRadioButton.Checked then
  527. FRegistryHelper.PrivilegesRequired := prAdmin
  528. else
  529. FRegistryHelper.PrivilegesRequired := prLowest
  530. end else
  531. FRegistryHelper.PrivilegesRequired := prDynamic;
  532. end else if FCurPage = wpFinished then begin
  533. GenerateScript;
  534. ModalResult := mrOk;
  535. Exit;
  536. end;
  537. Inc(FCurPage);
  538. { Even if we're skipping a page, we should still update it }
  539. case FCurPage of
  540. wpAppDir: if AppDirNameEdit.Text = '' then AppDirNameEdit.Text := AppNameEdit.Text;
  541. wpAppAssoc: if AppAssocNameEdit.Text = '' then AppAssocNameEdit.Text := AppNameEdit.Text + ' File';
  542. wpAppIcons: if AppGroupNameEdit.Text = '' then AppGroupNameEdit.Text := AppNameEdit.Text;
  543. end;
  544. until not SkipCurPage;
  545. CurPageChanged;
  546. end;
  547. procedure TWizardForm.BackButtonClick(Sender: TObject);
  548. begin
  549. if FCurPage = Low(TWizardPage) then Exit;
  550. { Go to the previous page }
  551. Dec(FCurPage);
  552. while SkipCurPage do
  553. Dec(FCurPage);
  554. CurPageChanged;
  555. end;
  556. {---}
  557. procedure TWizardForm.UpdateAppExeControls;
  558. var
  559. Enabled: Boolean;
  560. begin
  561. Enabled := not NotCreateAppDirCheck.Checked;
  562. NoAppExeCheck.Enabled := Enabled;
  563. Enabled := Enabled and not NoAppExeCheck.Checked;
  564. AppExeLabel.Enabled := Enabled;
  565. AppExeEdit.Enabled := Enabled;
  566. AppExeEdit.Color := EnabledColors[Enabled];
  567. AppExeButton.Enabled := Enabled;
  568. AppExeRunCheck.Enabled := Enabled;
  569. AppExeIconsLabel.Enabled := Enabled;
  570. DesktopIconCheck.Enabled := Enabled;
  571. if Enabled then
  572. AppExeLabel.Font.Style := AppExeLabel.Font.Style + [fsBold]
  573. else
  574. AppExeLabel.Font.Style := AppExeLabel.Font.Style - [fsBold];
  575. end;
  576. procedure TWizardForm.UpdateAppAssocControls;
  577. var
  578. Enabled: Boolean;
  579. begin
  580. Enabled := not NoAppExeCheck.Checked;
  581. CreateAssocCheck.Enabled := Enabled;
  582. Enabled := Enabled and CreateAssocCheck.Checked;
  583. AppAssocNameLabel.Enabled := Enabled;
  584. AppAssocNameEdit.Enabled := Enabled;
  585. AppAssocExtLabel.Enabled := Enabled;
  586. AppAssocExtEdit.Enabled := Enabled;
  587. if Enabled then begin
  588. AppAssocNameLabel.Font.Style := AppAssocNameLabel.Font.Style + [fsBold];
  589. AppAssocExtLabel.Font.Style := AppAssocExtLabel.Font.Style + [fsBold];
  590. end else begin
  591. AppAssocNameLabel.Font.Style := AppAssocNameLabel.Font.Style - [fsBold];
  592. AppAssocExtLabel.Font.Style := AppAssocExtLabel.Font.Style - [fsBold];
  593. end;
  594. end;
  595. procedure TWizardForm.UpdateAppIconsControls;
  596. var
  597. Enabled: Boolean;
  598. begin
  599. UseAutoProgramsCheck.Enabled := NoAppExeCheck.Enabled and not NoAppExeCheck.Checked;
  600. Enabled := not (UseAutoProgramsCheck.Enabled and UseAutoProgramsCheck.Checked);
  601. AppGroupNameLabel.Enabled := Enabled;
  602. AppGroupNameEdit.Enabled := Enabled;
  603. AppGroupNameEdit.Color := EnabledColors[Enabled];
  604. NotDisableProgramGroupPageCheck.Enabled := Enabled;
  605. AllowNoIconsCheck.Enabled := Enabled and NotDisableProgramGroupPageCheck.Checked;
  606. CreateURLIconCheck.Enabled := Enabled and (AppURLEdit.Text <> '');
  607. CreateUninstallIconCheck.Enabled := Enabled;
  608. if Enabled then
  609. AppGroupNameLabel.Font.Style := AppGroupNameLabel.Font.Style + [fsBold]
  610. else
  611. AppGroupNameLabel.Font.Style := AppGroupNameLabel.Font.Style - [fsBold];
  612. end;
  613. procedure TWizardForm.UpdateWizardStyleImages;
  614. procedure UpdateWizardStyleImage(const WizardStylePngImage: TPngImage; ImageName: String);
  615. begin
  616. ImageName := ImageName.Replace('dark windows11', 'dark');
  617. const ImageIndex = WizardStyleImageCollection.GetIndexByName(ImageName);
  618. if ImageIndex = -1 then
  619. raise Exception.CreateFmt('Image name ''%s'' not found', [ImageName]);
  620. WizardStylePngImage.Assign(WizardStyleImageCollection.GetSourceImage(ImageIndex, 0, 0));
  621. end;
  622. begin
  623. var WizardStyle := GetWizardStyle;
  624. const Dynamic = WizardStyle.Contains('dynamic');
  625. if Dynamic then begin
  626. WizardStyle := WizardStyle.Replace('dynamic', 'dark');
  627. UpdateWizardStyleImage(WizardStyleImage2.PngImage, WizardStyle); { This image is always invisible }
  628. WizardStyle := WizardStyle.Replace(' dark', '');
  629. end;
  630. UpdateWizardStyleImage(WizardStyleImage.PngImage, WizardStyle);
  631. { To keep things simple this timer is always running but here we do reset it so the new images
  632. will never be swapped too quickly }
  633. WizardStyleImageTimer.Enabled := False;
  634. WizardStyleImageTimer.Enabled := True;
  635. end;
  636. {---}
  637. procedure TWizardForm.AppRootDirComboBoxChange(Sender: TObject);
  638. begin
  639. if AppRootDirComboBox.ItemIndex = AppRootDirComboBox.Items.Count-1 then begin
  640. AppRootDirEdit.Enabled := True;
  641. AppRootDirEdit.Color := clWindow;
  642. ActiveControl := AppRootDirEdit;
  643. end else begin
  644. AppRootDirEdit.Enabled := False;
  645. AppRootDirEdit.Color := clBtnFace;
  646. end;
  647. end;
  648. procedure TWizardForm.NotCreateAppDirCheckClick(Sender: TObject);
  649. var
  650. Enabled: Boolean;
  651. begin
  652. Enabled := not NotCreateAppDirCheck.Checked;
  653. { AppDir }
  654. AppRootDirLabel.Enabled := Enabled;
  655. AppRootDirComboBox.Enabled := Enabled;
  656. AppRootDirComboBox.Color := EnabledColors[Enabled];
  657. AppRootDirEdit.Enabled := Enabled and (AppRootDirComboBox.ItemIndex = AppRootDirComboBox.Items.Count-1);
  658. AppRootDirEdit.Color := EnabledColors[AppRootDirEdit.Enabled];
  659. AppDirNameLabel.Enabled := Enabled;
  660. AppDirNameEdit.Enabled := Enabled;
  661. AppDirNameEdit.Color := EnabledColors[Enabled];
  662. NotDisableDirPageCheck.Enabled := Enabled;
  663. if Enabled then begin
  664. AppRootDirLabel.Font.Style := AppRootDirLabel.Font.Style + [fsBold];
  665. AppDirNameLabel.Font.Style := AppRootDirLabel.Font.Style + [fsBold];
  666. end else begin
  667. AppRootDirLabel.Font.Style := AppRootDirLabel.Font.Style - [fsBold];
  668. AppDirNameLabel.Font.Style := AppRootDirLabel.Font.Style - [fsBold];
  669. end;
  670. { AppFiles }
  671. UpdateAppExeControls;
  672. end;
  673. procedure TWizardForm.AppExeButtonClick(Sender: TObject);
  674. var
  675. FileName: String;
  676. begin
  677. FileName := AppExeEdit.Text;
  678. if NewGetOpenFileName('', FileName, PathExtractPath(FileName), SWizardAppExeFilter, SWizardAppExeDefaultExt, Handle) then
  679. AppExeEdit.Text := FileName;
  680. end;
  681. procedure TWizardForm.NoAppExeCheckClick(Sender: TObject);
  682. begin
  683. UpdateAppExeControls;
  684. UpdateAppAssocControls;
  685. UpdateAppIconsControls;
  686. end;
  687. procedure TWizardForm.CreateAssocCheckClick(Sender: TObject);
  688. begin
  689. UpdateAppAssocControls;
  690. end;
  691. procedure TWizardForm.UseAutoProgramsCheckClick(Sender: TObject);
  692. begin
  693. UpdateAppIconsControls;
  694. end;
  695. procedure TWizardForm.NotDisableProgramGroupPageCheckClick(
  696. Sender: TObject);
  697. begin
  698. UpdateAppIconsControls;
  699. end;
  700. procedure TWizardForm.FileButtonClick(Sender: TObject);
  701. var
  702. Edit: TEdit;
  703. Filter, DefaultExt, FileName: String;
  704. begin
  705. if Sender = AppLicenseFileButton then
  706. Edit := AppLicenseFileEdit
  707. else if Sender = AppInfoBeforeFileButton then
  708. Edit := AppInfoBeforeFileEdit
  709. else if Sender = AppInfoAfterFileButton then
  710. Edit := AppInfoAfterFileEdit
  711. else
  712. Edit := SetupIconFileEdit;
  713. if Sender <> SetupIconFileButton then begin
  714. Filter := SWizardAppDocsFilter;
  715. DefaultExt := SWizardAppDocsDefaultExt;
  716. end else begin
  717. Filter := SWizardCompilerSetupIconFileFilter;
  718. DefaultExt := SWizardCompilerSetupIconFileDefaultExt;
  719. end;
  720. FileName := Edit.Text;
  721. if NewGetOpenFileName('', FileName, PathExtractPath(FileName), Filter, DefaultExt, Handle) then
  722. Edit.Text := FileName;
  723. end;
  724. procedure TWizardForm.OutputDirButtonClick(Sender: TObject);
  725. var
  726. Path: String;
  727. begin
  728. Path := OutputDirEdit.Text;
  729. if PathDrivePartLength(Path) = 0 then
  730. Path := ''; { don't pass in a relative path to BrowseForFolder }
  731. if BrowseForFolder(SWizardCompilerOutputDir, Path, Handle, True) then
  732. OutputDirEdit.Text := Path;
  733. end;
  734. procedure TWizardForm.PasswordEditChange(Sender: TObject);
  735. begin
  736. EncryptionCheck.Enabled := PasswordEdit.Text <> '';
  737. end;
  738. procedure TWizardForm.AllLanguagesButtonClick(Sender: TObject);
  739. var
  740. I: Integer;
  741. begin
  742. for I := 0 to LanguagesList.Items.Count-1 do
  743. LanguagesList.Checked[I] := True;
  744. end;
  745. procedure TWizardForm.NoLanguagesButtonClick(Sender: TObject);
  746. var
  747. I: Integer;
  748. begin
  749. for I := 0 to LanguagesList.Items.Count-1 do
  750. LanguagesList.Checked[I] := False;
  751. end;
  752. procedure TWizardForm.PrivilegesRequiredOverridesAllowedDialogCheckboxClick(
  753. Sender: TObject);
  754. begin
  755. PrivilegesRequiredOverridesAllowedCommandLineCheckbox.Enabled := not PrivilegesRequiredOverridesAllowedDialogCheckbox.Checked;
  756. if PrivilegesRequiredOverridesAllowedDialogCheckbox.Checked then
  757. PrivilegesRequiredOverridesAllowedCommandLineCheckbox.Checked := True;
  758. end;
  759. procedure TWizardForm.WizardStyleComboBoxChange(Sender: TObject);
  760. begin
  761. if (WizardStyleDarkComboBox.Text <> 'light') and ((WizardStyleSubStyleComboBox.Text = 'slate') or (WizardStyleSubStyleComboBox.Text = 'zircon')) then
  762. WizardStyleDarkComboBox.ItemIndex := WizardStyleDarkComboBox.Items.IndexOf('light');
  763. UpdateWizardStyleImages;
  764. end;
  765. procedure TWizardForm.WizardStyleImagePreviewKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  766. begin
  767. if Key = VK_ESCAPE then
  768. (Sender as TForm).ModalResult := mrCancel;
  769. end;
  770. procedure TWizardForm.WizardStyleImagePreviewImageClick(Sender: TObject);
  771. begin
  772. const F = GetParentForm(Sender as TControl);
  773. if F <> nil then
  774. F.ModalResult := mrOk;
  775. end;
  776. procedure TWizardForm.WizardStyleImageClick(Sender: TObject);
  777. begin
  778. const PreviewForm = TForm.CreateNew(nil);
  779. try
  780. PreviewForm.AutoSize := True;
  781. PreviewForm.BorderStyle := bsNone;
  782. PreviewForm.BorderIcons := [];
  783. PreviewForm.Color := clWindow;
  784. PreviewForm.KeyPreview := True;
  785. PreviewForm.OnKeyDown := WizardStyleImagePreviewKeyDown;
  786. PreviewForm.Position := poDesigned;
  787. const R = BoundsRect;
  788. PreviewForm.Left := R.Left + MulDiv(32, CurrentPPI, 96);
  789. PreviewForm.Top := R.Top + MulDiv(32, CurrentPPI, 96);
  790. const PreviewImage = TBitmapImage.Create(PreviewForm);
  791. PreviewImage.AutoSize := True;
  792. PreviewImage.BackColor := clNone;
  793. PreviewImage.Bitmap.Assign(WizardStyleImage.Bitmap);
  794. PreviewImage.Cursor := crHandPoint;
  795. PreviewImage.OnClick := WizardStyleImagePreviewImageClick;
  796. PreviewImage.Parent := PreviewForm;
  797. PreviewForm.ShowModal;
  798. finally
  799. PreviewForm.Free;
  800. end;
  801. end;
  802. procedure TWizardForm.WizardStyleImageTimerTimer(Sender: TObject);
  803. begin
  804. if (FCurPage = wpWizardStyle) and (WizardStyleDarkComboBox.Text = 'dynamic') then begin
  805. const SaveBitmap = TBitmap.Create;
  806. try
  807. SaveBitmap.Assign(WizardStyleImage.Bitmap);
  808. WizardStyleImage.Bitmap.Assign(WizardStyleImage2.Bitmap);
  809. WizardStyleImage2.Bitmap.Assign(SaveBitmap);
  810. finally
  811. SaveBitmap.Free;
  812. end;
  813. end;
  814. end;
  815. { --- }
  816. function TWizardForm.GetWizardStyle: String;
  817. begin
  818. Result := WizardStyleMainComboBox.Text;
  819. if WizardStyleDarkComboBox.ItemIndex <> 0 then
  820. Result := Result + ' ' + WizardStyleDarkComboBox.Text;
  821. if WizardStyleSubStyleComboBox.ItemIndex <> 0 then
  822. Result := Result + ' ' + WizardStyleSubStyleComboBox.Text;
  823. end;
  824. procedure TWizardForm.GenerateScript;
  825. function Is64BitPEImage(const Filename: String): Boolean;
  826. { Returns True if the specified file is a non-32-bit PE image, False
  827. otherwise. }
  828. var
  829. F: TFile;
  830. DosHeader: packed record
  831. Sig: array[0..1] of AnsiChar;
  832. Other: array[0..57] of Byte;
  833. PEHeaderOffset: LongWord;
  834. end;
  835. PESigAndHeader: packed record
  836. Sig: DWORD;
  837. Header: TImageFileHeader;
  838. OptHeaderMagic: Word;
  839. end;
  840. begin
  841. Result := False;
  842. F := TFile.Create(Filename, fdOpenExisting, faRead, fsRead);
  843. try
  844. if F.Read(DosHeader, SizeOf(DosHeader)) = SizeOf(DosHeader) then begin
  845. if (DosHeader.Sig[0] = 'M') and (DosHeader.Sig[1] = 'Z') and
  846. (DosHeader.PEHeaderOffset <> 0) then begin
  847. F.Seek(DosHeader.PEHeaderOffset);
  848. if F.Read(PESigAndHeader, SizeOf(PESigAndHeader)) = SizeOf(PESigAndHeader) then begin
  849. if (PESigAndHeader.Sig = IMAGE_NT_SIGNATURE) and
  850. (PESigAndHeader.OptHeaderMagic <> IMAGE_NT_OPTIONAL_HDR32_MAGIC) then
  851. Result := True;
  852. end;
  853. end;
  854. end;
  855. finally
  856. F.Free;
  857. end;
  858. end;
  859. var
  860. Script, ISPP, Setup, Languages, Tasks, Files, Registry, INI, Icons, Run, UninstallDelete: String;
  861. I: Integer;
  862. AppExeName, AppName, AppAmpEscapedName, AppAssocKey, LanguageName, LanguageMessagesFile: String;
  863. begin
  864. Script := '';
  865. AppExeName := PathExtractName(AppExeEdit.Text);
  866. AppName := AppNameEdit.Text;
  867. AppAmpEscapedName := EscapeAmpersands(AppName);
  868. if ISPPCheck.Checked then begin
  869. { Setup ISPP usage. Change the edits to reflect ISPP usage. A bit ugly but for now it works. }
  870. ISPP := '#define MyAppName "' + AppNameEdit.Text + '"' + SNewLine +
  871. '#define MyAppVersion "' + AppVersionEdit.Text + '"' + SNewLine;
  872. if AppDirNameEdit.Text = AppNameEdit.Text then
  873. AppDirNameEdit.Text := '{#MyAppName}';
  874. if AppGroupNameEdit.Text = AppNameEdit.Text then
  875. AppGroupNameEdit.Text := '{#MyAppName}';
  876. AppNameEdit.Text := '{#MyAppName}';
  877. AppAmpEscapedName := '{#StringChange(MyAppName, ''&'', ''&&'')}';
  878. AppVersionEdit.Text := '{#MyAppVersion}';
  879. if AppPublisherEdit.Text <> '' then begin
  880. ISPP := ISPP + '#define MyAppPublisher "' + AppPublisherEdit.Text + '"' + SNewLine;
  881. AppPublisherEdit.Text := '{#MyAppPublisher}';
  882. end;
  883. if AppURLEdit.Text <> '' then begin
  884. ISPP := ISPP + '#define MyAppURL "' + AppURLEdit.Text + '"' + SNewLine;
  885. AppURLEdit.Text := '{#MyAppURL}';
  886. end;
  887. { Special ones }
  888. if not NoAppExeCheck.Checked then begin
  889. ISPP := ISPP + '#define MyAppExeName "' + AppExeName + '"' + SNewLine;
  890. AppExeName := '{#MyAppExeName}';
  891. end;
  892. if CreateAssocCheck.Enabled and CreateAssocCheck.Checked then begin
  893. if Pos(AppName, AppAssocNameEdit.Text) = 1 then
  894. ISPP := ISPP + '#define MyAppAssocName MyAppName + "' + Copy(AppAssocNameEdit.Text, Length(AppName)+1, MaxInt) + '"' + SNewLine
  895. else
  896. ISPP := ISPP + '#define MyAppAssocName "' + AppAssocNameEdit.Text + '"' + SNewLine;
  897. AppAssocNameEdit.Text := '{#MyAppAssocName}';
  898. ISPP := ISPP + '#define MyAppAssocExt "' + AppAssocExtEdit.Text + '"' + SNewLine;
  899. AppAssocExtEdit.Text := '{#MyAppAssocExt}';
  900. ISPP := ISPP + '#define MyAppAssocKey StringChange(MyAppAssocName, " ", "") + MyAppAssocExt' + SNewLine;
  901. AppAssocKey := '{#MyAppAssocKey}';
  902. end;
  903. end else begin
  904. ISPP := '';
  905. AppAssocKey := StringReplace(AppAssocNameEdit.Text, ' ', '', [rfReplaceAll]) + AppAssocExtEdit.Text;
  906. end;
  907. Setup := '[Setup]' + SNewLine;
  908. Languages := '[Languages]' + SNewLine;
  909. Tasks := '[Tasks]' + SNewLine;
  910. Files := '[Files]' + SNewLine;
  911. Registry := '[Registry]' + SNewLine;
  912. INI := '[INI]' + SNewLine;
  913. Icons := '[Icons]' + SNewLine;
  914. Run := '[Run]' + SNewLine;
  915. UninstallDelete := '[UninstallDelete]' + SNewLine;
  916. if not EmptyCheck.Checked then begin
  917. Setup := Setup + (
  918. '; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.' + SNewLine +
  919. '; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)' + SNewLine);
  920. Setup := Setup + 'AppId={' + GenerateGuid + SNewLine;
  921. { AppInfo }
  922. Setup := Setup + 'AppName=' + AppNameEdit.Text + SNewLine;
  923. Setup := Setup + 'AppVersion=' + AppVersionEdit.Text + SNewLine;
  924. Setup := Setup + ';AppVerName=' + AppNameEdit.Text + ' ' + AppVersionEdit.Text + SNewLine;
  925. if AppPublisherEdit.Text <> '' then
  926. Setup := Setup + 'AppPublisher=' + AppPublisherEdit.Text + SNewLine;
  927. if AppURLEdit.Text <> '' then begin
  928. Setup := Setup + 'AppPublisherURL=' + AppURLEdit.Text + SNewLine;
  929. Setup := Setup + 'AppSupportURL=' + AppURLEdit.Text + SNewLine;
  930. Setup := Setup + 'AppUpdatesURL=' + AppURLEdit.Text + SNewLine;
  931. end;
  932. { AppDir }
  933. if not NotCreateAppDirCheck.Checked then begin
  934. if AppRootDirComboBox.ItemIndex = AppRootDirComboBox.Items.Count-1 then
  935. Setup := Setup + 'DefaultDirName=' + AddBackslash(AppRootDirEdit.Text) + AppDirNameEdit.Text + SNewLine
  936. else
  937. Setup := Setup + 'DefaultDirName=' + AddBackslash(AppRootDirs[AppRootDirComboBox.ItemIndex].Constant) + AppDirNameEdit.Text + SNewLine;
  938. if not NotDisableDirPageCheck.Checked then
  939. Setup := Setup + 'DisableDirPage=yes' + SNewLine;
  940. end else begin
  941. Setup := Setup + 'CreateAppDir=no' + SNewLine;
  942. end;
  943. { AppFiles }
  944. if not NotCreateAppDirCheck.Checked and not NoAppExeCheck.Checked then begin
  945. Files := Files + 'Source: "' + PathExtractPath(AppExeEdit.Text) + AppExeName + '"; DestDir: "{app}"; Flags: ignoreversion' + SNewLine;
  946. var AppExeIsReallyExe := SameText(PathExtractExt(AppExeEdit.Text), '.exe');
  947. if AppExeRunCheck.Checked then begin
  948. if AppExeIsReallyExe then
  949. Run := Run + 'Filename: "{app}\' + AppExeName + '"; Description: "{cm:LaunchProgram,' + AppAmpEscapedName + '}"; Flags: nowait postinstall skipifsilent' + SNewLine
  950. else
  951. Run := Run + 'Filename: "{app}\' + AppExeName + '"; Description: "{cm:LaunchProgram,' + AppAmpEscapedName + '}"; Flags: shellexec postinstall skipifsilent' + SNewLine;
  952. end;
  953. if AppExeIsReallyExe then
  954. Setup := Setup + 'UninstallDisplayIcon={app}\' + AppExeName + SNewLine;
  955. if Is64BitPEImage(AppExeEdit.Text) then begin
  956. Setup := Setup + '; "ArchitecturesAllowed=x64compatible" specifies that Setup cannot run' + SNewLine;
  957. Setup := Setup + '; on anything but x64 and Windows 11 on Arm.' + SNewLine;
  958. Setup := Setup + 'ArchitecturesAllowed=x64compatible' + SNewLine;
  959. Setup := Setup + '; "ArchitecturesInstallIn64BitMode=x64compatible" requests that the' + SNewLine;
  960. Setup := Setup + '; install be done in "64-bit mode" on x64 or Windows 11 on Arm,' + SNewLine;
  961. Setup := Setup + '; meaning it should use the native 64-bit Program Files directory and' + SNewLine;
  962. Setup := Setup + '; the 64-bit view of the registry.' + SNewLine;
  963. Setup := Setup + 'ArchitecturesInstallIn64BitMode=x64compatible' + SNewLine;
  964. end;
  965. end;
  966. var HasExtractArchive: Boolean;
  967. FFilesHelper.AddScript(Files, HasExtractArchive);
  968. if HasExtractArchive then begin
  969. Setup := Setup + 'ArchiveExtraction=full' + SNewLine;
  970. Setup := Setup + '; Use "ArchiveExtraction=enhanced" if all your archives are .7z files' + SNewLine;
  971. Setup := Setup + '; Use "ArchiveExtraction=enhanced/nopassword" if all your archives are not password-protected' + SNewLine;
  972. end;
  973. { AppAssocation }
  974. if CreateAssocCheck.Enabled and CreateAssocCheck.Checked then begin
  975. Setup := Setup + 'ChangesAssociations=yes' + SNewLine;
  976. Registry := Registry + 'Root: HKA; Subkey: "Software\Classes\' + AppAssocExtEdit.Text + '\OpenWithProgids"; ValueType: string; ValueName: "' + AppAssocKey + '"; ValueData: ""; Flags: uninsdeletevalue' + SNewLine;
  977. Registry := Registry + 'Root: HKA; Subkey: "Software\Classes\' + AppAssocKey + '"; ValueType: string; ValueName: ""; ValueData: "' + AppAssocNameEdit.Text + '"; Flags: uninsdeletekey' + SNewLine;
  978. Registry := Registry + 'Root: HKA; Subkey: "Software\Classes\' + AppAssocKey + '\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\' + AppExeName + ',0"' + SNewLine;
  979. Registry := Registry + 'Root: HKA; Subkey: "Software\Classes\' + AppAssocKey + '\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\' + AppExeName + '"" ""%1"""' + SNewLine;
  980. end;
  981. { AppGroup }
  982. if not NotCreateAppDirCheck.Checked then begin
  983. if UseAutoProgramsCheck.Enabled and UseAutoProgramsCheck.Checked then begin
  984. Setup := Setup + 'DisableProgramGroupPage=yes' + SNewLine;
  985. Icons := Icons + 'Name: "{autoprograms}\' + AppNameEdit.Text + '"; Filename: "{app}\' + AppExeName + '"' + SNewLine;
  986. end else begin
  987. Setup := Setup + 'DefaultGroupName=' + AppGroupNameEdit.Text + SNewLine;
  988. if not NoAppExeCheck.Checked then
  989. Icons := Icons + 'Name: "{group}\' + AppNameEdit.Text + '"; Filename: "{app}\' + AppExeName + '"' + SNewLine;
  990. if not NotDisableProgramGroupPageCheck.Checked then
  991. Setup := Setup + 'DisableProgramGroupPage=yes' + SNewLine;
  992. if AllowNoIconsCheck.Checked and NotDisableProgramGroupPageCheck.Checked then
  993. Setup := Setup + 'AllowNoIcons=yes' + SNewLine;
  994. if CreateURLIconCheck.Enabled and CreateURLIconCheck.Checked then
  995. Icons := Icons + 'Name: "{group}\{cm:ProgramOnTheWeb,' + AppNameEdit.Text + '}"; Filename: "' + AppURLEdit.Text + '"' + SNewLine;
  996. if CreateUninstallIconCheck.Checked then
  997. Icons := Icons + 'Name: "{group}\{cm:UninstallProgram,' + AppNameEdit.Text + '}"; Filename: "{uninstallexe}"' + SNewLine;
  998. end;
  999. if DesktopIconCheck.Enabled and DesktopIconCheck.Checked then begin
  1000. Tasks := Tasks + 'Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked' + SNewLine;
  1001. Icons := Icons + 'Name: "{autodesktop}\' + AppNameEdit.Text + '"; Filename: "{app}\' + AppExeName + '"; Tasks: desktopicon' + SNewLine;
  1002. end;
  1003. end;
  1004. { AppDocs }
  1005. if AppLicenseFileEdit.Text <> '' then
  1006. Setup := Setup + 'LicenseFile=' + AppLicenseFileEdit.Text + SNewLine;
  1007. if AppInfoBeforeFileEdit.Text <> '' then
  1008. Setup := Setup + 'InfoBeforeFile=' + AppInfoBeforeFileEdit.Text + SNewLine;
  1009. if AppInfoAfterFileEdit.Text <> '' then
  1010. Setup := Setup + 'InfoAfterFile=' + AppInfoAfterFileEdit.Text + SNewLine;
  1011. { PrivilegesRequired }
  1012. if PrivilegesRequiredAdminRadioButton.Checked then
  1013. Setup := Setup + '; Uncomment the following line to run in non administrative install mode (install for current user only).' + SNewLine + ';'
  1014. else
  1015. Setup := Setup + '; Remove the following line to run in administrative install mode (install for all users).' + SNewLine;
  1016. Setup := Setup + 'PrivilegesRequired=lowest' + SNewLine; { Note how previous made sure this is outputted as comment if needed. }
  1017. if PrivilegesRequiredOverridesAllowedDialogCheckbox.Checked then
  1018. Setup := Setup + 'PrivilegesRequiredOverridesAllowed=dialog' + SNewLine
  1019. else if PrivilegesRequiredOverridesAllowedCommandLineCheckbox.Checked then
  1020. Setup := Setup + 'PrivilegesRequiredOverridesAllowed=commandline' + SNewLine;
  1021. { AppRegistry }
  1022. FRegistryHelper.AddScript(Registry, False);
  1023. { Languages }
  1024. if FLanguages.Count > 1 then begin
  1025. for I := 0 to LanguagesList.Items.Count-1 do begin
  1026. if LanguagesList.Checked[I] then begin
  1027. LanguageMessagesFile := FLanguages[Integer(LanguagesList.ItemObject[I])];
  1028. if LanguageMessagesFile <> LanguagesDefaultIsl then begin
  1029. LanguageName := LanguagesList.Items[I];
  1030. LanguageMessagesFile := 'Languages\' + LanguageMessagesFile;
  1031. end else
  1032. LanguageName := LanguagesDefaultIslDescription;
  1033. StringChange(LanguageName, ' ', '');
  1034. LanguageName := LowerCase(LanguageName);
  1035. Languages := Languages + 'Name: "' + LanguageName + '"; MessagesFile: "compiler:' + LanguageMessagesFile + '"' + SNewLine;
  1036. end;
  1037. end;
  1038. end;
  1039. { Compiler }
  1040. if OutputDirEdit.Text <> '' then
  1041. Setup := Setup + 'OutputDir=' + OutputDirEdit.Text + SNewLine;
  1042. if OutputBaseFileNameEdit.Text <> '' then
  1043. Setup := Setup + 'OutputBaseFilename=' + OutputBaseFileNameEdit.Text + SNewLine;
  1044. if SetupIconFileEdit.Text <> '' then
  1045. Setup := Setup + 'SetupIconFile=' + SetupIconFileEdit.Text + SNewLine;
  1046. if PasswordEdit.Text <> '' then begin
  1047. Setup := Setup + 'Password=' + PasswordEdit.Text + SNewLine;
  1048. if EncryptionCheck.Checked then
  1049. Setup := Setup + 'Encryption=yes' + SNewLine;
  1050. end;
  1051. { Other }
  1052. Setup := Setup + 'SolidCompression=yes' + SNewLine;
  1053. Setup := Setup + 'WizardStyle=' + GetWizardStyle + SNewLine;
  1054. { Build script }
  1055. if ISPP <> '' then
  1056. Script := Script + ISPP + SNewLine;
  1057. Script := Script + Setup + SNewLine;
  1058. if Length(Languages) > Length('[Languages]')+2 then
  1059. Script := Script + Languages + SNewLine;
  1060. if Length(Tasks) > Length('[Tasks]')+2 then
  1061. Script := Script + Tasks + SNewLine;
  1062. if Length(Files) > Length('[Files]')+2 then
  1063. Script := Script + Files +
  1064. '; NOTE: Don''t use "Flags: ignoreversion" on any shared system files' +
  1065. SNewLine2;
  1066. if Length(Registry) > Length('[Registry]')+2 then
  1067. Script := Script + Registry + SNewLine;
  1068. if Length(INI) > Length('[INI]')+2 then
  1069. Script := Script + INI + SNewLine;
  1070. if Length(Icons) > Length('[Icons]')+2 then
  1071. Script := Script + Icons + SNewLine;
  1072. if Length(Run) > Length('[Run]')+2 then
  1073. Script := Script + Run + SNewLine;
  1074. if Length(UninstallDelete) > Length('[UninstallDelete]')+2 then
  1075. Script := Script + UninstallDelete + SNewLine;
  1076. FResult := wrComplete;
  1077. end else begin
  1078. Script := Script + Setup;
  1079. FResult := wrEmpty;
  1080. end;
  1081. FResultScript := FixLabel(SWizardScriptHeader) + SNewLine;
  1082. if (FResult = wrComplete) and not IsLicensed then
  1083. FResultScript := FResultScript + '; ' + GetLicenseeDescription + SNewLine;
  1084. FResultScript := FResultScript + SNewLine + Script;
  1085. end;
  1086. { --- }
  1087. end.