5

I am currently writing a windowing system for an existing Delphi application.

Currently, the program consists of a number of full-sized forms which are shown modally in the order they are required and none of which can be moved by the user. My aim is to allow all of these forms to be moveable. Previously forms were stacked on top of each other but since none could be moved the background forms were not visible to the user. My solution so far has been to hide the 'parent' form when opening a new child, and reshowing it when that child is closed.

Unfortunately since each child is called with showModal, the call the make the parent form visible does not come until after the modal process has completed and hence after the child form has been hidden so the user sees a split second flash where no form is visible.

Is there a way I can prevent the modal forms from being hidden automatically after their process has completed? This would allow me to manually hide them once the parent form is visible again. I have tried to schedule this in the FormHide event of each child form but this does not work as a child form is also hidden when opening one of its own children.

EDIT:

Here is what I have so far based of Remy's advice below

procedure openModalChild(child: TForm; parent: TForm);
var
  WindowList: Pointer;
  SaveFocusCount: Integer;
  SaveCursor: TCursor;
  SaveCount: Integer;
  ActiveWindow: HWnd;
  Result: integer;
begin
  CancelDrag;
  with child do begin
  Application.ModalStarted;
  try
  ActiveWindow := GetActiveWindow;
  WindowList := DisableTaskWindows(0);
  //set the window to fullscreen if required
  setScreenMode(child);
  try
    Show; //show the child form
    try
      SendMessage(Handle, CM_ACTIVATE, 0, 0);
      ModalResult := 0;
      repeat
        Application.HandleMessage;
        //if Forms.Application.FTerminate then ModalResult := mrCancel else
          if ModalResult <> 0 then closeModal(child as TCustomForm);
      until ModalResult <> 0;
      Result := ModalResult;
      SendMessage(Handle, CM_DEACTIVATE, 0, 0);
      if GetActiveWindow <> Handle then ActiveWindow := 0;
    finally
      parent.Show;
      Hide;
    end;
  finally
    EnableTaskWindows(WindowList);
    parent.Show; //reshow the parent form
    if ActiveWindow <> 0 then SetActiveWindow(ActiveWindow);
  end;
  finally
    Application.ModalFinished;
  end;
  end;
end;

This works well but the only problem is the active repeat loop never breaks, even after the child has been escaped and so the parent form is never reshown. Is there any way I can resolve this?

jmc
  • 620
  • 14
  • 24
  • Have you tried making the parent form visible from the child form prior to closing? – Marcus Adams Dec 16 '11 at 21:52
  • I don't get how hiding the 'parent' window will result in movability of either form. Please describe your goal precisely, or delete the superfluous part from the question. – NGLN Dec 16 '11 at 21:58
  • Hiding the parent doesn't change whether either form can move (they already can). The forms I am referencing should be all within one window but due to existing design implementation they are not. To give the one-window effect each newly shown child is positioned and sized identical to its calling parent and when closed the parent is relocated to the child position and made visible. Visually these appear as one window with the exception of a brief moment where no form is visible. – jmc Dec 16 '11 at 22:08
  • Unfortunately no. It should be though. I'm basically trying to give that impression without having to modify too much of the existing forms. – jmc Dec 16 '11 at 23:34

1 Answers1

10

ShowModal() explicitally calls Show() just before entering its modal processing loop, and explicitally calls Hide() immediately after exiting the loop. You cannot change that without altering the code in the VCL's Forms.pas source file.

If you need finer control over the windows, without editing VCL source code, then don't use ShowModal() at all. Use Show(), Hide(), DisableTaskWindows(), and EnableTaskWindows() yourself as needed. I would sugest you look at Forms.pas to see how they are used. Copy the implementation of ShowModal() into your own function, then you can customize it as needed.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Hi Remy - as a non-experience Delphi programmer, how do I create a new implementation of ShowModal for a collection of forms? I assume they have to implement from some superclass of Form that inherits from TForm? Speaking in Java/C terms here... – jmc Dec 21 '11 at 02:32
  • I would implement it as a standalone function that you can pass a `TForm` pointer as a parameter. – Remy Lebeau Dec 21 '11 at 03:27