浏览代码

Bug 1614: Simple input boxes (like "Edit File" dialog) are broken on multi monitor systems with different DPI

https://winscp.net/tracker/1614

Reimplemented InputDialog using "custom dialogs" to reduce code redundancy

Source commit: 4c9070be7a35691de6b3826ff0d489f3c946a839
Martin Prikryl 7 年之前
父节点
当前提交
9fea030558
共有 1 个文件被更改,包括 94 次插入153 次删除
  1. 94 153
      source/forms/InputDlg.cpp

+ 94 - 153
source/forms/InputDlg.cpp

@@ -9,189 +9,130 @@
 #include <HistoryComboBox.hpp>
 #include <PasTools.hpp>
 #include <PasswordEdit.hpp>
+#include <Custom.h>
 //---------------------------------------------------------------------------
 #pragma package(smart_init)
 //---------------------------------------------------------------------------
-struct TInputDialogToken
+class TInputDialog : public TCustomDialog
 {
-  TInputDialogInitialize OnInitialize;
-  TInputDialogData Data;
-  TWinControl * EditControl;
-  bool PathInput;
+public:
+  __fastcall TInputDialog(
+    const UnicodeString & ACaption, const UnicodeString & Prompt, const UnicodeString & HelpKeyword,
+    TStrings * History, bool PathInput, TInputDialogInitialize OnInitialize, bool Echo);
+
+  bool __fastcall Execute(UnicodeString & Value);
+
+protected:
+  DYNAMIC void __fastcall DoShow();
+
+private:
+  bool FPathInput;
+  TInputDialogInitialize FOnInitialize;
+  TStrings * FHistory;
+  TCustomEdit * Edit;
+  THistoryComboBox * HistoryCombo;
 };
 //---------------------------------------------------------------------------
-void __fastcall InputDialogHelp(void * /*Data*/, TObject * Sender)
+__fastcall TInputDialog::TInputDialog(
+  const UnicodeString & ACaption, const UnicodeString & Prompt, const UnicodeString & HelpKeyword,
+  TStrings * History, bool PathInput, TInputDialogInitialize OnInitialize, bool Echo) :
+  TCustomDialog(HelpKeyword)
 {
-  TControl * Control = dynamic_cast<TControl *>(Sender);
-  Application->HelpKeyword(Control->Parent->HelpKeyword);
-}
-//---------------------------------------------------------------------------
-void __fastcall InputDialogShow(void * Data, TObject * Sender)
-{
-  TInputDialogToken & Token = *static_cast<TInputDialogToken *>(Data);
+  Caption = ACaption;
+  FPathInput = PathInput;
+  FOnInitialize = OnInitialize;
+  FHistory = History;
+
+  ClientWidth = ScaleByTextHeight(this, 275);
 
-  if (Token.OnInitialize != NULL)
+  TLabel * Label = CreateLabel(Prompt);
+  if (History == NULL)
   {
-    Token.OnInitialize(Sender, &Token.Data);
+    if (Echo)
+    {
+      Edit = new TEdit(this);
+    }
+    else
+    {
+      Edit = new TPasswordEdit(this);
+    }
+    HistoryCombo = NULL;
+    AddEditLikeControl(Edit, Label);
+    reinterpret_cast<TEdit *>(Edit)->MaxLength = 255;
   }
-
-  if (Token.PathInput)
+  else
   {
-    InstallPathWordBreakProc(Token.EditControl);
+    DebugAssert(Echo);
+    HistoryCombo = new THistoryComboBox(this);
+    AddEditLikeControl(HistoryCombo, Label);
+    HistoryCombo->MaxLength = 255;
+    HistoryCombo->AutoComplete = false;
+    Edit = NULL;
   }
 }
 //---------------------------------------------------------------------------
-bool __fastcall InputDialog(const UnicodeString ACaption,
-  const UnicodeString APrompt, UnicodeString & Value, UnicodeString HelpKeyword,
-  TStrings * History, bool PathInput, TInputDialogInitialize OnInitialize, bool Echo)
+void __fastcall TInputDialog::DoShow()
 {
-  bool Result = False;
-  TInputDialogToken Token;
-  TForm * Form = new TForm(GetFormOwner(), 0); // bypass the VCL streaming (for Salamander)
-  try
-  {
-    // salam needs to override this in UseSystemSettings
-    Form->Position = poOwnerFormCenter;
-    SetCorrectFormParent(Form);
-    UseSystemSettingsPre(Form);
+  TCustomDialog::DoShow();
 
-    // this is what TCustomForm.Loaded does
-    // Note that this is not needed as due to use of an alternative constructor above
-    // we are already set to default font
-    // See TMessageForm::Create for contrary
-    Form->Font->Assign(Application->DefaultFont);
-    Form->ParentFont = true;
-
-    Token.OnInitialize = OnInitialize;
-    Token.PathInput = PathInput;
-
-    TNotifyEvent OnShow;
-    ((TMethod *)&OnShow)->Data = &Token;
-    ((TMethod *)&OnShow)->Code = InputDialogShow;
-    Form->OnShow = OnShow;
-
-    Form->Canvas->Font = Form->Font;
-    Form->BorderStyle = bsDialog;
-    Form->Caption = ACaption;
-    Form->ClientWidth = ScaleByTextHeightRunTime(Form, 275);
-    Form->ClientHeight = ScaleByTextHeightRunTime(Form, 102);
-    if (!HelpKeyword.IsEmpty())
-    {
-      Form->HelpKeyword = HelpKeyword;
-
-      Form->BorderIcons = TBorderIcons(Form->BorderIcons) << biHelp;
-    }
-
-    TLabel * Prompt = new TLabel(Form);
-    Prompt->Parent = Form;
-    Prompt->AutoSize = True;
-    Prompt->Left = ScaleByTextHeightRunTime(Form, 10);
-    Prompt->Top = ScaleByTextHeightRunTime(Form, 13);
-    Prompt->Caption = APrompt;
+  if (FOnInitialize != NULL)
+  {
+    TInputDialogData Data;
+    Data.Edit = Edit;
+    FOnInitialize(this, &Data);
+  }
 
-    TCustomEdit * Edit;
-    THistoryComboBox * HistoryCombo;
-    if (History == NULL)
+  if (FPathInput)
+  {
+    if (FHistory == NULL)
     {
-      if (Echo)
-      {
-        Edit = new TEdit(Form);
-      }
-      else
-      {
-        Edit = new TPasswordEdit(Form);
-      }
-      Edit->Parent = Form;
-      Edit->Text = Value;
-      Edit->SelectAll();
-      reinterpret_cast<TEdit *>(Edit)->MaxLength = 255;
-      Token.Data.Edit = Edit;
-      Token.EditControl = Edit;
+      InstallPathWordBreakProc(Edit);
     }
     else
     {
-      DebugAssert(Echo);
-      HistoryCombo = new THistoryComboBox(Form);
-      HistoryCombo->Parent = Form;
-      HistoryCombo->Text = Value;
-      HistoryCombo->SelectAll();
-      HistoryCombo->Items = History;
-      HistoryCombo->MaxLength = 255;
-      HistoryCombo->AutoComplete = false;
-      Token.EditControl = HistoryCombo;
+      InstallPathWordBreakProc(HistoryCombo);
     }
-    Token.EditControl->Left = Prompt->Left;
-    Token.EditControl->Top = ScaleByTextHeightRunTime(Form, 30);
-    Token.EditControl->Width = ScaleByTextHeightRunTime(Form, 255);
-
-    Prompt->FocusControl = Token.EditControl;
-
-    int ButtonTop = ScaleByTextHeightRunTime(Form, 66);
-    int ButtonSpace = ScaleByTextHeightRunTime(Form, 6);
+  }
+}
+//---------------------------------------------------------------------------
+bool __fastcall TInputDialog::Execute(UnicodeString & Value)
+{
+  if (FHistory == NULL)
+  {
+    Edit->Text = Value;
+    Edit->SelectAll();
+  }
+  else
+  {
+    HistoryCombo->Items = FHistory;
+    HistoryCombo->Text = Value;
+    HistoryCombo->SelectAll();
+  }
 
-    TButton * Button;
-    Button = new TButton(Form);
-    Button->Parent = Form;
-    Button->Caption = Vcl_Consts_SMsgDlgOK;
-    Button->ModalResult = mrOk;
-    Button->Default = True;
+  bool Result = TCustomDialog::Execute();
 
-    int ButtonHeight = ScaleByTextHeightRunTime(Button, Button->Height);
-    int ButtonWidth = ScaleByTextHeightRunTime(Button, Button->Width);
-    int ButtonsStart;
-    if (HelpKeyword.IsEmpty())
+  if (Result)
+  {
+    if (FHistory != NULL)
     {
-      ButtonsStart = (Form->ClientWidth / 2) - ButtonWidth - (ButtonSpace / 2);
+      HistoryCombo->SaveToHistory();
+      FHistory->Assign(HistoryCombo->Items);
+      Value = HistoryCombo->Text;
     }
     else
     {
-      ButtonsStart = (Form->ClientWidth / 2) - (3 * ButtonWidth / 2) - ButtonSpace;
-    }
-
-    Button->SetBounds(ButtonsStart, ButtonTop, ButtonWidth, ButtonHeight);
-
-    Button = new TButton(Form);
-    Button->Parent = Form;
-    Button->Caption = Vcl_Consts_SMsgDlgCancel;
-    Button->ModalResult = mrCancel;
-    Button->Cancel = True;
-    Button->SetBounds(ButtonsStart + ButtonWidth + ButtonSpace, ButtonTop,
-      ButtonWidth, ButtonHeight);
-
-    if (!HelpKeyword.IsEmpty())
-    {
-      Button = new TButton(Form);
-      Button->Parent = Form;
-      Button->Caption = Vcl_Consts_SMsgDlgHelp;
-      Button->ModalResult = mrNone;
-      Button->SetBounds(ButtonsStart + 2 * (ButtonWidth + ButtonSpace), ButtonTop,
-        ButtonWidth, ButtonHeight);
-      TNotifyEvent OnClick;
-      ((TMethod*)&OnClick)->Code = InputDialogHelp;
-      Button->OnClick = OnClick;
-    }
-
-    UseSystemSettingsPost(Form);
-
-    if (Form->ShowModal() == DefaultResult(Form))
-    {
-      if (History != NULL)
-      {
-        HistoryCombo->SaveToHistory();
-        History->Assign(HistoryCombo->Items);
-        Value = HistoryCombo->Text;
-      }
-      else
-      {
-        Value = Edit->Text;
-      }
-      Result = true;
+      Value = Edit->Text;
     }
   }
-  __finally
-  {
-    delete Form;
-  }
+
   return Result;
 }
 //---------------------------------------------------------------------------
+bool __fastcall InputDialog(const UnicodeString ACaption,
+  const UnicodeString APrompt, UnicodeString & Value, UnicodeString HelpKeyword,
+  TStrings * History, bool PathInput, TInputDialogInitialize OnInitialize, bool Echo)
+{
+  std::unique_ptr<TInputDialog> Dialog(new TInputDialog(ACaption, APrompt, HelpKeyword, History, PathInput, OnInitialize, Echo));
+  return Dialog->Execute(Value);
+}
+//---------------------------------------------------------------------------