FormShow 在嵌入式表单上被调用两次
FormShow being called twice on embedded form
我正在创建一个应用程序,其中主要表单基本上是一个菜单(在拆分视图中)和一个带有 "home tab" 的页面控件。根据选择的菜单项,创建一个新的标签表,上面有一个嵌入式表单,用户可以在其中执行许多操作和数据查找等。这一切都很好,除了我有一个嵌入式表单问题,它的 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;
并且 "good" 表单以这种方式创建(对我来说这似乎是一样的)
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 方法集确保数据模块中任何必需的查找 table 已打开,然后根据用户对它们的权限设置每个表单的 TAction.Enabled
状态。 FormShow 只是将表单的主要 table 定位到第一条记录 (<tdataset>.First
),然后在用户看到该表单的数据之前检查一些其他预处理(例如它是否需要移动通过 <tdataset>.Locate(...)
).
到特定记录
我追踪过多种形态的动作。全部通过创建过程一次(如预期的那样),returns 到主窗体中的过程,然后 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;
非常感谢有人提供的任何帮助或想法。
谢谢 - 里克布罗津斯基
你这个麻烦Form的Visible
属性值是多少?如果它是 True 那么就可以解释为什么 OnShow
事件会触发两次。
第一次,OnShow
事件将在创建表单后立即触发,因为在您将其设为 TabSheet 的子项之前它已经可见。
第二次,它会在您调用表单的 Show()
方法时触发。
我正在创建一个应用程序,其中主要表单基本上是一个菜单(在拆分视图中)和一个带有 "home tab" 的页面控件。根据选择的菜单项,创建一个新的标签表,上面有一个嵌入式表单,用户可以在其中执行许多操作和数据查找等。这一切都很好,除了我有一个嵌入式表单问题,它的 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;
并且 "good" 表单以这种方式创建(对我来说这似乎是一样的)
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 方法集确保数据模块中任何必需的查找 table 已打开,然后根据用户对它们的权限设置每个表单的 TAction.Enabled
状态。 FormShow 只是将表单的主要 table 定位到第一条记录 (<tdataset>.First
),然后在用户看到该表单的数据之前检查一些其他预处理(例如它是否需要移动通过 <tdataset>.Locate(...)
).
我追踪过多种形态的动作。全部通过创建过程一次(如预期的那样),returns 到主窗体中的过程,然后 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;
非常感谢有人提供的任何帮助或想法。
谢谢 - 里克布罗津斯基
你这个麻烦Form的Visible
属性值是多少?如果它是 True 那么就可以解释为什么 OnShow
事件会触发两次。
第一次,OnShow
事件将在创建表单后立即触发,因为在您将其设为 TabSheet 的子项之前它已经可见。
第二次,它会在您调用表单的 Show()
方法时触发。