FormShow在嵌入式表单上被调用两次

问题描述 投票:0回答:1

我正在创建一个应用程序,其中主窗体基本上是一个菜单(在拆分视图中)和一个带有“主页选项卡”的页面控件。根据所选的菜单项,创建一个新的标签页,其上有一个嵌入的表单,用户可以在其中执行大量的操作和数据查找等。这一切都很有效,除了我有一个问题嵌入表单,其FormShow方法在为此表单创建新选项卡时,将触发两次。

要创建问题表单,我使用:

procedure TMain.actMemberExecute(Sender: TObject);
var
  NewTabSheet : TTabSheet;
  NewMembForm : TMembForm;
begin
  CloseSVMenu;
  NewTabSheet := TTabSheet.Create(PageControl1);
  NewTabSheet.Visible := true;
  NewTabSheet.Caption := 'Member Tab';
  NewTabSheet.PageControl := PageControl1;
  NewTabSheet.ImageIndex := 18;

  NewMembForm := TMembForm.Create(NewTabSheet);
  NewMembForm.Parent := NewTabSheet;

  NewMembForm.Align := alclient;
  NewMembForm.Show;
  PageControl1.ActivePage := NewTabSheet;
end;

并且以这种方式创建了一个“好”的形式(对我来说似乎是一样的)

procedure TMain.actPersonExecute(Sender: TObject);
var
  NewTabSheet : TTabSheet;
  NewPersForm : TPersInfoForm;
begin
  CloseSVMenu;
  NewTabSheet := TTabSheet.Create(PageControl1);
  NewTabSheet.Visible := true;
  NewTabSheet.Caption := 'Person';
  NewTabSheet.PageControl := PageControl1;
  NewTabSheet.ImageIndex := 17;

  NewPersForm := TPersInfoForm.Create(NewTabSheet);
  NewPersForm.Parent := NewTabSheet;
  NewPersForm.Align := alClient;

  NewPersForm.Show;

  PageControl1.ActivePage := NewTabSheet;
end;

每个表单都有类似的OnCreate和OnShow表单事件。 FormCreate方法集确保数据模块中的任何所需查找表都是打开的,然后根据用户对它们的权限设置每个表单的TAction.Enabled状态。 FormShow只是将表单的主表定位到第一个记录(<tdataset>.First),然后在用户看到该表单的数据之前检查一些其他预处理(例如,如果需要通过<tdataset>.Locate(...)移动到特定记录) 。

我已经追溯了多种形式的行为。所有这些都通过Create过程(如预期的那样),返回到Main窗体中的过程,然后触发FormShow。该过程完成,然后使用问题表单,整个屏幕闪烁,并再次启动FormShow。其他8个表单,都基于相同的代码,按预期工作,FormShow调用一次,没有屏幕闪烁。

以下是上述相同两个示例的FormCreate和FormShow程序的片段

问题表(TMembForm)

procedure TMembForm.FormCreate(Sender: TObject);
var
   CategoryLabel : string;

begin
   OpenToMemberID := 0;
   CreateNewMember := false;

   fdqMembList.active := true;

   dm1.fdtMemCat.Active := true;
   dm1.fdtMemStatus.Active := true;
   dm1.fdtMemStatus.First;
   dm1.fdtMemStatus.Next;
   cbFilterList.Items.Clear;
   cbFilterList.Items.Add('All');
   while not dm1.fdtMemStatus.Eof do
   begin
      CategoryLabel := dm1.fdtMemStatus.FieldByName('MemStatDesc').AsString;
      cbFilterList.Items.Add(CategoryLabel);
      dm1.fdtMemStatus.Next;
   end;
   cbFilterList.Items.Add('Other');
   cbFilterList.ItemIndex := 1;
   fdqMembList.Filter := 'MemStatID=1';
   fdqMembList.Filtered := true;
   cpgMembers.CollapseAll;
   cpMemBasic.Collapsed := false;

   {set action.enabled here....} 

end;


procedure TMembForm.FormShow(Sender: TObject);
var
  StatID, NMResult : integer;
  NewMemStat, NewMemPrime, NewMembID : integer;
  NewMembDlg : TNewMembDlg;

begin
   {whatever pre-processing}
   OpenToMemberID := MembOpen;
   CreateNewMember := CreateNewMemb;

   fdqMembList.First;

   {check if need to immediately create new member}
   if CreateNewMember then
   begin
     CreateNewMember := false;
     CreateNewMemb := false;
     NewMembDlg := TNewMembDlg.Create(nil);
     try
       NMResult := NewMembDlg.ShowModal;
       if NMResult=mrOK then
       begin
         NewMembID := dm1.dbMain.ExecSQLScalar('select max(memberno)+1 from member');
         NewMemStat := NewMembDlg.NewMemStat;
         NewMemPrime := NewMembDlg.NewMemPrime;
         fdqNewMemb.Close;
         fdqNewMemb.ParamByName('MembID').AsInteger := NewMembID;
         fdqNewMemb.ParamByName('StatID').AsInteger := NewMemStat;
         fdqNewMemb.ExecSQL;
         fdqNewMembPrime.Close;
         fdqNewMembPrime.ParamByName('MembID').AsInteger := NewMembID;
         fdqNewMembPrime.ParamByName('PersID').AsInteger := NewMemPrime;
         fdqNewMembPrime.ExecSQL;
         OpenToMemberID := NewMembID;
         fdqMembList.Refresh;
       end;
     finally
       NewMembDlg.Free;
     end;
   end;

   {check if open to specific member}
   if OpentoMemberID>0 then
   begin
     fdqMembList.Filtered := false; {need to be able to find any}
     if fdqMembList.Locate('MemberNo',OpenToMemberID,[]) then
     begin
        fdqMembList.Filtered := false;
        StatID := fdqMembList.FieldByName('MemStatID').AsInteger ;
        fdqMembList.Filter := 'MemStatID='+StatID.ToString;
        if StatID=0 then cbFilterList.ItemIndex := cbFilterlist.Items.Count - 1
          else cbFilterList.ItemIndex := StatID;
        fdqMembList.Filtered := true;
     end;
     OpenToMemberID := 0;
     MembOpen := 0;
   end;

end;

这是一个很好的形式(TPersInfoForm)

procedure TPersInfoForm.FormCreate(Sender: TObject);
var
   CategoryLabel : string;
begin

   fdtPerson.Active := true; {make sure table is open}

   fdtPersMile.Active := true;
   fdtPersContact.Active := true;


   dm1.fdtMilestones.Active := true;
   {populate combo box with person category lables}
   cbFilterList.Items.Clear;
   cbFilterList.Items.Add('All');
   dm1.fdtPersonCat.Active := true;
   dm1.fdtPersonCat.First;  {now skip 0}
   dm1.fdtPersonCat.Next;
   dm1.fdtContactType.Active := true;
   dm1.fdtPersRelateType.Active := true;
   dm1.fdtActivityCat.Active := true;

   while not dm1.fdtPersonCat.Eof do
   begin
      CategoryLabel := dm1.fdtPersonCat.FieldByName('PersCatDesc').AsString;
      cbFilterList.Items.Add(CategoryLabel);
      dm1.fdtPersonCat.Next;
   end;
   cbFilterList.Items.Add('Other');
   cbFilterList.ItemIndex := 1;
   fdtPerson.Filtered := true;
   fdtPerson.Filter := 'PersCatID=1';
   {set the rest of the permissions for actions}


end;


procedure TPersInfoForm.FormShow(Sender: TObject);
var
   CatID, NPresult : integer;
   NewPersDlg : TNewPersDlg;
begin

  {test if new Person record should be created}

  fdtPerson.First;

  if CreateNewPerson then
  begin
       {create an instance of NewPerson form, call modally, then create record}
      {new person will always be set to Other, to start}
       CreateNewPerson := false;
       NewPersDlg := TNewPersDlg.Create(nil);
       try
         NPResult := NewPersDlg.ShowModal;
         if NPResult=mrOK then
         begin
            fdtPerson.Insert;
            fdtPerson.FieldByName('LastName').AsString := NewPersDlg.LastName;
            fdtPerson.FieldByName('FirstName').AsString := NewPersDlg.FirstName;
            fdtPerson.FieldByName('PersCatID').AsInteger := 0;
            fdtPerson.Post;
            OpenToPersonID := dm1.dbMain.ExecSQLScalar('select last_insert_id()');
            fdtPerson.Filter := 'PersCatID=0';
            fdtPerson.Filtered := true;
            cbFilterList.ItemIndex := cbFilterList.Items.Count-1;
         end;
       finally
         NewPersDlg.Free;
       end;

  end;

  if OpenToPersonID>0 then
  begin
     fdtPerson.Filtered := false; {need to allow all}

     if fdtPerson.Locate('PersonID',OpenToPersonID,[])then begin
        fdtPerson.Filtered := false;

        catID := fdtPerson.FieldByName('PersCatID').AsInteger;
        fdtPerson.Filter := 'PersCatID='+CatID.ToString;
        fdtPerson.Filtered := true;
        fdtPerson.Locate('PersonID',OpenToPersonID,[]); {needed to ensure on correct record after re-filtering}
        cbFilterList.ItemIndex := CatID;
        if CatID=0 then cbFilterList.ItemIndex := cbFilterList.Items.Count-1;
        OpenToPersonID := 0;  {reset the flag}
     end;
  end;

end;

非常感谢有人可能提供的任何帮助或想法。

谢谢 - 里克布罗津斯基

delphi vcl
1个回答
1
投票

你麻烦的表格的Visible财产的价值是多少?如果它是真的那么这将解释为什么OnShow事件发射两次。

第一次,OnShow事件将在创建Form之后触发,因为在您使其成为TabSheet的子项之前它已经可见。

第二次,当你调用Form的Show()方法时会触发它。

© www.soinside.com 2019 - 2024. All rights reserved.