Question

I have a function that closes all the forms in the application apart from the main form

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;

Called from the main form:

CloseOpenForms(Self);

It works fine as long as there are no active OLE dialogs (e.g. TJvObjectPickerDialog).

How can I force these non modal OLE dialogs to close?

Was it helpful?

Solution

JVCL passes the application handle to 'hwndParent' parameter of IDSObjectPicker.InvokeDialog, hence the dialog is owned (not like 'owner' as in VCL, but more like popup parent) by the application window. Then you can enurate windows to find out the ones owned by the application window and post them a close command.

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;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top