2

我有一个功能可以关闭应用程序中除主表单之外的所有表单

procedure CloseOpenForms(const Component: TComponent);
var
  i: Integer;
begin
  for i := 0 to pred(Component.ComponentCount) do
  begin
    CloseOpenForms(Component.Components[i]);

    if Component.Components[i] is TForm then
    begin
      TForm(Component.Components[i]).OnCloseQuery := nil;

      TForm(Component.Components[i]).Close;
    end;
  end;
end;

从主窗体调用:

CloseOpenForms(Self);

只要没有活动的 OLE 对话框(例如 TJvObjectPickerDialog),它就可以正常工作。

如何强制关闭这些非模式 OLE 对话框?

4

1 回答 1

3

JVCL 将应用程序句柄传递给 'hwndParent' 参数IDSObjectPicker.InvokeDialog,因此对话框由应用程序窗口拥有(不像 VCL 中的“所有者”,但更像弹出父级)。然后,您可以启动窗口以找出应用程序窗口所拥有的窗口,并向它们发布关闭命令。

procedure CloseOpenForms(const AComponent: TComponent);

  function CloseOwnedWindows(wnd: HWND; lParam: LPARAM): BOOL; stdcall;
  begin
    Result := TRUE;

    if (GetWindow(wnd, GW_OWNER) = HWND(lParam)) and (not IsVCLControl(wnd)) then
    begin
      if not IsWindowEnabled(wnd) then      // has a modal dialog of its own
        EnumWindows(@CloseOwnedWindows, wnd);

      SendMessage(wnd, WM_CLOSE, 0, 0);
    end;
  end;

  procedure CloseOpenFormsRecursive(const RecComponent: TComponent);
  var
    i: Integer;
  begin
    for i := 0 to pred(RecComponent.ComponentCount) do
    begin
      CloseOpenFormsRecursive(RecComponent.Components[i]);

      if RecComponent.Components[i] is TForm then
      begin
        TForm(RecComponent.Components[i]).OnCloseQuery := nil;

        TForm(RecComponent.Components[i]).Close;
      end;
    end;
  end;

begin
  EnumWindows(@CloseOwnedWindows, Application.Handle);

  CloseOpenFormsRecursive(AComponent)
end;
于 2012-04-25T01:03:10.037 回答