Frage

I have this awkward situation that causes an exception. I've found the problem but the solution is so far tricky to implement for me.

In our application, if a user stays in-active for a certain period of time, the security time-out procedure kicks in to prompt the user the password entry box.

However, whenever a form has a message box displayed during the FormShow() event for any particular reason (thing to pay attention here; the formShow event execution hasn't been fully completed yet) and the user decided to not click the OK button of the dialog box for a certain time, the security code kicks in and tries to hide all forms so that it can prompt a password. This scenario will trigger the exception "Cannot change Visible in OnShow or OnHide".

Security code loops all forms using TScreen.FormCount and hides them using TForm(TScreen.Forms[ii]).Hide individually. Hide procedure will cause the exception, because I think this form has not completed it's loading procedure fully yet.

I've done tests, and if I display a message box after the FormShow() event is executed, the security code works perfectly fine and hides all windows without any issues.

I've tried several properties and window message checking to do an "if check" before hiding forms, like Screen.Forms[ii].Visible, Screen.Forms[ii].Active but no luck so far. The mentioned form will be visible and there's no guarantee that it will be active, and if it's active how am I going to hide other non active forms. So my question is, which property or Windows message would indicate that a form is fully loaded, or at least it has past the FormShow event of any given form that exists in TScreen.Forms?

I need an answer to what I am asking please, I need a generalized solution that needs to be implemented in the security code, I can't go through over a thousand forms we have in this giant application and individually try to find solutions to any validation/warning logic exist in those forms.

Thank you

War es hilfreich?

Lösung

The simple answer is to stop showing the modal dialog in the OnShow of the owner form. Wait until the form has finished showing before you display the modal dialog. If you make that change, and that change alone, your existing code will start to work.

The question title you chose was:

Can't hide a window that's not been fully initialized

And so the obvious solution is to wait until the window has been fully initialized.

The simplest way to achieve this is to move your code that currently runs in OnShow into a handler for CM_SHOWINGCHANGED:

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

Implement it like this:

procedure TMyForm.CMShowingChanged(var Message: TMessage);
begin
  inherited; // this is what invokes OnShow
  if Visible then
  begin
    // do what you previously did in OnShow
  end;
end;

Andere Tipps

David Heffernan's solution gave me an idea and I solved this issue on my end.

I created following;

const
  WM_SHOW_MESSAGE = WM_USER + 1;

private
  procedure WMShowMessage(var Msg: TMessage); message WM_SHOW_MESSAGE; 

Inside constructor;

PostMessage(Handle, WM_SHOW_MESSAGE, 0, 0); 

And this will have the message box logic:

procedure MyMethod.WMShowMessage(var msg: TMessage); message WM_SHOW_MESSAGE;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top