如何将结果编码为组合框中的选择?

How to code a result to a selection from a combobox?

我在 Delphi 10.3 中有一个 TComboBox。我有一个包含 30 多个项目的组合框。我需要为组合框的每个项目编写不同的操作。目前我正在使用 if-else 语句。由于有 30 个不同的项目,if 语句会太长。有没有更快的方法来做到这一点?

这个完全取决于你的情况。在不知道您的确切情况的情况下几乎不可能回答您的问题。

不过,这里有一些想法。也许他们与你的情况有关,也许他们不是。

索引的简单参数化

在最好的情况下,您的 30 个动作可以被参数化。例如,假设组合框的项目是

Show 1
Show 10
Show 100
Show 1000
...

这将显示一个带有给定数字的消息框。在这种情况下,您不需要 30 个不同的过程(这里每个过程都由对 ShowMessage 的简单调用表示):

procedure TForm1.btnNextClick(Sender: TObject);
begin
  case ComboBox1.ItemIndex of
    0:
      ShowMessage('1');
    1:
      ShowMessage('10');
    2:
      ShowMessage('100');
    3:
      ShowMessage('1000');
    // ...
  end;
end;

相反,您应该只使用一个过程,但带有一个参数:

procedure TForm1.btnNextClick(Sender: TObject);
begin
  if ComboBox1.ItemIndex <> -1 then
    ShowMessage(IntPower(10, ComboBox1.ItemIndex).ToString)
end;

关联对象的参数化

如果不能单独通过项目的索引来描述操作,您可以使用与每个项目关联的对象指针。也许用它来存储一个整数就足够了:

procedure TForm1.FormCreate(Sender: TObject);
begin
  ComboBox1.Items.BeginUpdate;
  try
    ComboBox1.Items.Clear;
    ComboBox1.Items.AddObject('Show 51', TObject(51));
    ComboBox1.Items.AddObject('Show 111', TObject(111));
    ComboBox1.Items.AddObject('Show 856', TObject(856));
    ComboBox1.Items.AddObject('Show 1000', TObject(1000));
  finally
    ComboBox1.Items.EndUpdate;
  end;
end;

procedure TForm1.btnNextClick(Sender: TObject);
begin
  if ComboBox1.ItemIndex <> -1 then
    ShowMessage(Integer(ComboBox1.Items.Objects[ComboBox1.ItemIndex]).ToString);
end;

否则,您可以让它成为指向具有任意数量数据(整数、字符串...)的某个对象的真正指针。

无关程序

上面的例子都要求过程可以参数化,即用一个带参数的过程代替。如果不是这种情况,如果程序完全不相关,则您需要采用不同的方法。但同样,哪种方法最合适取决于您的具体情况。

这里有几个例子。

简单的案例陈述

在设计时,将项目设置为 Play soundRun NotepadShow Start Menu

procedure PlaySound;
begin
  MessageBeep(MB_ICONINFORMATION);
end;

procedure RunNotepad;
begin
  ShellExecute(Form1.Handle, nil, 'notepad', nil, nil, SW_SHOWNORMAL)
end;

procedure ShowStartMenu;
begin
  Form1.Perform(WM_SYSCOMMAND, SC_TASKLIST, 0)
end;

procedure TForm1.btnNextClick(Sender: TObject);
begin
  case ComboBox1.ItemIndex of
    0:
      PlaySound;
    1:
      RunNotepad;
    2:
      ShowStartMenu;
  end;
end;

将程序指针与项目一起存储

procedure PlaySound;
begin
  MessageBeep(MB_ICONINFORMATION);
end;

procedure RunNotepad;
begin
  ShellExecute(Form1.Handle, nil, 'notepad', nil, nil, SW_SHOWNORMAL)
end;

procedure ShowStartMenu;
begin
  Form1.Perform(WM_SYSCOMMAND, SC_TASKLIST, 0)
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ComboBox1.Items.BeginUpdate;
  try
    ComboBox1.Items.Clear;
    ComboBox1.Items.AddObject('Play sound', TObject(@PlaySound));
    ComboBox1.Items.AddObject('Run notepad', TObject(@RunNotepad));
    ComboBox1.Items.AddObject('ShowStartMenu', TObject(@ShowStartMenu));
  finally
    ComboBox1.Items.EndUpdate;
  end;
end;

procedure TForm1.btnNextClick(Sender: TObject);
begin
  if ComboBox1.ItemIndex <> -1 then
    TProcedure(ComboBox1.Items.Objects[ComboBox1.ItemIndex])();
end;

好处:没有混淆索引的风险;操作“附加”到项目。

使用命令字典

也许您的应用程序有一组全局命令,用英文单词表示。然后您可能想使用字典来获取与某个词关联的过程。这也可以用于组合框。在设计时,假设有三个项目:beepwritestart:

type
  TForm1 = class(TForm)
    ComboBox1: TComboBox;
    btnNext: TButton;
    procedure btnNextClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FCommands: TDictionary<string, TProcedure>;
  public
  end;

procedure PlaySound;
begin
  MessageBeep(MB_ICONINFORMATION);
end;

procedure RunNotepad;
begin
  ShellExecute(Form1.Handle, nil, 'notepad', nil, nil, SW_SHOWNORMAL)
end;

procedure ShowStartMenu;
begin
  Form1.Perform(WM_SYSCOMMAND, SC_TASKLIST, 0)
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FCommands := TDictionary<string, TProcedure>.Create;
  FCommands.Add('beep', PlaySound);
  FCommands.Add('write', RunNotepad);
  FCommands.Add('start', ShowStartMenu);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FCommands.Free;
end;

procedure TForm1.btnNextClick(Sender: TObject);
var
  Cmd: TProcedure;
begin
  if
    (ComboBox1.ItemIndex <> -1)
      and
    FCommands.TryGetValue(ComboBox1.Items[ComboBox1.ItemIndex], Cmd)
  then
    Cmd();
end;