ScriptDlg.pas 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049
  1. unit ScriptDlg;
  2. {
  3. Inno Setup
  4. Copyright (C) 1997-2012 Jordan Russell
  5. Portions by Martijn Laan
  6. For conditions of distribution and use, see LICENSE.TXT.
  7. Custom wizard pages
  8. }
  9. interface
  10. {$I VERSION.INC}
  11. uses
  12. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, StdCtrls, Contnrs,
  13. Wizard, Install,
  14. NewCheckListBox, NewStaticText, NewProgressBar, PasswordEdit, RichEditViewer,
  15. BidiCtrls, TaskbarProgressFunc;
  16. type
  17. TInputQueryWizardPage = class(TWizardPage)
  18. private
  19. FEdits: TList;
  20. FPromptLabels: TList;
  21. FSubCaptionLabel: TNewStaticText;
  22. FY: Integer;
  23. function GetEdit(Index: Integer): TPasswordEdit;
  24. function GetPromptLabel(Index: Integer): TNewStaticText;
  25. function GetValue(Index: Integer): String;
  26. procedure SetValue(Index: Integer; const Value: String);
  27. public
  28. constructor Create(AOwner: TComponent); override;
  29. destructor Destroy; override;
  30. function Add(const APrompt: String; const APassword: Boolean): Integer;
  31. property Edits[Index: Integer]: TPasswordEdit read GetEdit;
  32. procedure Initialize(const SubCaption: String);
  33. property PromptLabels[Index: Integer]: TNewStaticText read GetPromptLabel;
  34. property Values[Index: Integer]: String read GetValue write SetValue;
  35. published
  36. property SubCaptionLabel: TNewStaticText read FSubCaptionLabel;
  37. end;
  38. TInputOptionWizardPage = class(TWizardPage)
  39. private
  40. FCheckListBox: TNewCheckListBox;
  41. FExclusive: Boolean;
  42. FSubCaptionLabel: TNewStaticText;
  43. function GetSelectedValueIndex: Integer;
  44. function GetValue(Index: Integer): Boolean;
  45. procedure SetSelectedValueIndex(Value: Integer);
  46. procedure SetValue(Index: Integer; Value: Boolean);
  47. public
  48. function Add(const ACaption: String): Integer;
  49. function AddEx(const ACaption: String; const ALevel: Byte; const AExclusive: Boolean): Integer;
  50. procedure Initialize(const SubCaption: String; const Exclusive, ListBox: Boolean);
  51. property SelectedValueIndex: Integer read GetSelectedValueIndex write SetSelectedValueIndex;
  52. property Values[Index: Integer]: Boolean read GetValue write SetValue;
  53. published
  54. property CheckListBox: TNewCheckListBox read FCheckListBox;
  55. property SubCaptionLabel: TNewStaticText read FSubCaptionLabel;
  56. end;
  57. TInputDirWizardPage = class(TWizardPage)
  58. private
  59. FAppendDir: Boolean;
  60. FButtons: TList;
  61. FEdits: TList;
  62. FNewFolderName: String;
  63. FPromptLabels: TList;
  64. FSubCaptionLabel: TNewStaticText;
  65. FY: Integer;
  66. procedure ButtonClick(Sender: TObject);
  67. function GetButton(Index: Integer): TNewButton;
  68. function GetEdit(Index: Integer): TEdit;
  69. function GetPromptLabel(Index: Integer): TNewStaticText;
  70. function GetValue(Index: Integer): String;
  71. procedure SetValue(Index: Integer; const Value: String);
  72. protected
  73. procedure NextButtonClick(var Continue: Boolean); override;
  74. public
  75. constructor Create(AOwner: TComponent); override;
  76. destructor Destroy; override;
  77. function Add(const APrompt: String): Integer;
  78. property Buttons[Index: Integer]: TNewButton read GetButton;
  79. property Edits[Index: Integer]: TEdit read GetEdit;
  80. procedure Initialize(const SubCaption: String; const AppendDir: Boolean;
  81. const NewFolderName: String);
  82. property PromptLabels[Index: Integer]: TNewStaticText read GetPromptLabel;
  83. property Values[Index: Integer]: String read GetValue write SetValue;
  84. published
  85. property SubCaptionLabel: TNewStaticText read FSubCaptionLabel;
  86. end;
  87. TInputFileWizardPage = class(TWizardPage)
  88. private
  89. FButtons: TList;
  90. FEdits: TList;
  91. FInputFileDefaultExtensions: TStringList;
  92. FInputFileFilters: TStringList;
  93. FPromptLabels: TList;
  94. FSubCaptionLabel: TNewStaticText;
  95. FY: Integer;
  96. procedure ButtonClick(Sender: TObject);
  97. function GetButton(Index: Integer): TNewButton;
  98. function GetEdit(Index: Integer): TEdit;
  99. function GetPromptLabel(Index: Integer): TNewStaticText;
  100. function GetValue(Index: Integer): String;
  101. procedure SetValue(Index: Integer; const Value: String);
  102. function GetIsSaveButton(Index: Integer): Boolean;
  103. procedure SetIsSaveButton(Index: Integer; const IsSaveButton: Boolean);
  104. public
  105. constructor Create(AOwner: TComponent); override;
  106. destructor Destroy; override;
  107. function Add(const APrompt, AFilter, ADefaultExtension: String): Integer;
  108. property Buttons[Index: Integer]: TNewButton read GetButton;
  109. property Edits[Index: Integer]: TEdit read GetEdit;
  110. procedure Initialize(const SubCaption: String);
  111. property PromptLabels[Index: Integer]: TNewStaticText read GetPromptLabel;
  112. property Values[Index: Integer]: String read GetValue write SetValue;
  113. property IsSaveButton[Index: Integer]: Boolean read GetIsSaveButton write SetIsSaveButton;
  114. published
  115. property SubCaptionLabel: TNewStaticText read FSubCaptionLabel;
  116. end;
  117. TOutputMsgWizardPage = class(TWizardPage)
  118. private
  119. FMsgLabel: TNewStaticText;
  120. public
  121. procedure Initialize(const Msg: String);
  122. published
  123. property MsgLabel: TNewStaticText read FMsgLabel;
  124. end;
  125. TOutputMsgMemoWizardPage = class(TWizardPage)
  126. private
  127. FRichEditViewer: TRichEditViewer;
  128. FSubCaptionLabel: TNewStaticText;
  129. public
  130. procedure Initialize(const SubCaption: String; const Msg: AnsiString);
  131. published
  132. property RichEditViewer: TRichEditViewer read FRichEditViewer;
  133. property SubCaptionLabel: TNewStaticText read FSubCaptionLabel;
  134. end;
  135. TOutputProgressWizardPage = class(TWizardPage)
  136. private
  137. FMsg1Label: TNewStaticText;
  138. FMsg2Label: TNewStaticText;
  139. FProgressBar: TNewProgressBar;
  140. FUseMarqueeStyle: Boolean;
  141. FSavePageID: Integer;
  142. procedure ProcessMsgs;
  143. public
  144. constructor Create(AOwner: TComponent); override;
  145. procedure Hide;
  146. procedure Initialize; virtual;
  147. procedure SetProgress(const Position, Max: Longint);
  148. procedure SetText(const Msg1, Msg2: String);
  149. procedure Show; virtual;
  150. published
  151. property Msg1Label: TNewStaticText read FMsg1Label;
  152. property Msg2Label: TNewStaticText read FMsg2Label;
  153. property ProgressBar: TNewProgressBar read FProgressBar;
  154. end;
  155. TOutputMarqueeProgressWizardPage = class(TOutputProgressWizardPage)
  156. public
  157. constructor Create(AOwner: TComponent); override;
  158. procedure Animate;
  159. procedure Initialize; override;
  160. procedure SetProgress(const Position, Max: Longint);
  161. end;
  162. {$IFNDEF PS_NOINT64}
  163. TDownloadWizardPage = class(TOutputProgressWizardPage)
  164. private
  165. FFiles: TObjectList;
  166. FOnDownloadProgress: TOnDownloadProgress;
  167. FAbortButton: TNewButton;
  168. FShowProgressControlsOnNextProgress, FAbortedByUser: Boolean;
  169. procedure AbortButtonClick(Sender: TObject);
  170. function InternalOnDownloadProgress(const Url, BaseName: string; const Progress, ProgressMax: Int64): Boolean;
  171. procedure ShowProgressControls(const AVisible: Boolean);
  172. public
  173. constructor Create(AOwner: TComponent); override;
  174. destructor Destroy; override;
  175. procedure Initialize; override;
  176. property AbortedByUser: Boolean read FAbortedByUser;
  177. procedure Add(const Url, BaseName, RequiredSHA256OfFile: String);
  178. procedure Clear;
  179. function Download: Int64;
  180. property OnDownloadProgress: TOnDownloadProgress write FOnDownloadProgress;
  181. procedure Show; override;
  182. published
  183. property AbortButton: TNewButton read FAbortButton;
  184. end;
  185. {$ENDIF}
  186. implementation
  187. uses
  188. Struct, Main, SelFolderForm, Msgs, MsgIDs, PathFunc, CmnFunc, CmnFunc2,
  189. BrowseFunc, Logging, InstFunc;
  190. const
  191. DefaultLabelHeight = 14;
  192. DefaultBoxTop = 24; { relative to top of InnerNotebook }
  193. DefaultBoxBottom = DefaultBoxTop + 205;
  194. {------}
  195. procedure SetCtlParent(const AControl, AParent: TWinControl);
  196. { Like assigning to AControl.Parent, but puts the control at the *bottom* of
  197. the z-order instead of the top, for MSAA compatibility. }
  198. var
  199. OldVisible: Boolean;
  200. begin
  201. { Hide the control so the handle won't be created yet, so that unnecessary
  202. "OBJ_REORDER" MSAA events don't get sent }
  203. OldVisible := AControl.Visible;
  204. AControl.Visible := False;
  205. AControl.Parent := AParent;
  206. AControl.SendToBack;
  207. AControl.Visible := OldVisible;
  208. end;
  209. {--- InputQuery ---}
  210. constructor TInputQueryWizardPage.Create(AOwner: TComponent);
  211. begin
  212. inherited;
  213. FEdits := TList.Create;
  214. FPromptLabels := TList.Create;
  215. end;
  216. destructor TInputQueryWizardPage.Destroy;
  217. begin
  218. FPromptLabels.Free;
  219. FEdits.Free;
  220. inherited;
  221. end;
  222. procedure TInputQueryWizardPage.Initialize(const SubCaption: String);
  223. begin
  224. FSubCaptionLabel := TNewStaticText.Create(Self);
  225. with FSubCaptionLabel do begin
  226. AutoSize := False;
  227. Width := SurfaceWidth;
  228. Height := WizardForm.ScalePixelsY(DefaultLabelHeight);
  229. WordWrap := True;
  230. Caption := SubCaption;
  231. Parent := Surface;
  232. end;
  233. FY := WizardForm.AdjustLabelHeight(FSubCaptionLabel) + WizardForm.ScalePixelsY(DefaultBoxTop);
  234. end;
  235. function TInputQueryWizardPage.Add(const APrompt: String;
  236. const APassword: Boolean): Integer;
  237. var
  238. PromptLabel: TNewStaticText;
  239. Edit: TPasswordEdit;
  240. begin
  241. if APrompt <> '' then begin
  242. PromptLabel := TNewStaticText.Create(Self);
  243. with PromptLabel do begin
  244. AutoSize := False;
  245. Top := FY;
  246. Width := SurfaceWidth;
  247. Height := WizardForm.ScalePixelsY(DefaultLabelHeight);
  248. Anchors := [akLeft, akTop, akRight];
  249. WordWrap := True;
  250. Caption := APrompt;
  251. end;
  252. SetCtlParent(PromptLabel, Surface);
  253. Inc(FY, WizardForm.AdjustLabelHeight(PromptLabel) + WizardForm.ScalePixelsY(16));
  254. end else
  255. PromptLabel := nil;
  256. Edit := TPasswordEdit.Create(Self);
  257. with Edit do begin
  258. Password := APassword;
  259. Top := FY;
  260. Width := SurfaceWidth;
  261. Anchors := [akLeft, akTop, akRight];
  262. end;
  263. SetCtlParent(Edit, Surface);
  264. Inc(FY, WizardForm.ScalePixelsY(36));
  265. if PromptLabel <> nil then
  266. PromptLabel.FocusControl := Edit;
  267. FPromptLabels.Add(PromptLabel);
  268. Result := FEdits.Add(Edit);
  269. end;
  270. function TInputQueryWizardPage.GetEdit(Index: Integer): TPasswordEdit;
  271. begin
  272. Result := TPasswordEdit(FEdits[Index]);
  273. end;
  274. function TInputQueryWizardPage.GetPromptLabel(Index: Integer): TNewStaticText;
  275. begin
  276. Result := TNewStaticText(FPromptLabels[Index]);
  277. end;
  278. function TInputQueryWizardPage.GetValue(Index: Integer): String;
  279. begin
  280. Result := GetEdit(Index).Text;
  281. end;
  282. procedure TInputQueryWizardPage.SetValue(Index: Integer; const Value: String);
  283. begin
  284. GetEdit(Index).Text := Value;
  285. end;
  286. {--- InputOption ---}
  287. procedure TInputOptionWizardPage.Initialize(const SubCaption: String;
  288. const Exclusive, ListBox: Boolean);
  289. var
  290. CaptionYDiff: Integer;
  291. begin
  292. FSubCaptionLabel := TNewStaticText.Create(Self);
  293. with SubCaptionLabel do begin
  294. AutoSize := False;
  295. Width := SurfaceWidth;
  296. Height := WizardForm.ScalePixelsY(DefaultLabelHeight);
  297. Anchors := [akLeft, akTop, akRight];
  298. WordWrap := True;
  299. Caption := SubCaption;
  300. Parent := Surface;
  301. end;
  302. CaptionYDiff := WizardForm.AdjustLabelHeight(SubCaptionLabel);
  303. FCheckListBox := TNewCheckListBox.Create(Self);
  304. with FCheckListBox do begin
  305. Top := CaptionYDiff + WizardForm.ScalePixelsY(DefaultBoxTop);
  306. Width := SurfaceWidth;
  307. Height := WizardForm.ScalePixelsY(DefaultBoxBottom) - Top;
  308. Anchors := [akLeft, akTop, akRight, akBottom];
  309. Flat := ListBox and (shFlatComponentsList in SetupHeader.Options);
  310. end;
  311. SetCtlParent(FCheckListBox, Surface);
  312. FExclusive := Exclusive;
  313. if not ListBox then begin
  314. FCheckListBox.BorderStyle := bsNone;
  315. FCheckListBox.Color := SurfaceColor;
  316. FCheckListBox.MinItemHeight := WizardForm.ScalePixelsY(22);
  317. FCheckListBox.WantTabs := True;
  318. end;
  319. end;
  320. function TInputOptionWizardPage.Add(const ACaption: String): Integer;
  321. begin
  322. Result := AddEx(ACaption, 0, FExclusive);
  323. end;
  324. function TInputOptionWizardPage.AddEx(const ACaption: String;
  325. const ALevel: Byte; const AExclusive: Boolean): Integer;
  326. begin
  327. if AExclusive then
  328. Result := FCheckListBox.AddRadioButton(ACaption, '', ALevel, False, True, nil)
  329. else
  330. Result := FCheckListBox.AddCheckBox(ACaption, '', ALevel, False, True, True,
  331. True, nil);
  332. end;
  333. function TInputOptionWizardPage.GetSelectedValueIndex: Integer;
  334. var
  335. I: Integer;
  336. begin
  337. for I := 0 to FCheckListBox.Items.Count-1 do
  338. if (FCheckListBox.ItemLevel[I] = 0) and FCheckListBox.Checked[I] then begin
  339. Result := I;
  340. Exit;
  341. end;
  342. Result := -1;
  343. end;
  344. function TInputOptionWizardPage.GetValue(Index: Integer): Boolean;
  345. begin
  346. Result := FCheckListBox.Checked[Index];
  347. end;
  348. procedure TInputOptionWizardPage.SetSelectedValueIndex(Value: Integer);
  349. var
  350. I: Integer;
  351. begin
  352. for I := 0 to FCheckListBox.Items.Count-1 do
  353. if FCheckListBox.ItemLevel[I] = 0 then
  354. FCheckListBox.Checked[I] := (I = Value);
  355. end;
  356. procedure TInputOptionWizardPage.SetValue(Index: Integer; Value: Boolean);
  357. begin
  358. FCheckListBox.Checked[Index] := Value;
  359. end;
  360. {--- InputDir ---}
  361. constructor TInputDirWizardPage.Create(AOwner: TComponent);
  362. begin
  363. inherited;
  364. FButtons := TList.Create;
  365. FEdits := TList.Create;
  366. FPromptLabels := TList.Create;
  367. end;
  368. destructor TInputDirWizardPage.Destroy;
  369. begin
  370. FPromptLabels.Free;
  371. FEdits.Free;
  372. FButtons.Free;
  373. inherited;
  374. end;
  375. procedure TInputDirWizardPage.ButtonClick(Sender: TObject);
  376. var
  377. I: Integer;
  378. Edit: TEdit;
  379. S: String;
  380. begin
  381. I := FButtons.IndexOf(Sender);
  382. if I <> -1 then begin
  383. Edit := TEdit(FEdits[I]);
  384. S := Edit.Text;
  385. if ShowSelectFolderDialog(False, FAppendDir, S, FNewFolderName) then
  386. Edit.Text := S;
  387. end;
  388. end;
  389. procedure TInputDirWizardPage.NextButtonClick(var Continue: Boolean);
  390. var
  391. I: Integer;
  392. Edit: TEdit;
  393. begin
  394. for I := 0 to FEdits.Count-1 do begin
  395. Edit := FEdits[I];
  396. if not ValidateCustomDirEdit(Edit, True, True, True) then begin
  397. if WizardForm.Visible then
  398. Edit.SetFocus;
  399. Continue := False;
  400. Exit;
  401. end;
  402. end;
  403. inherited;
  404. end;
  405. procedure TInputDirWizardPage.Initialize(const SubCaption: String;
  406. const AppendDir: Boolean; const NewFolderName: String);
  407. begin
  408. FSubCaptionLabel := TNewStaticText.Create(Self);
  409. with FSubCaptionLabel do begin
  410. AutoSize := False;
  411. Width := SurfaceWidth;
  412. Height := WizardForm.ScalePixelsY(DefaultLabelHeight);
  413. Anchors := [akLeft, akTop, akRight];
  414. WordWrap := True;
  415. Caption := SubCaption;
  416. Parent := Surface;
  417. end;
  418. FY := WizardForm.AdjustLabelHeight(FSubCaptionLabel) + WizardForm.ScalePixelsY(DefaultBoxTop);
  419. FAppendDir := AppendDir;
  420. FNewFolderName := NewFolderName;
  421. end;
  422. function TInputDirWizardPage.Add(const APrompt: String): Integer;
  423. var
  424. ButtonWidth: Integer;
  425. PromptLabel: TNewStaticText;
  426. Edit: TEdit;
  427. Button: TNewButton;
  428. begin
  429. ButtonWidth := WizardForm.CalculateButtonWidth([SetupMessages[msgButtonWizardBrowse]]);
  430. if APrompt <> '' then begin
  431. PromptLabel := TNewStaticText.Create(Self);
  432. with PromptLabel do begin
  433. AutoSize := False;
  434. Top := FY;
  435. Width := SurfaceWidth;
  436. Height := WizardForm.ScalePixelsY(DefaultLabelHeight);
  437. Anchors := [akLeft, akTop, akRight];
  438. WordWrap := True;
  439. Caption := APrompt;
  440. end;
  441. SetCtlParent(PromptLabel, Surface);
  442. Inc(FY, WizardForm.AdjustLabelHeight(PromptLabel) + WizardForm.ScalePixelsY(16));
  443. end else
  444. PromptLabel := nil;
  445. Edit := TEdit.Create(Self);
  446. with Edit do begin
  447. Top := FY;
  448. Width := SurfaceWidth-ButtonWidth-WizardForm.ScalePixelsX(10);
  449. Anchors := [akLeft, akTop, akRight];
  450. end;
  451. SetCtlParent(Edit, Surface);
  452. TryEnableAutoCompleteFileSystem(Edit.Handle);
  453. if PromptLabel <> nil then
  454. PromptLabel.FocusControl := Edit;
  455. Button := TNewButton.Create(Self);
  456. with Button do begin
  457. Left := SurfaceWidth-ButtonWidth;
  458. Top := Edit.Top-1;
  459. Width := ButtonWidth;
  460. Height := WizardForm.NextButton.Height;
  461. Anchors := [akTop, akRight];
  462. if FEdits.Count = 0 then
  463. Caption := SetupMessages[msgButtonWizardBrowse]
  464. else
  465. { Can't use the same accel key for secondary buttons... }
  466. Caption := RemoveAccelChar(SetupMessages[msgButtonWizardBrowse]);
  467. OnClick := ButtonClick;
  468. end;
  469. SetCtlParent(Button, Surface);
  470. Inc(FY, WizardForm.ScalePixelsY(36));
  471. FButtons.Add(Button);
  472. FPromptLabels.Add(PromptLabel);
  473. Result := FEdits.Add(Edit);
  474. end;
  475. function TInputDirWizardPage.GetButton(Index: Integer): TNewButton;
  476. begin
  477. Result := TNewButton(FButtons[Index]);
  478. end;
  479. function TInputDirWizardPage.GetEdit(Index: Integer): TEdit;
  480. begin
  481. Result := TEdit(FEdits[Index]);
  482. end;
  483. function TInputDirWizardPage.GetPromptLabel(Index: Integer): TNewStaticText;
  484. begin
  485. Result := TNewStaticText(FPromptLabels[Index]);
  486. end;
  487. function TInputDirWizardPage.GetValue(Index: Integer): String;
  488. begin
  489. Result := GetEdit(Index).Text;
  490. end;
  491. procedure TInputDirWizardPage.SetValue(Index: Integer; const Value: String);
  492. begin
  493. GetEdit(Index).Text := RemoveBackslashUnlessRoot(PathExpand(Value));
  494. end;
  495. {--- InputFile ---}
  496. constructor TInputFileWizardPage.Create(AOwner: TComponent);
  497. begin
  498. inherited;
  499. FButtons := TList.Create;
  500. FEdits := TList.Create;
  501. FInputFileDefaultExtensions := TStringList.Create;
  502. FInputFileFilters := TStringList.Create;
  503. FPromptLabels := TList.Create;
  504. end;
  505. destructor TInputFileWizardPage.Destroy;
  506. begin
  507. FPromptLabels.Free;
  508. FInputFileFilters.Free;
  509. FInputFileDefaultExtensions.Free;
  510. FEdits.Free;
  511. FButtons.Free;
  512. inherited;
  513. end;
  514. procedure TInputFileWizardPage.ButtonClick(Sender: TObject);
  515. var
  516. I: Integer;
  517. Edit: TEdit;
  518. FileName: String;
  519. begin
  520. I := FButtons.IndexOf(Sender);
  521. if I <> -1 then begin
  522. Edit := TEdit(FEdits[I]);
  523. FileName := Edit.Text;
  524. if (not IsSaveButton[I] and NewGetOpenFileName(RemoveAccelChar(SetupMessages[msgButtonWizardBrowse]),
  525. FileName, PathExtractPath(FileName), FInputFileFilters[I],
  526. FInputFileDefaultExtensions[I], Surface.Handle)) or
  527. (IsSaveButton[I] and NewGetSaveFileName(RemoveAccelChar(SetupMessages[msgButtonWizardBrowse]),
  528. FileName, PathExtractPath(FileName), FInputFileFilters[I],
  529. FInputFileDefaultExtensions[I], Surface.Handle)) then
  530. Edit.Text := FileName;
  531. end;
  532. end;
  533. procedure TInputFileWizardPage.Initialize(const SubCaption: String);
  534. begin
  535. FSubCaptionLabel := TNewStaticText.Create(Self);
  536. with FSubCaptionLabel do begin
  537. AutoSize := False;
  538. Width := SurfaceWidth;
  539. Height := WizardForm.ScalePixelsY(DefaultLabelHeight);
  540. Anchors := [akLeft, akTop, akRight];
  541. WordWrap := True;
  542. Caption := SubCaption;
  543. Parent := Surface;
  544. end;
  545. FY := WizardForm.AdjustLabelHeight(FSubCaptionLabel) + WizardForm.ScalePixelsY(DefaultBoxTop);
  546. end;
  547. function TInputFileWizardPage.Add(const APrompt, AFilter,
  548. ADefaultExtension: String): Integer;
  549. var
  550. ButtonWidth: Integer;
  551. PromptLabel: TNewStaticText;
  552. Edit: TEdit;
  553. Button: TNewButton;
  554. begin
  555. ButtonWidth := WizardForm.CalculateButtonWidth([SetupMessages[msgButtonWizardBrowse]]);
  556. if APrompt <> '' then begin
  557. PromptLabel := TNewStaticText.Create(Self);
  558. with PromptLabel do begin
  559. AutoSize := False;
  560. Top := FY;
  561. Width := SurfaceWidth;
  562. Height := WizardForm.ScalePixelsY(DefaultLabelHeight);
  563. Anchors := [akLeft, akTop, akRight];
  564. WordWrap := True;
  565. Caption := APrompt;
  566. end;
  567. SetCtlParent(PromptLabel, Surface);
  568. Inc(FY, WizardForm.AdjustLabelHeight(PromptLabel) + WizardForm.ScalePixelsY(16));
  569. end else
  570. PromptLabel := nil;
  571. Edit := TEdit.Create(Self);
  572. with Edit do begin
  573. Top := FY;
  574. Width := SurfaceWidth-ButtonWidth-WizardForm.ScalePixelsX(10);
  575. Anchors := [akLeft, akTop, akRight];
  576. end;
  577. SetCtlParent(Edit, Surface);
  578. TryEnableAutoCompleteFileSystem(Edit.Handle);
  579. if PromptLabel <> nil then
  580. PromptLabel.FocusControl := Edit;
  581. Button := TNewButton.Create(Self);
  582. with Button do begin
  583. Left := SurfaceWidth-ButtonWidth;
  584. Top := Edit.Top-1;
  585. Width := ButtonWidth;
  586. Height := WizardForm.NextButton.Height;
  587. Anchors := [akTop, akRight];
  588. if FButtons.Count = 0 then
  589. Caption := SetupMessages[msgButtonWizardBrowse]
  590. else
  591. { Can't use the same accel key for secondary buttons... }
  592. Caption := RemoveAccelChar(SetupMessages[msgButtonWizardBrowse]);
  593. OnClick := ButtonClick;
  594. end;
  595. SetCtlParent(Button, Surface);
  596. Inc(FY, WizardForm.ScalePixelsY(36));
  597. FInputFileFilters.Add(AFilter);
  598. FInputFileDefaultExtensions.Add(ADefaultExtension);
  599. FButtons.Add(Button);
  600. FPromptLabels.Add(PromptLabel);
  601. Result := FEdits.Add(Edit);
  602. end;
  603. function TInputFileWizardPage.GetButton(Index: Integer): TNewButton;
  604. begin
  605. Result := TNewButton(FButtons[Index]);
  606. end;
  607. function TInputFileWizardPage.GetEdit(Index: Integer): TEdit;
  608. begin
  609. Result := TEdit(FEdits[Index]);
  610. end;
  611. function TInputFileWizardPage.GetPromptLabel(Index: Integer): TNewStaticText;
  612. begin
  613. Result := TNewStaticText(FPromptLabels[Index]);
  614. end;
  615. function TInputFileWizardPage.GetValue(Index: Integer): String;
  616. begin
  617. Result := GetEdit(Index).Text;
  618. end;
  619. procedure TInputFileWizardPage.SetValue(Index: Integer; const Value: String);
  620. begin
  621. GetEdit(Index).Text := Value;
  622. end;
  623. function TInputFileWizardPage.GetIsSaveButton(Index: Integer): Boolean;
  624. begin
  625. Result := GetButton(Index).Tag = 1;
  626. end;
  627. procedure TInputFileWizardPage.SetIsSaveButton(Index: Integer; const IsSaveButton: Boolean);
  628. begin
  629. if IsSaveButton then
  630. GetButton(Index).Tag := 1
  631. else
  632. GetButton(Index).Tag := 0;
  633. end;
  634. {--- OutputMsg ---}
  635. procedure TOutputMsgWizardPage.Initialize(const Msg: String);
  636. begin
  637. FMsgLabel := TNewStaticText.Create(Self);
  638. with FMsgLabel do begin
  639. AutoSize := False;
  640. Width := SurfaceWidth;
  641. Height := WizardForm.ScalePixelsY(DefaultLabelHeight);
  642. WordWrap := True;
  643. Caption := Msg;
  644. Parent := Surface;
  645. end;
  646. WizardForm.AdjustLabelHeight(MsgLabel);
  647. end;
  648. {--- OutputMsgMemo ---}
  649. procedure TOutputMsgMemoWizardPage.Initialize(const SubCaption: String; const Msg: AnsiString);
  650. var
  651. Y: Integer;
  652. begin
  653. Y := 0;
  654. if SubCaption <> '' then begin
  655. FSubCaptionLabel := TNewStaticText.Create(Self);
  656. with FSubCaptionLabel do begin
  657. AutoSize := False;
  658. Width := SurfaceWidth;
  659. Height := WizardForm.ScalePixelsY(DefaultLabelHeight);
  660. Anchors := [akLeft, akTop, akRight];
  661. WordWrap := True;
  662. Caption := SubCaption;
  663. Parent := Surface;
  664. end;
  665. Inc(Y, WizardForm.ScalePixelsY(DefaultBoxTop) +
  666. WizardForm.AdjustLabelHeight(FSubCaptionLabel));
  667. end else
  668. FSubCaptionLabel := nil;
  669. FRichEditViewer := TRichEditViewer.Create(Self);
  670. with FRichEditViewer do begin
  671. Top := Y;
  672. Width := SurfaceWidth;
  673. Height := WizardForm.ScalePixelsY(DefaultBoxBottom) - Y;
  674. Anchors := [akLeft, akTop, akRight, akBottom];
  675. BevelKind := bkFlat;
  676. BorderStyle := bsNone;
  677. ReadOnly := True;
  678. ScrollBars := ssVertical;
  679. WantReturns := False;
  680. end;
  681. SetCtlParent(FRichEditViewer, Surface);
  682. with FRichEditViewer do begin
  683. UseRichEdit := True;
  684. RTFText := Msg;
  685. end;
  686. end;
  687. {--- OutputProgress ---}
  688. constructor TOutputProgressWizardPage.Create(AOwner: TComponent);
  689. begin
  690. inherited;
  691. Style := Style + [psAlwaysSkip, psNoButtons];
  692. end;
  693. procedure TOutputProgressWizardPage.Initialize;
  694. begin
  695. FMsg1Label := TNewStaticText.Create(Self);
  696. with FMsg1Label do begin
  697. AutoSize := False;
  698. ShowAccelChar := False;
  699. Width := SurfaceWidth;
  700. Anchors := [akLeft, akTop, akRight];
  701. Height := WizardForm.StatusLabel.Height;
  702. WordWrap := WizardForm.StatusLabel.WordWrap;
  703. Parent := Surface;
  704. end;
  705. FMsg2Label := TNewStaticText.Create(Self);
  706. with FMsg2Label do begin
  707. AutoSize := False;
  708. ForceLTRReading := True;
  709. ShowAccelChar := False;
  710. Top := WizardForm.ScalePixelsY(16);
  711. Width := SurfaceWidth;
  712. Height := WizardForm.FileNameLabel.Height;
  713. Anchors := [akLeft, akTop, akRight];
  714. end;
  715. SetCtlParent(FMsg2Label, Surface);
  716. FProgressBar := TNewProgressBar.Create(Self);
  717. with FProgressBar do begin
  718. Top := WizardForm.ScalePixelsY(42);
  719. Width := SurfaceWidth;
  720. Height := WizardForm.ScalePixelsY(21);
  721. Anchors := [akLeft, akTop, akRight];
  722. Visible := False;
  723. end;
  724. SetCtlParent(FProgressBar, Surface);
  725. end;
  726. procedure TOutputProgressWizardPage.Hide;
  727. begin
  728. if (WizardForm.CurPageID = ID) and (FSavePageID <> 0) then begin
  729. SetMessageBoxCallbackFunc(nil, 0);
  730. SetAppTaskbarProgressState(tpsNoProgress);
  731. WizardForm.SetCurPage(FSavePageID);
  732. FSavePageID := 0;
  733. end;
  734. end;
  735. procedure TOutputProgressWizardPage.ProcessMsgs;
  736. { Process messages to repaint and keep Windows from thinking the process is
  737. hung. This is safe; due to the psNoButtons style the user shouldn't be able
  738. to cancel or do anything else during this time. }
  739. begin
  740. if WizardForm.CurPageID = ID then
  741. Application.ProcessMessages;
  742. end;
  743. procedure TOutputProgressWizardPage.SetProgress(const Position, Max: Longint);
  744. begin
  745. if Max > 0 then begin
  746. FProgressBar.Style := npbstNormal;
  747. FProgressBar.Max := Max;
  748. FProgressBar.Position := Position;
  749. FProgressBar.Visible := True;
  750. SetAppTaskbarProgressState(tpsNormal);
  751. SetAppTaskbarProgressValue(Position, Max);
  752. end else begin
  753. if FUseMarqueeStyle then
  754. FProgressBar.Style := npbstMarquee
  755. else
  756. FProgressBar.Visible := False;
  757. SetAppTaskbarProgressState(tpsNoProgress);
  758. end;
  759. ProcessMsgs;
  760. end;
  761. procedure TOutputProgressWizardPage.SetText(const Msg1, Msg2: String);
  762. begin
  763. FMsg1Label.Caption := Msg1;
  764. FMsg2Label.Caption := MinimizePathName(Msg2, FMsg2Label.Font,
  765. FMsg2Label.Width);
  766. ProcessMsgs;
  767. end;
  768. procedure OutputProgressWizardPageMessageBoxCallback(const Flags: LongInt; const After: Boolean;
  769. const Param: LongInt);
  770. const
  771. States: array [TNewProgressBarState] of TTaskbarProgressState =
  772. (tpsNormal, tpsError, tpsPaused);
  773. var
  774. OutputProgressWizardPage: TOutputProgressWizardPage;
  775. NewState: TNewProgressBarState;
  776. begin
  777. OutputProgressWizardPage := TOutputProgressWizardPage(Param);
  778. if After then
  779. NewState := npbsNormal
  780. else if (Flags and MB_ICONSTOP) <> 0 then
  781. NewState := npbsError
  782. else
  783. NewState := npbsPaused;
  784. with OutputProgressWizardPage.ProgressBar do begin
  785. State := NewState;
  786. Invalidate;
  787. end;
  788. SetAppTaskbarProgressState(States[NewState]);
  789. end;
  790. procedure TOutputProgressWizardPage.Show;
  791. begin
  792. if WizardForm.CurPageID <> ID then begin
  793. FSavePageID := WizardForm.CurPageID;
  794. WizardForm.SetCurPage(ID);
  795. SetMessageBoxCallbackFunc(OutputProgressWizardPageMessageBoxCallback, LongInt(Self));
  796. ProcessMsgs;
  797. end;
  798. end;
  799. constructor TOutputMarqueeProgressWizardPage.Create(AOwner: TComponent);
  800. begin
  801. inherited;
  802. FUseMarqueeStyle := True;
  803. end;
  804. procedure TOutputMarqueeProgressWizardPage.Animate;
  805. begin
  806. ProcessMsgs;
  807. end;
  808. procedure TOutputMarqueeProgressWizardPage.Initialize;
  809. begin
  810. inherited;
  811. FProgressBar.Visible := True;
  812. inherited SetProgress(0, 0);
  813. end;
  814. procedure TOutputMarqueeProgressWizardPage.SetProgress(const Position, Max: Longint);
  815. begin
  816. InternalError('Cannot call TOutputMarqueeProgressWizardPage.SetProgress');
  817. end;
  818. {$IFNDEF PS_NOINT64}
  819. {--- OutputDownload ---}
  820. type
  821. TDownloadFile = class
  822. Url, BaseName, RequiredSHA256OfFile: String;
  823. end;
  824. procedure TDownloadWizardPage.AbortButtonClick(Sender: TObject);
  825. begin
  826. FAbortedByUser := LoggedMsgBox(SetupMessages[msgStopDownload], '', mbConfirmation, MB_YESNO, True, ID_YES) = IDYES;
  827. end;
  828. function TDownloadWizardPage.InternalOnDownloadProgress(const Url, BaseName: string; const Progress, ProgressMax: Int64): Boolean;
  829. var
  830. Progress32, ProgressMax32: LongInt;
  831. begin
  832. if FAbortedByUser then begin
  833. Log('Need to abort download.');
  834. Result := False;
  835. end else begin
  836. if ProgressMax > 0 then
  837. Log(Format(' %d of %d bytes done.', [Progress, ProgressMax]))
  838. else
  839. Log(Format(' %d bytes done.', [Progress]));
  840. FMsg2Label.Caption := Url;
  841. if ProgressMax > MaxLongInt then begin
  842. Progress32 := Round((Progress / ProgressMax) * MaxLongInt);
  843. ProgressMax32 := MaxLongInt;
  844. end else begin
  845. Progress32 := Progress;
  846. ProgressMax32 := ProgressMax;
  847. end;
  848. SetProgress(Progress32, ProgressMax32); { This will process messages which we need for the abort button to work }
  849. if FShowProgressControlsOnNextProgress then begin
  850. ShowProgressControls(True);
  851. FShowProgressControlsOnNextProgress := False;
  852. ProcessMsgs;
  853. end;
  854. if Assigned(FOnDownloadProgress) then
  855. Result := FOnDownloadProgress(Url, BaseName, Progress, ProgressMax)
  856. else
  857. Result := True;
  858. end;
  859. end;
  860. constructor TDownloadWizardPage.Create(AOwner: TComponent);
  861. begin
  862. inherited;
  863. FUseMarqueeStyle := True;
  864. FFiles := TObjectList.Create;
  865. end;
  866. destructor TDownloadWizardPage.Destroy;
  867. begin
  868. FFiles.Free;
  869. inherited;
  870. end;
  871. procedure TDownloadWizardPage.Initialize;
  872. begin
  873. inherited;
  874. FMsg1Label.Caption := SetupMessages[msgDownloadingLabel];
  875. FAbortButton := TNewButton.Create(Self);
  876. with FAbortButton do begin
  877. Caption := SetupMessages[msgButtonStopDownload];
  878. Top := FProgressBar.Top + FProgressBar.Height + WizardForm.ScalePixelsY(8);
  879. Width := WizardForm.CalculateButtonWidth([Caption]);
  880. Anchors := [akLeft, akTop];
  881. Height := WizardForm.CancelButton.Height;
  882. OnClick := AbortButtonClick;
  883. end;
  884. SetCtlParent(FAbortButton, Surface);
  885. end;
  886. procedure TDownloadWizardPage.Show;
  887. begin
  888. if WizardForm.CurPageID <> ID then begin
  889. ShowProgressControls(False);
  890. FShowProgressControlsOnNextProgress := True;
  891. end;
  892. inherited;
  893. end;
  894. procedure TDownloadWizardPage.ShowProgressControls(const AVisible: Boolean);
  895. begin
  896. FMsg2Label.Visible := AVisible;
  897. FProgressBar.Visible := AVisible;
  898. FAbortButton.Visible := AVisible;
  899. end;
  900. procedure TDownloadWizardPage.Add(const Url, BaseName, RequiredSHA256OfFile: String);
  901. var
  902. F: TDownloadFile;
  903. begin
  904. F := TDownloadFile.Create;
  905. F.Url := Url;
  906. F.BaseName := BaseName;
  907. F.RequiredSHA256OfFile := RequiredSHA256OfFile;
  908. FFiles.Add(F);
  909. end;
  910. procedure TDownloadWizardPage.Clear;
  911. begin
  912. FFiles.Clear;
  913. end;
  914. function TDownloadWizardPage.Download: Int64;
  915. var
  916. F: TDownloadFile;
  917. I: Integer;
  918. begin
  919. FAbortedByUser := False;
  920. Result := 0;
  921. for I := 0 to FFiles.Count-1 do begin
  922. F := TDownloadFile(FFiles[I]);
  923. { Don't need to set DownloadTemporaryFileProcessMessages before downloading since we already process messages ourselves. }
  924. Result := Result + DownloadTemporaryFile(F.Url, F.BaseName, F.RequiredSHA256OfFile, InternalOnDownloadProgress);
  925. end;
  926. end;
  927. {$ENDIF}
  928. end.