소스 검색

Add new TPathEdit control (also to [Code]) which forces LTR and also auto-enables autocompletion + use it for all our Setup path edits. Fixes WizardForm.DirEdit and others allowing RTL since 6.5.2.

Also link to SHAutoComplete statically since it's available on all supported OSes.

Also cleanup ScriptDlg.
Martijn Laan 1 주 전
부모
커밋
ac593bd72d

+ 25 - 2
Components/NewCtrls.pas

@@ -24,6 +24,13 @@ uses
 type
   TNewEdit = class(TEdit);
 
+  TNewPathEdit = class(TNewEdit)
+  protected
+    procedure CreateWnd; override;
+  public
+    constructor Create(AOwner: TComponent); override;
+  end;
+
   TNewMemo = class(TMemo);
 
   TNewComboBox = class(TComboBox);
@@ -66,15 +73,31 @@ procedure Register;
 implementation
 
 uses
-  CommCtrl, Types,
+  CommCtrl, ShLwApi,
+  Types,
   BidiUtils;
 
 procedure Register;
 begin
-  RegisterComponents('JR', [TNewEdit, TNewMemo, TNewComboBox, TNewListBox,
+  RegisterComponents('JR', [TNewEdit, TNewPathEdit, TNewMemo, TNewComboBox, TNewListBox,
     TNewButton, TNewCheckBox, TNewRadioButton]);
 end;
 
+{ TNewPathEdit }
+
+constructor TNewPathEdit.Create(AOwner: TComponent);
+begin
+  inherited;
+  ParentBidiMode := False;
+  BidiMode := bdLeftToRight;
+end;
+
+procedure TNewPathEdit.CreateWnd;
+begin
+  inherited;
+  SHAutoComplete(Handle, SHACF_FILESYSTEM);
+end;
+
 { TNewButton }
 
 class constructor TNewButton.Create;

+ 11 - 3
Examples/CodeClasses.iss

@@ -117,6 +117,7 @@ var
   Panel: TPanel;
   CheckBox: TNewCheckBox;
   Edit: TNewEdit;
+  PathEdit: TNewPathEdit;
   PasswordEdit: TPasswordEdit;
   Memo: TNewMemo;
   ComboBox: TNewComboBox;
@@ -167,13 +168,20 @@ begin
 
   Edit := TNewEdit.Create(Page);
   Edit.Top := CheckBox.Top + CheckBox.Height + ScaleY(8);
-  Edit.Width := Page.SurfaceWidth div 2 - ScaleX(8);
+  Edit.Width := (Page.SurfaceWidth - 2 * ScaleX(8)) div 3;
   Edit.Text := 'TNewEdit';
   Edit.Parent := Page.Surface;
 
+  PathEdit := TNewPathEdit.Create(Page);
+  PathEdit.Left := Edit.Left + Edit.Width + ScaleX(8);
+  PathEdit.Top := Edit.Top;
+  PathEdit.Width := Edit.Width;
+  PathEdit.Text := ExpandConstant('{sd}\');
+  PathEdit.Parent := Page.Surface;
+
   PasswordEdit := TPasswordEdit.Create(Page);
-  PasswordEdit.Left := Page.SurfaceWidth - Edit.Width;
-  PasswordEdit.Top := CheckBox.Top + CheckBox.Height + ScaleY(8);
+  PasswordEdit.Left := PathEdit.Left + PathEdit.Width + ScaleX(8);
+  PasswordEdit.Top := Edit.Top;
   PasswordEdit.Width := Edit.Width;
   PasswordEdit.Text := 'TPasswordEdit';
   PasswordEdit.Parent := Page.Surface;

+ 6 - 3
ISHelp/isxclasses.pas

@@ -370,6 +370,9 @@ end;
 TNewEdit = class(TEdit)
 end;
 
+TNewPathEdit = class(TNewEdit)
+end;
+
 TCustomMemo = class(TCustomEdit)
   property Lines: TStrings; read write;
 end;
@@ -770,7 +773,7 @@ end;
 TInputDirWizardPage = class(TWizardPage)
   function Add(const APrompt: String): Integer;
   property Buttons[Index: Integer]: TNewButton; read;
-  property Edits[Index: Integer]: TEdit; read;
+  property Edits[Index: Integer]: TNewPathEdit; read;
   property NewFolderName: String; read write;
   property PromptLabels[Index: Integer]: TNewStaticText; read;
   property SubCaptionLabel: TNewStaticText; read;
@@ -780,7 +783,7 @@ end;
 TInputFileWizardPage = class(TWizardPage)
   function Add(const APrompt, AFilter, ADefaultExtension: String): Integer;
   property Buttons[Index: Integer]: TNewButton; read;
-  property Edits[Index: Integer]: TEdit; read;
+  property Edits[Index: Integer]: TNewPathEdit; read;
   property PromptLabels[Index: Integer]: TNewStaticText; read;
   property SubCaptionLabel: TNewStaticText; read;
   property Values[Index: Integer]: String; read write;
@@ -873,7 +876,7 @@ TWizardForm = class(TSetupForm)
   property InstallingPage: TNewNotebookPage; read;
   property InfoAfterPage: TNewNotebookPage; read;
   property DiskSpaceLabel: TNewStaticText; read;
-  property DirEdit: TNewEdit; read;
+  property DirEdit: TNewPathEdit; read;
   property GroupEdit: TNewEdit; read;
   property NoIconsCheck: TNewCheckBox; read;
   property PasswordLabel: TNewStaticText; read;

+ 10 - 9
ISHelp/isxclasses_wordlists_generated.pas

@@ -30,15 +30,16 @@ var
     'TInputQueryWizardPage', 'TKeyEvent', 'TKeyPressEvent', 'TLabel', 'TLinkLabel', 'TListBox',
     'TListBoxStyle', 'TMemo', 'TNewButton', 'TNewCheckBox', 'TNewCheckListBox', 'TNewComboBox',
     'TNewEdit', 'TNewLinkLabel', 'TNewListBox', 'TNewMemo', 'TNewNotebook', 'TNewNotebookPage',
-    'TNewProgressBar', 'TNewProgressBarState', 'TNewProgressBarStyle', 'TNewRadioButton',
-    'TNewStaticText', 'TNotifyEvent', 'TObject', 'TOutputMarqueeProgressWizardPage', 'TOutputMsgMemoWizardPage',
-    'TOutputMsgWizardPage', 'TOutputProgressWizardPage', 'TPanel', 'TPanelBevel', 'TPasswordEdit',
-    'TPen', 'TPenMode', 'TPenStyle', 'TPersistent', 'TPngImage', 'TPopupMode', 'TPosition',
-    'TRadioButton', 'TRichEditViewer', 'TScrollingWinControl', 'TScrollStyle', 'TSetupForm',
-    'TShiftState', 'TSizeConstraints', 'TStartMenuFolderTreeView', 'TStream', 'TStringList',
-    'TStrings', 'TStringStream', 'TStyleElement', 'TStyleElements', 'TSysLinkEvent', 'TSysLinkType',
-    'TUIStateForm', 'TUninstallProgressForm', 'TWinControl', 'TWizardForm', 'TWizardPage',
-    'TWizardPageButtonEvent', 'TWizardPageCancelEvent', 'TWizardPageNotifyEvent', 'TWizardPageShouldSkipEvent'
+    'TNewPathEdit', 'TNewProgressBar', 'TNewProgressBarState', 'TNewProgressBarStyle',
+    'TNewRadioButton', 'TNewStaticText', 'TNotifyEvent', 'TObject', 'TOutputMarqueeProgressWizardPage',
+    'TOutputMsgMemoWizardPage', 'TOutputMsgWizardPage', 'TOutputProgressWizardPage', 'TPanel',
+    'TPanelBevel', 'TPasswordEdit', 'TPen', 'TPenMode', 'TPenStyle', 'TPersistent', 'TPngImage',
+    'TPopupMode', 'TPosition', 'TRadioButton', 'TRichEditViewer', 'TScrollingWinControl',
+    'TScrollStyle', 'TSetupForm', 'TShiftState', 'TSizeConstraints', 'TStartMenuFolderTreeView',
+    'TStream', 'TStringList', 'TStrings', 'TStringStream', 'TStyleElement', 'TStyleElements',
+    'TSysLinkEvent', 'TSysLinkType', 'TUIStateForm', 'TUninstallProgressForm', 'TWinControl',
+    'TWizardForm', 'TWizardPage', 'TWizardPageButtonEvent', 'TWizardPageCancelEvent', 'TWizardPageNotifyEvent',
+    'TWizardPageShouldSkipEvent'
   ];
 
   PascalEnumValues_Isxclasses: array of AnsiString = [

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

@@ -284,6 +284,7 @@ end;
 procedure RegisterNewCtrls_C(Cl: TPSPascalCompiler);
 begin
   Cl.AddClassN(Cl.FindClass('TEdit'), 'TNewEdit');
+  Cl.AddClassN(Cl.FindClass('TNewEdit'), 'TNewPathEdit');
   Cl.AddClassN(Cl.FindClass('TMemo'), 'TNewMemo');
   Cl.AddClassN(Cl.FindClass('TComboBox'), 'TNewComboBox');
   Cl.AddClassN(Cl.FindClass('TListBox'), 'TNewListBox');

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

@@ -45,7 +45,7 @@ type
 implementation
 
 uses
-  Windows, Classes, SysUtils, StrUtils, TypInfo, Graphics, UITypes,
+  Windows, ShLwApi, Classes, SysUtils, StrUtils, TypInfo, Graphics, UITypes,
   ComCtrls, BrowseFunc,
   IDE.MainForm, IDE.ImagesModule, IDE.HelperFunc, IDE.Messages, Shared.CommonFunc, IDE.HtmlHelpFunc;
 
@@ -91,7 +91,7 @@ begin
   MinVerDocBitBtn.OnClick := MinVerDocBitBtnClick;
   MinVerDocBitBtn.Cursor := crHandPoint;
 
-  TryEnableAutoCompleteFileSystem(FileEdit.Handle);
+  SHAutoComplete(FileEdit.Handle, SHACF_FILESYSTEM);
 
   Form.OnAfterMonitorDpiChanged := AfterMonitorDpiChanged;
   UpdateImages;

+ 1 - 1
Projects/Src/Setup.NewDiskForm.dfm

@@ -57,7 +57,7 @@ object NewDiskForm: TNewDiskForm
     TabOrder = 3
     OnClick = BrowseButtonClick
   end
-  object PathEdit: TEdit
+  object PathEdit: TNewPathEdit
     Left = 8
     Top = 96
     Width = 281

+ 1 - 3
Projects/Src/Setup.NewDiskForm.pas

@@ -20,7 +20,7 @@ type
     DiskBitmapImage: TBitmapImage;
     SelectDiskLabel: TNewStaticText;
     PathLabel: TNewStaticText;
-    PathEdit: TEdit;
+    PathEdit: TNewPathEdit;
     BrowseButton: TNewButton;
     OKButton: TNewButton;
     CancelButton: TNewButton;
@@ -80,8 +80,6 @@ begin
 
   DiskBitmapImage.InitializeFromStockIcon(SIID_MEDIABLANKCD, clNone, [48, 64]);
 
-  TryEnableAutoCompleteFileSystem(PathEdit.Handle);
-
   SetForeground := True;
 
   { WizardForm will not exist yet if we're being called from [Code]'s

+ 1 - 0
Projects/Src/Setup.ScriptClasses.pas

@@ -201,6 +201,7 @@ end;
 procedure RegisterNewCtrls_R(Cl: TPSRuntimeClassImporter);
 begin
   Cl.Add(TNewEdit);
+  Cl.Add(TNewPathEdit);
   Cl.Add(TNewMemo);
   Cl.Add(TNewComboBox);
   Cl.Add(TNewListBox);

+ 73 - 104
Projects/Src/Setup.ScriptDlg.pas

@@ -21,8 +21,8 @@ uses
 type
   TInputQueryWizardPage = class(TWizardPage)
     private
-      FEdits: TList;
-      FPromptLabels: TList;
+      FEdits: TList<TPasswordEdit>;
+      FPromptLabels: TList<TNewStaticText>;
       FSubCaptionLabel: TNewStaticText;
       FY: Integer;
       function GetEdit(Index: Integer): TPasswordEdit;
@@ -64,15 +64,15 @@ type
   TInputDirWizardPage = class(TWizardPage)
     private
       FAppendDir: Boolean;
-      FButtons: TList;
-      FEdits: TList;
+      FButtons: TList<TNewButton>;
+      FEdits: TList<TNewPathEdit>;
       FNewFolderName: String;
-      FPromptLabels: TList;
+      FPromptLabels: TList<TNewStaticText>;
       FSubCaptionLabel: TNewStaticText;
       FY: Integer;
       procedure ButtonClick(Sender: TObject);
       function GetButton(Index: Integer): TNewButton;
-      function GetEdit(Index: Integer): TEdit;
+      function GetEdit(Index: Integer): TNewPathEdit;
       function GetPromptLabel(Index: Integer): TNewStaticText;
       function GetValue(Index: Integer): String;
       procedure SetValue(Index: Integer; const Value: String);
@@ -83,7 +83,7 @@ type
       destructor Destroy; override;
       function Add(const APrompt: String): Integer;
       property Buttons[Index: Integer]: TNewButton read GetButton;
-      property Edits[Index: Integer]: TEdit read GetEdit;
+      property Edits[Index: Integer]: TNewPathEdit read GetEdit;
       procedure Initialize(const SubCaption: String; const AppendDir: Boolean;
         const NewFolderName: String);
       property PromptLabels[Index: Integer]: TNewStaticText read GetPromptLabel;
@@ -95,16 +95,16 @@ type
 
   TInputFileWizardPage = class(TWizardPage)
     private
-      FButtons: TList;
-      FEdits: TList;
+      FButtons: TList<TNewButton>;
+      FEdits: TList<TNewPathEdit>;
       FInputFileDefaultExtensions: TStringList;
       FInputFileFilters: TStringList;
-      FPromptLabels: TList;
+      FPromptLabels: TList<TNewStaticText>;
       FSubCaptionLabel: TNewStaticText;
       FY: Integer;
       procedure ButtonClick(Sender: TObject);
       function GetButton(Index: Integer): TNewButton;
-      function GetEdit(Index: Integer): TEdit;
+      function GetEdit(Index: Integer): TNewPathEdit;
       function GetPromptLabel(Index: Integer): TNewStaticText;
       function GetValue(Index: Integer): String;
       procedure SetValue(Index: Integer; const Value: String);
@@ -115,7 +115,7 @@ type
       destructor Destroy; override;
       function Add(const APrompt, AFilter, ADefaultExtension: String): Integer;
       property Buttons[Index: Integer]: TNewButton read GetButton;
-      property Edits[Index: Integer]: TEdit read GetEdit;
+      property Edits[Index: Integer]: TNewPathEdit read GetEdit;
       procedure Initialize(const SubCaption: String);
       property PromptLabels[Index: Integer]: TNewStaticText read GetPromptLabel;
       property Values[Index: Integer]: String read GetValue write SetValue;
@@ -305,8 +305,8 @@ end;
 constructor TInputQueryWizardPage.Create(AOwner: TComponent);
 begin
   inherited;
-  FEdits := TList.Create;
-  FPromptLabels := TList.Create;
+  FEdits := TList<TPasswordEdit>.Create;
+  FPromptLabels := TList<TNewStaticText>.Create;
 end;
 
 destructor TInputQueryWizardPage.Destroy;
@@ -332,10 +332,8 @@ end;
 
 function TInputQueryWizardPage.Add(const APrompt: String;
   const APassword: Boolean): Integer;
-var
-  PromptLabel: TNewStaticText;
-  Edit: TPasswordEdit;
 begin
+  var PromptLabel: TNewStaticText;
   if APrompt <> '' then begin
     PromptLabel := TNewStaticText.Create(Self);
     with PromptLabel do begin
@@ -351,7 +349,7 @@ begin
   end else
     PromptLabel := nil;
 
-  Edit := TPasswordEdit.Create(Self);
+  const Edit = TPasswordEdit.Create(Self);
   with Edit do begin
     Password := APassword;
     Top := FY;
@@ -369,12 +367,12 @@ end;
 
 function TInputQueryWizardPage.GetEdit(Index: Integer): TPasswordEdit;
 begin
-  Result := TPasswordEdit(FEdits[Index]);
+  Result := FEdits[Index];
 end;
 
 function TInputQueryWizardPage.GetPromptLabel(Index: Integer): TNewStaticText;
 begin
-  Result := TNewStaticText(FPromptLabels[Index]);
+  Result := FPromptLabels[Index];
 end;
 
 function TInputQueryWizardPage.GetValue(Index: Integer): String;
@@ -391,8 +389,6 @@ end;
 
 procedure TInputOptionWizardPage.Initialize(const SubCaption: String;
   const Exclusive, ListBox: Boolean);
-var
-  CaptionYDiff: Integer;
 begin
   FSubCaptionLabel := TNewStaticText.Create(Self);
   with SubCaptionLabel do begin
@@ -403,7 +399,7 @@ begin
     Caption := SubCaption;
   end;
   SetCtlParent(FSubCaptionLabel, Surface);
-  CaptionYDiff := WizardForm.AdjustLabelHeight(SubCaptionLabel);
+  const CaptionYDiff = WizardForm.AdjustLabelHeight(SubCaptionLabel);
 
   FCheckListBox := TNewCheckListBox.Create(Self);
   with FCheckListBox do begin
@@ -439,10 +435,8 @@ begin
 end;
 
 function TInputOptionWizardPage.GetSelectedValueIndex: Integer;
-var
-  I: Integer;
 begin
-  for I := 0 to FCheckListBox.Items.Count-1 do
+  for var I := 0 to FCheckListBox.Items.Count-1 do
     if (FCheckListBox.ItemLevel[I] = 0) and FCheckListBox.Checked[I] then begin
       Result := I;
       Exit;
@@ -456,10 +450,8 @@ begin
 end;
 
 procedure TInputOptionWizardPage.SetSelectedValueIndex(Value: Integer);
-var
-  I: Integer;
 begin
-  for I := 0 to FCheckListBox.Items.Count-1 do
+  for var I := 0 to FCheckListBox.Items.Count-1 do
     if FCheckListBox.ItemLevel[I] = 0 then
       FCheckListBox.Checked[I] := (I = Value);
 end;
@@ -474,9 +466,9 @@ end;
 constructor TInputDirWizardPage.Create(AOwner: TComponent);
 begin
   inherited;
-  FButtons := TList.Create;
-  FEdits := TList.Create;
-  FPromptLabels := TList.Create;
+  FButtons := TList<TNewButton>.Create;
+  FEdits := TList<TNewPathEdit>.Create;
+  FPromptLabels := TList<TNewStaticText>.Create;
 end;
 
 destructor TInputDirWizardPage.Destroy;
@@ -488,27 +480,22 @@ begin
 end;
 
 procedure TInputDirWizardPage.ButtonClick(Sender: TObject);
-var
-  I: Integer;
-  Edit: TEdit;
-  S: String;
-begin
-  I := FButtons.IndexOf(Sender);
-  if I <> -1 then begin
-    Edit := TEdit(FEdits[I]);
-    S := Edit.Text;
-    if ShowSelectFolderDialog(False, FAppendDir, S, FNewFolderName) then
-      Edit.Text := S;
+begin
+  if Sender is TNewButton then begin
+    const I = FButtons.IndexOf(Sender as TNewButton);
+    if I <> -1 then begin
+      const Edit = FEdits[I];
+      var S: String := Edit.Text;
+      if ShowSelectFolderDialog(False, FAppendDir, S, FNewFolderName) then
+        Edit.Text := S;
+    end;
   end;
 end;
 
 procedure TInputDirWizardPage.NextButtonClick(var Continue: Boolean);
-var
-  I: Integer;
-  Edit: TEdit;
 begin
-  for I := 0 to FEdits.Count-1 do begin
-    Edit := FEdits[I];
+  for var I := 0 to FEdits.Count-1 do begin
+    const Edit = FEdits[I];
     if not ValidateCustomDirEdit(Edit, True, True, True) then begin
       if WizardForm.Visible then
         Edit.SetFocus;
@@ -538,14 +525,10 @@ begin
 end;
 
 function TInputDirWizardPage.Add(const APrompt: String): Integer;
-var
-  ButtonWidth: Integer;
-  PromptLabel: TNewStaticText;
-  Edit: TEdit;
-  Button: TNewButton;
 begin
-  ButtonWidth := WizardForm.CalculateButtonWidth([SetupMessages[msgButtonWizardBrowse]]);
+  const ButtonWidth = WizardForm.CalculateButtonWidth([SetupMessages[msgButtonWizardBrowse]]);
 
+  var PromptLabel: TNewStaticText;
   if APrompt <> '' then begin
     PromptLabel := TNewStaticText.Create(Self);
     with PromptLabel do begin
@@ -561,18 +544,17 @@ begin
   end else
     PromptLabel := nil;
 
-  Edit := TEdit.Create(Self);
+  const Edit = TNewPathEdit.Create(Self);
   with Edit do begin
     Top := FY;
     Width := SurfaceWidth-ButtonWidth-WizardForm.ScalePixelsX(10);
   end;
   SetCtlParentAtBack(Edit, Surface);
-  TryEnableAutoCompleteFileSystem(Edit.Handle);
 
   if PromptLabel <> nil then
     PromptLabel.FocusControl := Edit;
 
-  Button := TNewButton.Create(Self);
+  const Button = TNewButton.Create(Self);
   with Button do begin
     Left := SurfaceWidth-ButtonWidth;
     Top := Edit.Top-1;
@@ -595,17 +577,17 @@ end;
 
 function TInputDirWizardPage.GetButton(Index: Integer): TNewButton;
 begin
-  Result := TNewButton(FButtons[Index]);
+  Result := FButtons[Index];
 end;
 
-function TInputDirWizardPage.GetEdit(Index: Integer): TEdit;
+function TInputDirWizardPage.GetEdit(Index: Integer): TNewPathEdit;
 begin
-  Result := TEdit(FEdits[Index]);
+  Result := FEdits[Index];
 end;
 
 function TInputDirWizardPage.GetPromptLabel(Index: Integer): TNewStaticText;
 begin
-  Result := TNewStaticText(FPromptLabels[Index]);
+  Result := FPromptLabels[Index];
 end;
 
 function TInputDirWizardPage.GetValue(Index: Integer): String;
@@ -623,11 +605,11 @@ end;
 constructor TInputFileWizardPage.Create(AOwner: TComponent);
 begin
   inherited;
-  FButtons := TList.Create;
-  FEdits := TList.Create;
+  FButtons := TList<TNewButton>.Create;
+  FEdits := TList<TNewPathEdit>.Create;
   FInputFileDefaultExtensions := TStringList.Create;
   FInputFileFilters := TStringList.Create;
-  FPromptLabels := TList.Create;
+  FPromptLabels := TList<TNewStaticText>.Create;
 end;
 
 destructor TInputFileWizardPage.Destroy;
@@ -641,22 +623,20 @@ begin
 end;
 
 procedure TInputFileWizardPage.ButtonClick(Sender: TObject);
-var
-  I: Integer;
-  Edit: TEdit;
-  FileName: String;
-begin
-  I := FButtons.IndexOf(Sender);
-  if I <> -1 then begin
-    Edit := TEdit(FEdits[I]);
-    FileName := Edit.Text;
-    if (not IsSaveButton[I] and NewGetOpenFileName(RemoveAccelChar(SetupMessages[msgButtonWizardBrowse]),
-        FileName, PathExtractPath(FileName), FInputFileFilters[I],
-        FInputFileDefaultExtensions[I], Surface.Handle)) or
-       (IsSaveButton[I] and NewGetSaveFileName(RemoveAccelChar(SetupMessages[msgButtonWizardBrowse]),
-        FileName, PathExtractPath(FileName), FInputFileFilters[I],
-        FInputFileDefaultExtensions[I], Surface.Handle)) then
-      Edit.Text := FileName;
+begin
+  if Sender is TNewButton then begin
+    const I = FButtons.IndexOf(Sender as TNewButton);
+    if I <> -1 then begin
+      const Edit = FEdits[I];
+      var FileName: String := Edit.Text;
+      if (not IsSaveButton[I] and NewGetOpenFileName(RemoveAccelChar(SetupMessages[msgButtonWizardBrowse]),
+          FileName, PathExtractPath(FileName), FInputFileFilters[I],
+          FInputFileDefaultExtensions[I], Surface.Handle)) or
+         (IsSaveButton[I] and NewGetSaveFileName(RemoveAccelChar(SetupMessages[msgButtonWizardBrowse]),
+          FileName, PathExtractPath(FileName), FInputFileFilters[I],
+          FInputFileDefaultExtensions[I], Surface.Handle)) then
+        Edit.Text := FileName;
+    end;
   end;
 end;
 
@@ -676,14 +656,10 @@ end;
 
 function TInputFileWizardPage.Add(const APrompt, AFilter,
   ADefaultExtension: String): Integer;
-var
-  ButtonWidth: Integer;
-  PromptLabel: TNewStaticText;
-  Edit: TEdit;
-  Button: TNewButton;
 begin
-  ButtonWidth := WizardForm.CalculateButtonWidth([SetupMessages[msgButtonWizardBrowse]]);
+  const ButtonWidth = WizardForm.CalculateButtonWidth([SetupMessages[msgButtonWizardBrowse]]);
 
+  var PromptLabel: TNewStaticText;
   if APrompt <> '' then begin
     PromptLabel := TNewStaticText.Create(Self);
     with PromptLabel do begin
@@ -699,18 +675,17 @@ begin
   end else
     PromptLabel := nil;
 
-  Edit := TEdit.Create(Self);
+  const Edit = TNewPathEdit.Create(Self);
   with Edit do begin
     Top := FY;
     Width := SurfaceWidth-ButtonWidth-WizardForm.ScalePixelsX(10);
   end;
   SetCtlParentAtBack(Edit, Surface);
-  TryEnableAutoCompleteFileSystem(Edit.Handle);
 
   if PromptLabel <> nil then
     PromptLabel.FocusControl := Edit;
 
-  Button := TNewButton.Create(Self);
+  const Button = TNewButton.Create(Self);
   with Button do begin
     Left := SurfaceWidth-ButtonWidth;
     Top := Edit.Top-1;
@@ -735,17 +710,17 @@ end;
 
 function TInputFileWizardPage.GetButton(Index: Integer): TNewButton;
 begin
-  Result := TNewButton(FButtons[Index]);
+  Result := FButtons[Index];
 end;
 
-function TInputFileWizardPage.GetEdit(Index: Integer): TEdit;
+function TInputFileWizardPage.GetEdit(Index: Integer): TNewPathEdit;
 begin
-  Result := TEdit(FEdits[Index]);
+  Result := FEdits[Index];
 end;
 
 function TInputFileWizardPage.GetPromptLabel(Index: Integer): TNewStaticText;
 begin
-  Result := TNewStaticText(FPromptLabels[Index]);
+  Result := FPromptLabels[Index];
 end;
 
 function TInputFileWizardPage.GetValue(Index: Integer): String;
@@ -791,10 +766,8 @@ end;
 {--- OutputMsgMemo ---}
 
 procedure TOutputMsgMemoWizardPage.Initialize(const SubCaption: String; const Msg: AnsiString);
-var
-  Y: Integer;
 begin
-  Y := 0;
+  var Y := 0;
   if SubCaption <> '' then begin
     FSubCaptionLabel := TNewStaticText.Create(Self);
     with FSubCaptionLabel do begin
@@ -920,12 +893,10 @@ procedure OutputProgressWizardPageMessageBoxCallback(const Flags: LongInt; const
 const
   States: array [TNewProgressBarState] of TTaskbarProgressState =
     (tpsNormal, tpsError, tpsPaused);
-var
-  OutputProgressWizardPage: TOutputProgressWizardPage;
-  NewState: TNewProgressBarState;
 begin
-  OutputProgressWizardPage := TOutputProgressWizardPage(Param);
+  const OutputProgressWizardPage = TOutputProgressWizardPage(Param);
 
+  var NewState: TNewProgressBarState;
   if After then
     NewState := npbsNormal
   else if (Flags and MB_ICONSTOP) <> 0 then
@@ -981,14 +952,13 @@ begin
 end;
 
 function TDownloadWizardPage.InternalOnDownloadProgress(const Url, BaseName: string; const Progress, ProgressMax: Int64): Boolean;
-var
-  Progress32, ProgressMax32: Integer;
 begin
   if FAbortedByUser then begin
     Log('Need to abort download.');
     Result := False;
   end else begin
     FMsg2Label.Caption := IfThen(FShowBaseNameInsteadOfUrl, PathExtractName(BaseName), Url);
+    var Progress32, ProgressMax32: Integer;
     if ProgressMax > MaxInt then begin
       Progress32 := Integer(Round((Progress / ProgressMax) * MaxInt));
       ProgressMax32 := MaxInt;
@@ -1203,8 +1173,6 @@ begin
 end;
 
 function TExtractionWizardPage.InternalOnExtractionProgress(const ArchiveName, FileName: string; const Progress, ProgressMax: Int64): Boolean;
-var
-  Progress32, ProgressMax32: Integer;
 begin
   if FAbortedByUser then begin
     Log('Need to abort extraction.');
@@ -1213,6 +1181,7 @@ begin
     { Unlike TDownloadWizardPage we don't log progress here. This is because 7zMain.c already logs output dirs and names. }
 
     FMsg2Label.Caption := IfThen(FShowArchiveInsteadOfFile, ArchiveName, FileName);
+    var Progress32, ProgressMax32: Integer;
     if ProgressMax > MaxInt then begin
       Progress32 := Integer(Round((Progress / ProgressMax) * MaxInt));
       ProgressMax32 := MaxInt;

+ 1 - 1
Projects/Src/Setup.SelectFolderForm.dfm

@@ -53,7 +53,7 @@ object SelectFolderForm: TSelectFolderForm
     TabOrder = 2
     OnClick = NewFolderButtonClick
   end
-  object PathEdit: TEdit
+  object PathEdit: TNewPathEdit
     Left = 16
     Top = 36
     Width = 317

+ 2 - 3
Projects/Src/Setup.SelectFolderForm.pas

@@ -18,7 +18,7 @@ uses
 type
   TSelectFolderForm = class(TSetupForm)
     BrowseLabel: TNewStaticText;
-    PathEdit: TEdit;
+    PathEdit: TNewPathEdit;
     NewFolderButton: TNewButton;
     OKButton: TNewButton;
     CancelButton: TNewButton;
@@ -41,7 +41,7 @@ implementation
 
 uses
   PathFunc, SetupLdrAndSetup.Messages, Shared.SetupMessageIDs, Setup.MainFunc,
-  Shared.SetupTypes, Setup.WizardForm, Shared.CommonFunc, Shared.CommonFunc.Vcl;
+  Shared.SetupTypes, Setup.WizardForm, Shared.CommonFunc.Vcl;
 
 {$R *.DFM}
 
@@ -123,7 +123,6 @@ begin
   YDiff := WizardForm.AdjustLabelHeight(BrowseLabel);
   ClientHeight := ClientHeight + YDiff;  { moves buttons down due to their anchors }
   PathEdit.Top := PathEdit.Top + YDiff;
-  TryEnableAutoCompleteFileSystem(PathEdit.Handle);
   FFolderTreeView.Top := FFolderTreeView.Top + YDiff;
   FFolderTreeView.Height := FFolderTreeView.Height - YDiff;
   NewFolderButton.Caption := SetupMessages[msgButtonNewFolder];

+ 1 - 1
Projects/Src/Setup.WizardForm.dfm

@@ -350,7 +350,7 @@ object WizardForm: TWizardForm
             TabOrder = 3
             OnClick = DirBrowseButtonClick
           end
-          object FDirEdit: TNewEdit
+          object FDirEdit: TNewPathEdit
             Left = 0
             Top = 68
             Width = 397

+ 2 - 3
Projects/Src/Setup.WizardForm.pas

@@ -103,7 +103,7 @@ type
     FInstallingPage: TNewNotebookPage;
     FInfoAfterPage: TNewNotebookPage;
     FDiskSpaceLabel: TNewStaticText;
-    FDirEdit: TNewEdit;
+    FDirEdit: TNewPathEdit;
     FGroupEdit: TNewEdit;
     FNoIconsCheck: TNewCheckBox;
     FPasswordLabel: TNewStaticText;
@@ -266,7 +266,7 @@ type
     property InstallingPage: TNewNotebookPage read FInstallingPage;
     property InfoAfterPage: TNewNotebookPage read FInfoAfterPage;
     property DiskSpaceLabel: TNewStaticText read FDiskSpaceLabel;
-    property DirEdit: TNewEdit read FDirEdit;
+    property DirEdit: TNewPathEdit read FDirEdit;
     property GroupEdit: TNewEdit read FGroupEdit;
     property NoIconsCheck: TNewCheckBox read FNoIconsCheck;
     property PasswordLabel: TNewStaticText read FPasswordLabel;
@@ -1014,7 +1014,6 @@ begin
   SelectDirBrowseLabel.Top := SelectDirBrowseLabel.Top + I;
   Inc(I, AdjustLabelHeight(SelectDirBrowseLabel));
   DirEdit.Top := DirEdit.Top + I;
-  TryEnableAutoCompleteFileSystem(DirEdit.Handle);
   DirBrowseButton.Caption := SetupMessages[msgButtonWizardBrowse];
   X := CalculateButtonWidth([SetupMessages[msgButtonWizardBrowse]]);
   DirBrowseButton.SetBounds(InnerNotebook.Width - X,

+ 1 - 23
Projects/Src/Shared.CommonFunc.pas

@@ -168,7 +168,6 @@ function ShutdownBlockReasonDestroy(Wnd: HWND): Boolean;
 function TryStrToBoolean(const S: String; var BoolResult: Boolean): Boolean;
 procedure WaitMessageWithTimeout(const Milliseconds: DWORD);
 function MoveFileReplace(const ExistingFileName, NewFileName: String): Boolean;
-procedure TryEnableAutoCompleteFileSystem(Wnd: HWND);
 procedure CreateMutex(const MutexName: String);
 function HighContrastActive: Boolean;
 function CurrentWindowsVersionAtLeast(const AMajor, AMinor: Byte; const ABuild: Word = 0): Boolean;
@@ -184,6 +183,7 @@ function StrToWnd(const S: String): HWND;
 implementation
 
 uses
+  ShLwApi,
   PathFunc, UnsignedFunc;
 
 { Avoid including Variants (via ActiveX and ShlObj) in SetupLdr (SetupLdr uses CmnFunc2), saving 26 KB. }
@@ -1586,28 +1586,6 @@ begin
     MOVEFILE_REPLACE_EXISTING);
 end;
 
-var
-  SHAutoCompleteInitialized: Boolean;
-  SHAutoCompleteFunc: function(hwndEdit: HWND; dwFlags: dWord): LongInt; stdcall;
-
-procedure TryEnableAutoCompleteFileSystem(Wnd: HWND);
-const
-  SHACF_FILESYSTEM = $1;
-var
-  M: HMODULE;
-begin
-  if not SHAutoCompleteInitialized then begin
-    M := SafeLoadLibrary(AddBackslash(GetSystemDir) + 'shlwapi.dll',
-      SEM_NOOPENFILEERRORBOX);
-    if M <> 0 then
-      SHAutoCompleteFunc := GetProcAddress(M, 'SHAutoComplete');
-    SHAutoCompleteInitialized := True;
-  end;
-
-  if Assigned(SHAutoCompleteFunc) then
-    SHAutoCompleteFunc(Wnd, SHACF_FILESYSTEM);
-end;
-
 procedure CreateMutex(const MutexName: String);
 const
   SECURITY_DESCRIPTOR_REVISION = 1;  { Win32 constant not defined in Delphi 3 }

+ 8 - 0
whatsnew.htm

@@ -123,6 +123,14 @@ For conditions of distribution and use, see <a href="files/is/license.txt">LICEN
     <li>Ctrl+W now closes the current tab (in addition to Ctrl+F4), consistent with other modern editors. Previously, Ctrl+W was assigned to <i>Target Uninstall</i> in the <i>Run</i> menu, which is now reassigned to Alt+Q.</li>
   </ul>
   </li>
+  <li><i>Fix:</i> File and directory controls in Setup should always use left-to-right reading order, even when a right-to-left language is active, but this has not been the case since version 6.5.2.</li>
+  <li>Pascal Scripting:
+  <ul>
+    <li>Added support class <tt>TNewPathEdit</tt>, a <tt>TNewEdit</tt> descendant that always uses left-to-right reading order and provides filesystem autocompletion.<br/>
+        You should use <tt>TNewPathEdit</tt> instead of <tt>TNewEdit</tt> for file and directory controls, but using <tt>TInputFileWizardPage</tt> and <tt>TInputDirWizardPage</tt> instead is still recommended.
+    </li>
+  </ul>
+  </li>
   <li>Other minor improvements.</li>
 </ul>