禁用/启用后,Delphi主窗体落后于其他应用程序

时间:2018-07-29 15:32:22

标签: forms delphi vcl

我有一些vcl mdi应用程序,我需要在其中做一些工作,并在上面显示另一种无模式的进度形式。并且由于此进度表是从某个线程更新的,并且上面有一些按钮(以取消操作),因此我使用application.ProcessMessages更新了进度。在此过程中,我需要禁用所有主窗体控件。我是这样做的:

MainForm.enabled := false;
... do some work here, update progress ...
MainForm.enabled := true;

但是,在此之后,我的主窗体进入了其他不很酷的Windows应用程序。如果我删除已启用/禁用的这两行-它会保持在应有的位置。

有什么解决办法吗?

2 个答案:

答案 0 :(得分:1)

一个简单的BringTofront可以工作。可以在将enabled设置为true之前或之后。

MainForm.enabled := false;
// ... do some work here, update progress ...
MainForm.enabled := true;
MainForm.BringTofront;

MainForm.enabled := false;
// ... do some work here, update progress ...
MainForm.BringTofront;
MainForm.enabled := true;

修改: 如下所述,使用上面的代码,主窗体在成为焦点之前将落后于其他窗体。这种情况发生在Delphi 7中,但似乎没有发生在Delphi 2009中。

当当前活动窗体关闭或隐藏时,Delphi尝试切换到主窗体。但是,如果禁用了主窗体,Delphi将无法激活它,而会将其移到后面。解决方案非常简单,只需在隐藏或释放其他表单之前将Enabled设置为true。无需致电BringTofront

MainForm.enabled := false;
ProgressForm.Show;  // Or Application.CreateForm(...)
// ... do some work here, update progress ...
MainForm.enabled := true;
ProgressForm.Hide;  // Or ProgressForm.Free;

修改: 这是导致此行为的Delphi代码:

procedure TCustomForm.CMShowingChanged(var Message: TMessage);
  ....
begin
  ....
      NewActiveWindow := 0;
      if (GetActiveWindow = Handle) and not IsIconic(Handle) then
        NewActiveWindow := FindTopMostWindow(Handle);
      if NewActiveWindow <> 0 then
      begin
        SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_HIDEWINDOW or
          SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE);
        SetActiveWindow(NewActiveWindow);
      end else
        ShowWindow(Handle, SW_HIDE);
  ....
end;

另一种解决方法是处理第二种形式的CM_SHOWINGCHANGED消息:

procedure CMSHOWINGCHANGED(var Message: TMessage); message CM_SHOWINGCHANGED;

procedure TProgressForm.CMSHOWINGCHANGED(var Message: TMessage);
begin
  if not visible then
     Application.MainForm.Enabled := True;
  inherited;
end;

答案 1 :(得分:0)

好的,看起来我找到了解决方案。进度表的PopupMode设置为pmAuto。在这种情况下,主窗体位于顶部。

它以这种方式工作:

procedure TMainForm.DoSomenthing;
begin
  enabled := false;
  try
    // open progress form
    Include(ProgressFrm.FFormState, fsModal);
    ProgressFrm.Show;

    .... do something, update progress ....

    // close progress form
    ProgressFrm.Hide;
    Exclude(ProgressFrm.FFormState, fsModal);
  finally
    enabled := true;
    BringToFront;
  end;
end;