forms - Delphi:在运行时以动态创建的形式创建TComboBox

标签 forms delphi dynamic macros scripting

好的,我正在从事一个最初在 D7 中完成的项目。我在这里承担双重职责,因为我正在修复原始代码中的错误并尝试将其移植到 XE3/4。当原作者在项目中使用一些非开源工具包时,有点困难。

但无论如何,该应用程序是一个脚本/宏程序。作为客户脚本/宏语言的一部分。能够为用户输入创建非常简单的基本表单。表单是在运行时根据脚本/宏作者创建的脚本/宏动态创建的。我已经修复了用于创建表单的代码中的一些错误。但是,有一点我就是想不通。

为父窗体创建 TComboBox 并设置 AT 组件创建的 Text 属性时。 Text 属性中的文本不显示。

以下是创建表单的代码:

procedure CreateForm(var wFrm: TForm; sName: String);
var
  iLoop, iPos, iLen: Integer;
  iFormHeight, iFormWidth: Integer;
  lh, hresult1, hresult2: Integer;
  sWork, sWork2, sLine, CmdName: String;
  lstForm, lst: TStringList;
  pnl: TPanel;

begin
  iFormHeight := 80;
  iFormWidth := 400;
  hresult1 := 0;
  lst := TStringList.Create;

  iLoop := lstForms.IndexOf(Trim(UpperCase(sName)));
  if iLoop < 0 then
  begin
    AbortError('Form "' + sName + '" could not be found!');
    Exit;
  end;

  lstForm := TStringList(lstForms.Objects[iLoop]);

  for iLoop := 0 to lstForm.Count - 1 do
  begin
    sLine := lstForm[iLoop];
    iPos := Pos('=', sLine);
    iLen := Length(sLine);
    if iPos = 0 then
      continue;

    CmdName := Uppercase(Trim(Copy(sLine, 1, iPos - 1)));
    sWork2 := Trim(Copy(sLine, iPos + 1, iLen));

    if CmdName = 'FORMCAPTION' then
    begin
      with wfrm do
      begin
        Caption := Trim(Copy(sLine, iPos + 1, iLen));
        Name := Trim(sName);
        Height := iFormHeight;
        Width := iFormWidth;
        Tag := 10;
        BorderStyle := bsSizeable;
        BorderIcons := [biSystemMenu];
        Position := poDesktopCenter;
        pnl := TPanel.Create(wfrm);
        with pnl do
        begin
          Parent := wfrm;
          Caption := '';
          Align := alBottom;
          BevelInner := bvNone;
          BevelOuter := bvNone;
          Height := 30;
        end;
        with TButton.Create(wfrm) do
        begin
          Parent := pnl;
          Caption := '&OK';
          Default := True;
          ModalResult := mrOK;
          Left := 235;
          Top := 0;
        end;
        with TButton.Create(wfrm) do
        begin
          Parent := pnl;
          Caption := '&Cancel';
          Cancel := True;
          ModalResult := mrCancel;
          Left := 310;
          Top := 0;
        end;
        pnl := TPanel.Create(wfrm);
        with pnl do
        begin
          Parent := wfrm;
          Caption := '';
          Align := alClient;
          BevelInner := bvRaised;
          BevelOuter := bvNone;
          BorderWidth := 5;
        end;
      end;
    end
    else
    begin
      lst.Clear;
      StringToList(sWork2, lst, ':');
      if UpperCase(lst[0]) = 'EDITBOX' then
        CreateEditBox
      else if UpperCase(lst[0]) = 'CHECKBOX' then
        CreateCheckBox
      else if UpperCase(lst[0]) = 'COMBOBOX' then
        CreateComboBox
      else if UpperCase(lst[0]) = 'LABEL' then
        CreateLabel;
    end;
  end;

  with wfrm do
  begin
    if hresult1 > 1 then
      hresult2 := 5
    else
      hresult2 := 9;
    Tag := Tag + hresult2;
    Height := Height + hresult2;
  end;

  lst.Free;
end;

下面是为表单创建 TComboBox(带 TLabel)的具体代码:

  procedure CreateComboBox;
  var
    iPos: Integer;
  begin
    with TLabel.Create(wfrm) do
    begin
      Parent := pnl;
      Caption := lst[1];
      Left := 15;
      if hresult1 > 1 then
        hresult2 := 5 * hresult1
      else
        hresult2 := 3 * hresult1;
      Top := wfrm.Tag + hresult2;
      Name := 'lbl' + CmdName;
      Width := 150;
      WordWrap := True;
      AutoSize := True;
      lh := Height;
    end;
    hresult1 := Trunc(lh/13);
    with TComboBox.Create(wfrm) do
    begin
      Parent := pnl;
      Left := 170;
      Width := 200;
      if hresult1 > 1 then
        hresult2 := 5 * hresult1
      else
        hresult2 := 3 * hresult1;
      Top := wfrm.Tag + hresult2;
      Style := csDropDownList;
      Name := UpperCase(CmdName);
      Text := 'Test Text';
      sWork := lst[3];
      lst.Clear;
      StringToList(sWork, lst, ',');
      for iPos := 0 to lst.Count - 1 do
        lst[iPos] := lst[iPos];
      Items.Assign(lst);
//      ItemIndex := 0;
    end;
    wfrm.Tag := wfrm.Tag + ((hresult1 * 13)+ 13);
    wfrm.Height := wfrm.Height + ((hresult1 * 13)+ 13);
    TComboBox(wfrm
  end;

注意:上述过程是 CreateForm 过程的子过程。

应用程序使用 TStringList 列表在脚本/宏运行时存储表单定义。然后,当作者希望显示表单时,上面的代码会检索该信息以创建表单。然后创建表单并将表单对象放入另一个临时 TStringList 列表中,然后再显示。这样做是为了当用户运行脚本/宏并输入表单中请求的信息/设置时。作者可以在表单被销毁之前从表单中检索所请求的信息/设置。

表单将从 tmp TStringList 列表中删除(如果以前创建过),创建并存储在 tmp TStringList 列表中,并使用以下代码以模态方式显示:

    iPos := lstForms.IndexOf(UpperCase(sWVar2));
    if iPos < 0 then
    begin
      AbortError('Could not find form "' + Trim(sWVar2) + '" defined!');
      Exit;
    end;

    iPos := lstFormsTMP.IndexOf(UpperCase(sWVar2));
    if iPos > -1then
    begin
      TForm(lstFormsTMP.Objects[iPos]).Free;
      lstFormsTMP.Delete(iPos);
      frm.Free;
      iPos := lstFormsTMP.IndexOf(UpperCase(sWVar2));
      if iPos > -1 then
      begin
        AbortError('Form "' + Trim(sWVar2) + '" was not removed from the lstFormsTMP TStringList.');
        Exit;
      end;
    end;

    frm := TForm.Create(frmMain);
    CreateForm(frm, sWVar2);
    lstFormsTMP.AddObject(Uppercase(sWVar2), frm);
  end;

  iPos := lstFormsTMP.IndexOf(UpperCase(sWVar2));
  if iPos < 0 then
  begin
    AbortError('Could not find form "' + Trim(sWVar2) + '" defined!');
    Exit;
  end;

  hndHold := SwitchToHandle(frmMain.Handle);
  try
    Result := TForm(lstFormsTMP.Objects[iPos]).ShowModal = mrOK;
  finally
    SwitchToHandle(hndHold);
  end;

使用上述代码集,可以创建并显示运行脚本中定义的表单,没有太多错误/错误。但是,即使我已经对 TComboBox.Text 属性的文本进行了硬编码。没有显示。谁能解释一下为什么我会出现这种情况?到目前为止,所有其他表单组件(TCheckBox、TEditBox、TLabel)都可以正常显示。只是 TComboBox 让我摸不着头脑。

注意:最终,TComboBox.Text 属性将根据表单组件定义中该属性的作者设置进行动态设置。

提前致谢。

已编辑 2013 年 8 月 18 日,包括以下内容:

原始代码还包括通过 TIniFile 对象保存/加载表单组件设置的功能。以下代码用于保存 TComboBox 的设置:

  if frm.Components[i] is TCombobox then
    iniWork.WriteString(frm.Name, TCombobox(frm.Components[i]).Name, TCombobox(frm.Components[i]).Text)
  else

以及以下内容来加载 TComboBox 设置:

  if frm.Components[i] is TCombobox then
  begin
    TCombobox(frm.Components[i]).ItemIndex := TCombobox(frm.Components[i]).Items.IndexOf(
      iniWork.ReadString(frm.Name, TCombobox(frm.Components[i]).Name, TCombobox(frm.Components[i]).Text));
  end

通过上面的代码,在我看来,设置正在从 TComboBox 的 Text 属性中保存并加载回其中。现在,当加载 TComboBox 设置时,表单在创建并作为对象放置到 tmp TStringList 列表中之后以及以模态方式显示之前会发生更改。然而,当显示表单时,将显示由上述加载代码设置的 Text 属性。

正是因为以上这些,我才感到困惑。为什么在创建表单之后它会在此时起作用。但不是在创建表单时?

最佳答案

这是一个下拉列表,因为您将样式设置为csDropDownList。这意味着组合框的编辑控件只能显示其列表控件中包含的项目。

对于下拉列表组合,设置 Text 属性无效。您应该指定 ItemIndex,而不是使用 Text 属性。

关于forms - Delphi:在运行时以动态创建的形式创建TComboBox,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18868133/

相关文章:

ios - 尝试实现动态单元格高度时 TableView 抛出错误

angularjs - MEAN.JS 联系表

delphi - 使用 Delphi 通过 UIAutomation 获取底层菜单项的列表

c# - 使用 IronPython 在 C# 中运行特定的 Python 函数

sql - 动态 SQL Server 数据透视表

Delphi shell 上下文菜单,如何绘制图标

jquery - 如何向 jQuery 数组添加键、值对?

javascript - 限制允许选中的复选框数量

php - AJAX 电子邮件注册表单 + .htaccess 干净 URL 问题

Delphi - identcache 扩展