Delphi - 隐藏的MDI子窗体创建

发布于 2024-08-29 20:42:31 字数 197 浏览 5 评论 0原文

我的应用程序有很多 mdi 表单,它们是在用户成功登录后创建的。我怎样才能最好地隐藏这个创作过程?它看起来很愚蠢,而且在创建新表单后绘制 mdi 表单需要更长的时间等等。

到目前为止,我已经使用了LockWindowUpdate,它并没有隐藏所有内容,但我想使用启动屏幕来显示创建进度,但我不能使用LockWindowUpdate。

此致 珍妮

My application has many many mdi forms and they are created after successfull user login. How can I best hide this creation process? It looks stupid and it takes longer time while mdi forms are painted after new form is created and so on.

So far I have used LockWindowUpdate, which doesn't hide everything, but I would like to use a splash screen showing the creation progress, but I can't with LockWindowUpdate.

Best Regards
Janne

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

饮湿 2024-09-05 20:42:31

要创建不可见的 MDI 子窗体,请将其 Visible 属性设置为 False,此外,您还必须禁用在创建过程中强制显示它们的 VCL 行为。这是由 TCustomFormFormStyle 属性设置器实现的,它将 MDI 子窗体的 Visible 设置为 True

如果您在对象检查器中设置了FormStyle,那么属性设置器将在表单创建期间被调用,并且表单不会立即显示,而是仅在构造完成后才显示。这允许您通过重写 AfterConstruction() 方法来重置请求以显示表单,如下所示:

procedure TMDIChild.AfterConstruction;
begin
  Exclude(FFormState, fsVisible);
  inherited;
end;

这将创建一个不可见的 MDI 子表单。

要测试这一点,您可以在 IDE 中创建一个新的 MDI 应用程序,重写子表单类中的方法(如上所示),并模拟长初始化:

procedure TMainForm.FileNew1Execute(Sender: TObject);
var
  i: integer;
begin
  for i := 1 to 10 do begin
    CreateMDIChild('NONAME' + IntToStr(MDIChildCount + 1));
    Update;
    Sleep(500);
  end;
  for i := 0 to MDIChildCount - 1 do
    MDIChildren[i].Visible := True;
end;

如果没有重写的 AfterConstruction() 方法,它将创建和每半秒显示一个 MDI 子项。使用覆盖的方法,它将在 5 秒的繁忙时间后显示所有内容,这将使您有机会显示启动屏幕。

重要提示:

使用LockWindowUpdate() 减少闪烁或抑制任何屏幕输出错误、错误、错误。 不要这样做,请阅读<有关该主题的 href="http://blogs.msdn.com/oldnewthing/archive/2007/02/22/1742084.aspx" rel="noreferrer">Raymond Chen 文章,了解为什么会这样。

To create MDI child forms invisible you set their Visible property to False, and in addition you have to disable the VCL behaviour of force-showing them during creation. This happens by the FormStyle property setter of TCustomForm, which sets Visible to True for MDI child forms.

If you set the FormStyle in the object inspector, then the property setter will be called during form creation already, and the form will not be shown immediately, but only after the construction is complete. This allows you to reset the request to show the form, by overriding the AfterConstruction() method like so:

procedure TMDIChild.AfterConstruction;
begin
  Exclude(FFormState, fsVisible);
  inherited;
end;

This will create an invisible MDI child form.

To test this you can create a new MDI application in the IDE, override the method in the child form class like shown above, and simulate a long initialization:

procedure TMainForm.FileNew1Execute(Sender: TObject);
var
  i: integer;
begin
  for i := 1 to 10 do begin
    CreateMDIChild('NONAME' + IntToStr(MDIChildCount + 1));
    Update;
    Sleep(500);
  end;
  for i := 0 to MDIChildCount - 1 do
    MDIChildren[i].Visible := True;
end;

Without the overridden AfterConstruction() method it will create and show a MDI child every half second. With the overridden method it will show them all after a busy period of 5 seconds, which will give you the chance to show your splash screen instead.

Important:

Using LockWindowUpdate() to reduce flicker or suppress any screen output is wrong, wrong, wrong. Don't do it, read the series of Raymond Chen articles on the topic to understand why that is so.

千秋岁 2024-09-05 20:42:31

我也遇到过类似的 MDI 儿童闪烁问题。我使用了此提示中的覆盖 AfterConstructionWM_SETREDRAW 消息的组合:
控制 Delphi 中 fsMDIChild 窗口的位置

SendMessage(Application.MainForm.ClientHandle, WM_SETREDRAW, False, 0);
try
  Child := TChildForm.Create(Self);
  Child.Left := ...;
  Child.Top := ...;
  Child.Show;
finally
  SendMessage(Application.MainForm.ClientHandle, WM_SETREDRAW, True, 0);
  InvalidateRect(Application.MainForm.ClientHandle, nil, True);
end;

一切正常。

I had a similar problem with flickering MDI childs. I used combination of overrinding AfterConstruction and WM_SETREDRAW message from this tip:
Controlling the placement of fsMDIChild windows in Delphi

SendMessage(Application.MainForm.ClientHandle, WM_SETREDRAW, False, 0);
try
  Child := TChildForm.Create(Self);
  Child.Left := ...;
  Child.Top := ...;
  Child.Show;
finally
  SendMessage(Application.MainForm.ClientHandle, WM_SETREDRAW, True, 0);
  InvalidateRect(Application.MainForm.ClientHandle, nil, True);
end;

And everything works fine.

假装爱人 2024-09-05 20:42:31

试试这个代码,它对我有用

 try
  SendMessage(Application.MainForm.ClientHandle,WM_SETREDRAW,0,0);
  FormChild:=TBaseChildForm.Create(application);
  FormChild.Caption:='Form '+IntToStr(n);
  FormChild.Show;
 finally
  SendMessage(Application.MainForm.ClientHandle,WM_SETREDRAW,1,0);
  RedrawWindow(Application.MainForm.ClientHandle, nil, 0, RDW_FRAME or RDW_INVALIDATE or   RDW_ALLCHILDREN or RDW_NOINTERNALPAINT);
 end;

try this code, it's work for me

 try
  SendMessage(Application.MainForm.ClientHandle,WM_SETREDRAW,0,0);
  FormChild:=TBaseChildForm.Create(application);
  FormChild.Caption:='Form '+IntToStr(n);
  FormChild.Show;
 finally
  SendMessage(Application.MainForm.ClientHandle,WM_SETREDRAW,1,0);
  RedrawWindow(Application.MainForm.ClientHandle, nil, 0, RDW_FRAME or RDW_INVALIDATE or   RDW_ALLCHILDREN or RDW_NOINTERNALPAINT);
 end;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文