1

Possible Duplicate:
How can I make a form that is not disabled when another form is shown modally?

Suppose I have an application with three forms: a main form that leads the user through a workflow, wizard style; a modal window that shows occasionally in certain steps of the wizard; and a third "information" window, which could show at any time, independent of where in the workflow the user is.

How do I make the modal window grab focus away from the main form, but keep the info window usable and responsive at all times?

Using the most obvious InfoFrame.Create(nil).Show from the main frame leaves the info window unusable when the modal form is showing.

Curiously, if I create and show the info window from the modal window, it will be responsive in the desired way, and it persists after the modal window is dismissed. When the modal window is shown again, though, the info window is forced into the background and becomes unresponsive.

How do I make the info windows remain usable at all times, even when another form's ShowModal procedure has been called?

In the actual application I'm working on, there are actually tens of modal forms from about a dozen 'workflow' main windows (many of them are also modal), but only one info window (of which multiple instances may be shown), I'd prefer not to have to change every call to ShowModal to something else, although I'm not averse to wrapping or subclassing the call if that's the only option.

Community
  • 1
  • 1
SingleNegationElimination
  • 151,563
  • 33
  • 264
  • 304
  • Not very practical, but if your _info_ window is just for information purposes, perhaps you can create it using `winapi` and leave it out of `Application`'s domain. – iMan Biglari Oct 30 '12 at 13:50
  • To be clear, if you have two "main" windows and one "info" window, and one of those main windows creates a modal dialog, you do want to disable the other main window, just not the info window? –  Oct 30 '12 at 13:52
  • right, everything besides the info window(s) and the newly opened modal form should be disabled. – SingleNegationElimination Oct 30 '12 at 13:56
  • 1
    @iMan That won't work. ShowModal will disable all top level windows, whether or not they are VCL windows. – David Heffernan Oct 30 '12 at 14:06
  • @DavidHeffernan My mistake. I thought perhaps `Application` can't access windows out of its reach. – iMan Biglari Oct 30 '12 at 14:07
  • 1
    @iMan - The windows belonging with the same thread with the modal form are disabled. – Sertac Akyuz Oct 30 '12 at 18:48

1 Answers1

4

Don't use ShowModal, but instead disable the MainForm using EnableWindow(MainForm.Handle, False) and enable it again afterwards using EnableWindow(MainForm.Handle, True). You might need to add something to make sure that the right window is always on top.

Edit: If you don't want to change anything in the MainForm, nor in the modal form, you can add a Timer to the InfoFrame that has that form constantly enable itself:

procedure TInfoFrame.EnablerTimer(Sender: TObject);
begin
  if not IsWindowEnabled(Self.Handle) then
    EnableWindow(Self.Handle, True);
end;

That way, the InfoFrame will be usable even after a call to ShowModal of another form.

Edit2: As pointed out by @DavidHeffernan, rather than in a Timer, a better place to put this logic would be in the WM_ENABLE handler of the InfoFrame. The idea remains the same, though.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Thijs van Dien
  • 6,516
  • 1
  • 29
  • 48
  • Sorry, the application in question uses `ShowModal` in more than 500 locations; it's not feasible for me to figure out how to 'almost show modal' that many times. I need a solution that extends existing behaviour. – SingleNegationElimination Oct 30 '12 at 14:54
  • 1
    @TokenMacGuy So basically you're asking for some kind of hack. Well, I edited my post. – Thijs van Dien Oct 30 '12 at 15:08
  • @TokenMacGuy I've already pointed you at that solution I think. – David Heffernan Oct 30 '12 at 15:15
  • @DavidHeffeman Well, partially true. The difference is that the way I used it, you don't need to change any other forms. – Thijs van Dien Oct 30 '12 at 15:19
  • 1
    @tvdien A timer isn't so great. Have a read of my answer again. I followed Sertac's advice and did it in a `WM_ENABLE` message handler. – David Heffernan Oct 30 '12 at 15:28
  • @DavidHefferman True, I couldn't think of a better place to put it that quickly. I agree that `WM_ENABLE` is a better choice. I suggest you make that an answer and I'll put a reference to it in mine. – Thijs van Dien Oct 30 '12 at 15:30
  • @tvdien I'm not going to add an answer since this question is an exact duplicate. What we do in that situation is close the question as being a duplicate. The idea is that we can have just a single topic for each distinct question. If you want to answer the question, it's better to do so at the original location: http://stackoverflow.com/questions/12953225/how-can-i-make-a-form-that-is-not-disabled-when-another-form-is-shown-modally?lq=1 – David Heffernan Oct 30 '12 at 15:33
  • @DavidHeffeman Very well then... – Thijs van Dien Oct 30 '12 at 15:34
  • By the way, I upvoted your answer because it is a good answer. And I'm not trying to put you off. You've not been very active yet on SO and I suspect you aren't familiar with the intricacies of close votes and so on. So I'm just trying to help. – David Heffernan Oct 30 '12 at 15:38
  • @DavidHefferman No problem. I don't mind giving credit where it is due, especially if it is to someone with a track record like yours. :) It makes sense to keep organized. – Thijs van Dien Oct 30 '12 at 15:41
  • In the case of using `WM_ENABLE` here, the real credit goes to Sertac Akyuz! He's the no. 1 Windows API expert in the Delphi tags in my opinion. – David Heffernan Oct 30 '12 at 15:43
  • @David - Heh, heh.. wish it were so, nice dream for me :D – Sertac Akyuz Oct 30 '12 at 18:50
  • @DavidHeffernan I just noticed that I had been misspelling your name all along. My apologies - unfortunately I'm unable to edit those comments anymore. – Thijs van Dien Oct 31 '12 at 08:52
  • @tvdien It's fine. I've spent a lifetime having my name misspelled. You are not the first and won't be the last to call me Hefferman! ;-) – David Heffernan Oct 31 '12 at 08:53