【问题标题】:Manipulate form components by form's name通过表单名称操作表单组件
【发布时间】:2012-01-22 09:21:54
【问题描述】:

我有一个 Form 类,用于生成多个表单对象。我重命名每个生成的表单。

我不知道如何在不影响其他生成的表单组件的情况下访问指定的表单组件。

我已经使用了这段代码,但最后创建的表单的组件总是受到影响:

procedure TmainForm.OFBloqueButtonClick(Sender: TObject);
begin
    if (mainForm.tabSheetBool = True) AND (mainForm.OFID <> '') then begin
       if OF_bloque = False then begin
           Application.CreateForm(TOFOperationsForm, OFOperationsForm);
           OFOperationsForm.Caption := 'Bloquer OF';
           OFOperationsForm.Name := 'OFBloqueForm';
           OF_bloque := True;
       end;
       OFOperationsForm.BringToFront;
       OFOperationsForm.ADOOF.SQL.Text := 'SELECT * FROM OFTab WHERE ID=''' + OFID + '''';
       OFOperationsForm.ADOOF.Open;
    end;
end;

我的目标是操纵所需表单的指定 ADOQuery。

谢谢。

【问题讨论】:

  • 没有必要设置新表单的 Name 属性,如果您的代码稍后不依赖它,那么也可以从这里的代码示例中删除。
  • 我命名了表单以通过它的名称来调用它。
  • TLama 我猜 OF_bloque 会阻止创建第二个表单。不过不确定。
  • 问题标题是“按表单名称操作表单组件” - 您的代码在哪里/如何使用表单名称?这未显示。
  • 其他方法确实使用 FindComponent(使用表单名称),而不是表单变量?抱歉,该问题没有提供有关主要问题的足够信息。

标签: forms delphi ado


【解决方案1】:

当您创建表单类的多个实例时,您不应使用 IDE 在表单单元中声明的变量。事实上,我认识的大多数 Delphi 开发人员会在创建新表单后立即删除该 var,只有应用程序的主表单会保留它,因为 dpr 需要它。

此外,您无需使用 FindWindow 查找表单,甚至无需遍历应用程序或屏幕的表单。只需在创建时使用本地 var:

procedure TmainForm.OFBloqueButtonClick(Sender: TObject);
var
  NewForm: TOFOperationsForm;
begin
    NewForm := nil;
    if (mainForm.tabSheetBool = True) AND (mainForm.OFID <> '') then begin
       if OF_bloque = False then begin
           NewForm := TOFOperationsForm.Create(Application);
           NewForm.Caption := 'Bloquer OF';
           NewForm.Name := 'OFBloqueForm';  //<== You'll need to make this unique!
           OF_bloque := True;
       end;
       if Assigned(NewForm) then begin
         NewForm.BringToFront;
         NewForm.ADOOF.SQL.Text := 'SELECT * FROM OFTab WHERE ID=''' + OFID + '''';
         NewForm.ADOOF.Open;
       end;
    end;
end;

编辑

在上面的代码中添加了一些安全措施来防止 AV。就目前而言,这意味着除非创建表单,否则不会更改查询。如果打算设置新表单的查询或更改上次创建的表单的查询,则需要 TmainForm 中的成员字段:

TmainForm = class(TForm)
private
  FLastFormCreated: TOFOperationsForm;
//...

并将 ButtonClick 处理程序中的代码更改为:

procedure TmainForm.OFBloqueButtonClick(Sender: TObject);
begin
    if (mainForm.tabSheetBool = True) AND (mainForm.OFID <> '') then begin
       if OF_bloque = False then begin
           FLastFormCreated := TOFOperationsForm.Create(Application);
           FLastFormCreated.Caption := 'Bloquer OF';
           FLastFormCreated.Name := 'OFBloqueForm';
           OF_bloque := True;
       end;
       if Assigned(FLastFormCreated) then begin
         FLastFormCreated.BringToFront;
         FLastFormCreated.ADOOF.SQL.Text := 'SELECT * FROM OFTab WHERE ID=''' + OFID + '''';
         FLastFormCreated.ADOOF.Open;
       end;
    end;
end;

我留在了 Assigned 检查中,因为如果没有其余代码,我无法判断如果 FLastFormCreated 至少收到一次引用(即设置了 OF_Blogue在其他地方设为 True)。

【讨论】:

  • OF_bloque 是一个标志,表示“已经有一个表单,不要创建另一个”
  • "我的目标是操作指定的 ADOQuery 所需的形式。" - 这需要使变量可以从其他方法访问
  • +1 “我认识的大多数 Delphi 开发人员在创建新表单后立即删除该 var...”
  • 但我得到了访问违规错误。
  • NewForm 是该例程的本地。因此OF_bloque 是多余的,并且在 True 时会导致 OP 的 AV。使NewForm 成为 TMainForm 或其单元的成员。
【解决方案2】:

我认为发生的情况是您创建了多个表单,这些表单删除了指向先前表单的指针,最终得到了指向最后创建的表单的指针。

您可以迭代 Screen.Forms 以获得对所需表单的引用,这是一个示例:

procedure TForm1.Button1Click(Sender: TObject);
var
  i: integer;
  NewForm: TForm2;
begin
  // create two forms, then show the first form
  Application.CreateForm(TForm2, NewForm);
  NewForm.Name := 'FirstForm';
  NewForm.Caption := 'This form was created 1st';
  Application.CreateForm(TForm2, NewForm);
  NewForm.Name := 'SecondForm';
  NewForm.Caption := 'This form was created 2nd';
  // iterate Screen.Forms to access the first form by name
  for i := 0 to Screen.FormCount - 1 do
    if Screen.Forms[i].Name = 'FirstForm' then
      Screen.Forms[i].Show;  // shows the first form
end;

【讨论】:

    【解决方案3】:

    解决办法是:

    unit main;
    
    interface
    
    uses
        Windows, Messages, ... , OF_operations;
    
    type
        TmainForm = class(TForm)
        ...
        ...
        ...
        private 
        ...
        public
             OFBloqueForm, OFCancelForm, OFDelaisClientForm, OFInspectionForm: TOFOperationsForm;
        end;
    
    // Bloquer OF
    procedure TmainForm.OFBloqueButtonClick(Sender: TObject);
    begin
        if (mainForm.tabSheetBool = True) AND (mainForm.OFID <> '') then begin
            if OF_bloque = False then begin
                OFBloqueForm := TOFOperationsForm.Create(Application);
                OFBloqueForm.Caption := 'Bloquer OF';
                OFBloqueForm.Name := 'OFBloqueForm';
                OF_bloque := True;
            end;
            OFBloqueForm.BringToFront;
            OFBloqueForm.ADOOF.SQL.Text := 'SELECT * FROM OFTab WHERE ID=''' + OFID + '''';
            OFBloqueForm.ADOOF.Open;
        end;
    end;
    

    【讨论】:

    • 问题出在哪里 - 简单地更改引用的单位就解决了吗?
    猜你喜欢
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 2020-11-18
    • 1970-01-01
    • 2013-12-26
    • 2012-07-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多