Discussion:
[Foxgui-users] Fwd: Message Box closing FXApp
Julia Dudascik (Contractor)
2016-07-22 14:47:50 UTC
Permalink
Hello

I created a message box (FXWindow::error(...)), to notify the User of an
invalid input.
This message box is displayed, following the press of a button, which
checks a text box for the User input. When the OK button is pressed within
the Message Box, the application ends.
It goes to my return statement, after FXApp run(). It is almost like
Message Box tells the application to end when the OK button is pressed. Do
you know why it would do this?
I also tried to create a class that inherits from MessageBox, so I could
override the onCmdClicked button press. I also ran into an issue with this
because of some private constructors in message box. So I have 2 questions:

1.) When you press the OK button in the message box, what does it do
"behind the scenes"? Is it telling my application to end?

2.) If the only way around this is to create a class that inherits from
MessageBox, could you show me a sample on how to do that? I know it might
seem like a silly request, but I am really having a problem with it. I was
able to create other classes, which inherit from FXMainWindow, but for some
reason FXMessageBox seems to be set-up differently.

Thanks
Julia
JVZ
2016-07-22 15:50:36 UTC
Permalink
On Fri, 22 Jul 2016 10:47:50 -0400
Post by Julia Dudascik (Contractor)
Hello
I created a message box (FXWindow::error(...)), to notify the User of an
invalid input.
This message box is displayed, following the press of a button, which
checks a text box for the User input. When the OK button is pressed within
the Message Box, the application ends.
It goes to my return statement, after FXApp run(). It is almost like
Message Box tells the application to end when the OK button is pressed. Do
you know why it would do this?
The stopModal() ends all recursive event loops from the inner-most one up to
the one whose window matches the one passed. So make sure you call stopModal
with the proper window.
Post by Julia Dudascik (Contractor)
I also tried to create a class that inherits from MessageBox, so I could
override the onCmdClicked button press. I also ran into an issue with this
1.) When you press the OK button in the message box, what does it do
"behind the scenes"? Is it telling my application to end?
The button sends ID_CLICKED_OK to the dialogbox. This maps to the onCmdClicked()
handler, which passes MBOX_CLICKED_OK to stopModal().

As mentioned above, stopModal() breaks out of the modal loop of the FXMessageBox,
thus causing the dialog's execute() function to return, with error code MBOX_CLICKED_OK.

We're assuming you've popped the dialog up with the execute() member function;
the warning/error/info dialogs are supposed to be modal, i.e. block events to
other widgets. If you didn't, then thats your problem, because in that case
the event loop being stopped is the main loop....
Post by Julia Dudascik (Contractor)
2.) If the only way around this is to create a class that inherits from
MessageBox, could you show me a sample on how to do that? I know it might
seem like a silly request, but I am really having a problem with it. I was
able to create other classes, which inherit from FXMainWindow, but for some
reason FXMessageBox seems to be set-up differently.
FXMessageBox is a convenience-widget for often-encountered little popups that
require a yes/no answer (and a handful of other common choices). Cases where
you need to make your own would include custom layouts, unusual input choices,
and so on).

Typical use is something like:

const char* filename = "precious_data.csv";

if(FXMessageBox::question(this,MBOX_YES_NO,"Overwrite File","Do you want to overwrite file %s?",filename))==MBOX_CLICKED_YES){

/// Overwrite the file ...

}


The first argument to FXMessageBox::question() would be the owning window, i.e.
the main window or dialog from which this dialog is spawned; this ensures that the
message box knows which other window to stay on top off.

If there is no such window, you can pass the FXApp pointer instead; this would make
the message box a top-level window, and as a consequence have no particular stacking
order w.r.t. other windows (which means it could be below another window!).

I have not found message boxes to be all that problematic, so if you're seeing something
unusual like cliking away the message box closing down the entire application, it is almost
100% sure something else is going on; perhaps some sort of bug elsewhere in the code.


Regards,

-- JVZ




+----------------------------------------------------------------------------+
| Copyright (C) 10:20 07/22/2016 Jeroen van der Zijp. All Rights Reserved. |
+----------------------------------------------------------------------------+
Julia Dudascik (Contractor)
2016-07-22 17:14:30 UTC
Permalink
I have looked into what you said, but I am a bit confused. I am just
learning FOX, so please forgive me if I seem completely lost. I have a
class NewItemWindow which inherits from FXMainWindow. This creates a window
in my FXApp and this window has a button. When the button is pressed, a
message box is displayed. When the OK button is pressed on my Message Box,
the whole application ends. I do not want for the application to end. How
can I stop it from ending? I use the default commands to create the message
box (FXMessageBox::error(...)) within the callback for pressing the button,
so I do not understand when you say "execute" function to return? I also
tried to call stopModal() and that still ends my application. I am using
FXApp run as my loop to keep the application running. Is the stopModal()
from pressing the OK button, causing the application to end? How can I
prevent it from ending? I would like the application to continue running.
Also if I display a window within my application do I need to call runPopup
(FXApp)? It does not fix the problem though.

Thanks
Post by JVZ
On Fri, 22 Jul 2016 10:47:50 -0400
Post by Julia Dudascik (Contractor)
Hello
I created a message box (FXWindow::error(...)), to notify the User of an
invalid input.
This message box is displayed, following the press of a button, which
checks a text box for the User input. When the OK button is pressed within
the Message Box, the application ends.
It goes to my return statement, after FXApp run(). It is almost like
Message Box tells the application to end when the OK button is pressed. Do
you know why it would do this?
The stopModal() ends all recursive event loops from the inner-most one up to
the one whose window matches the one passed. So make sure you call stopModal
with the proper window.
Post by Julia Dudascik (Contractor)
I also tried to create a class that inherits from MessageBox, so I could
override the onCmdClicked button press. I also ran into an issue with this
because of some private constructors in message box. So I have 2
1.) When you press the OK button in the message box, what does it do
"behind the scenes"? Is it telling my application to end?
The button sends ID_CLICKED_OK to the dialogbox. This maps to the onCmdClicked()
handler, which passes MBOX_CLICKED_OK to stopModal().
As mentioned above, stopModal() breaks out of the modal loop of the FXMessageBox,
thus causing the dialog's execute() function to return, with error code MBOX_CLICKED_OK.
We're assuming you've popped the dialog up with the execute() member function;
the warning/error/info dialogs are supposed to be modal, i.e. block events to
other widgets. If you didn't, then thats your problem, because in that case
the event loop being stopped is the main loop....
Post by Julia Dudascik (Contractor)
2.) If the only way around this is to create a class that inherits from
MessageBox, could you show me a sample on how to do that? I know it might
seem like a silly request, but I am really having a problem with it. I was
able to create other classes, which inherit from FXMainWindow, but for
some
Post by Julia Dudascik (Contractor)
reason FXMessageBox seems to be set-up differently.
FXMessageBox is a convenience-widget for often-encountered little popups that
require a yes/no answer (and a handful of other common choices). Cases where
you need to make your own would include custom layouts, unusual input choices,
and so on).
const char* filename = "precious_data.csv";
if(FXMessageBox::question(this,MBOX_YES_NO,"Overwrite File","Do you
want to overwrite file %s?",filename))==MBOX_CLICKED_YES){
/// Overwrite the file ...
}
The first argument to FXMessageBox::question() would be the owning window, i.e.
the main window or dialog from which this dialog is spawned; this ensures that the
message box knows which other window to stay on top off.
If there is no such window, you can pass the FXApp pointer instead; this would make
the message box a top-level window, and as a consequence have no particular stacking
order w.r.t. other windows (which means it could be below another window!).
I have not found message boxes to be all that problematic, so if you're seeing something
unusual like cliking away the message box closing down the entire application, it is almost
100% sure something else is going on; perhaps some sort of bug elsewhere in the code.
Regards,
-- JVZ
+----------------------------------------------------------------------------+
| Copyright (C) 10:20 07/22/2016 Jeroen van der Zijp. All Rights Reserved. |
+----------------------------------------------------------------------------+
JVZ
2016-07-28 14:04:12 UTC
Permalink
On Wed, 27 Jul 2016 14:20:30 -0400
Hello
In order to debug the problem where my application crashes when I call
close() on one of my created windows, I compiled the FOX code in with my
source code. When it crashed, I was then able to break on the line in the
FOX source code. It is crashing in the function dispatchEvent() in
FXApp.cpp. The "iMsg" it receives is WM_MOUSEMOVE. It detects that the
window has changed. So it goes to the if block "if (cursorWindow !=
window)". In this case, my "cursorWindow" is the window I just destroyed
and "window" is my other still existing window. The "cursorWindow" does not
really exist anymore, so when it calls commonAncestor(window,
cursorWindow), it crashes at the line where it tries to get the
cursorWindow parent "p2=p2->parent". What puzzles me is that it got passed
the if block, if (!b). I would think the cursorWindow would be null because
it was deleted during the close(). When I look at the variable cursorWindow
in the debugger it has a series of question marks next to all of its
fields.
Question really is, how did you get back into the event loop? When a window
is destroyed, all references to it (in FXApp, or its parent) are fixed.

So, this sequence of events is not possible.

Besides, if you close() your topwindow, close() will (after possibly
issueing a notify callback) itself destroy the window. After close(), therefore,
it is not possible to have any reference to the window anymore.
I have been trying to figure out how to set cursorWindow to th window that
still exists. I even tried to send a SEL_ENTER event to the window that
does exist. This event is processed, but the cursorWindow does not update.
This is done automatically when the window is destroyed, in ~FXWindow. So
its impossible for cursorWindow to point to a deleted (destructed) window.
I do not want to modify the FOX code to fit my situation, and I am not sure
if there is something else I am missing. Please tell me how I can set
cursorWindow to the window that exists. Or if there is something else I
need to do prior to calling close() on the window.
You don't change cursorWindow yourself, the library changes it for you.
As mentioned above, its impossible for cursorWindow to point to a deleted
window since the FXWindow destructor, executed for ANY widget derived from
it, will take care of that.

Now its possible for you to have written code that doesn't use FOX in the
way intended. I have written various FAQ's to set people on the right
tracks, insofar as getting things done and avoiding some common pitfalls.

Common pitfalls include referencing deleted objects (this is more of a
general progamming issue, in fact). However, you may not have realized
that close() will ultimately call the FXTopWindow's destructor.

A typical sequence of events w.r.t. closing a toplevel window. Note, for
toplevel windows, the system's user interface manages some aspects; for
instance, it may place an X button on the corner of the window.

If a user presses the X, a message is sent to the FXTopWindow, SEL_CLOSE.
This then calls close() to close the window. To avoid accidental loss of
data, close() may call upon a callback to your handler code. In a non-trivial
application such as yours, this handler would (a) prompt the user to save his/her
data to disk, (b) or cancel the closing.

In the case that close() is to proceed, the callback handler should return 0
("no objection"). [This choice of return value means if NO handler is set, or
the handler didn't handle the event, the default action will be to proceed
with the closing].

After returning from the handler, the FXTopWindow will check if there's another
toplevel window left in the application; if there is, then it'll just self-
destruct. Otherwise, if this is the last window, it will send ID_QUIT to the
FXApp in order to shut down all event loops, and eventually run() will return
with no errors.
From the perspective of the application programmer, if you called close()
programmatically and it returned true, then no further references to the
window should be made, as it is now gone.


Hope this helps,

-- JVZ




+----------------------------------------------------------------------------+
| Copyright (C) 15:50 07/25/2016 Jeroen van der Zijp. All Rights Reserved. |
+----------------------------------------------------------------------------+

------------------------------------------------------------------------------
Julia Dudascik (Contractor)
2016-07-22 17:15:33 UTC
Permalink
I have looked into what you said, but I am a bit confused. I am just
learning FOX, so please forgive me if I seem completely lost. I have a
class NewItemWindow which inherits from FXMainWindow. This creates a window
in my FXApp and this window has a button. When the button is pressed, a
message box is displayed. When the OK button is pressed on my Message Box,
the whole application ends. I do not want for the application to end. How
can I stop it from ending? I use the default commands to create the message
box (FXMessageBox::error(...)) within the callback for pressing the button,
so I do not understand when you say "execute" function to return? I also
tried to call stopModal() and that still ends my application. I am using
FXApp run as my loop to keep the application running. Is the stopModal()
from pressing the OK button, causing the application to end? How can I
prevent it from ending? I would like the application to continue running.
Also if I display a window within my application do I need to call runPopup
(FXApp)? It does not fix the problem though.

Thanks
Post by JVZ
On Fri, 22 Jul 2016 10:47:50 -0400
Post by Julia Dudascik (Contractor)
Hello
I created a message box (FXWindow::error(...)), to notify the User of an
invalid input.
This message box is displayed, following the press of a button, which
checks a text box for the User input. When the OK button is pressed within
the Message Box, the application ends.
It goes to my return statement, after FXApp run(). It is almost like
Message Box tells the application to end when the OK button is pressed. Do
you know why it would do this?
The stopModal() ends all recursive event loops from the inner-most one up to
the one whose window matches the one passed. So make sure you call stopModal
with the proper window.
Post by Julia Dudascik (Contractor)
I also tried to create a class that inherits from MessageBox, so I could
override the onCmdClicked button press. I also ran into an issue with this
because of some private constructors in message box. So I have 2
1.) When you press the OK button in the message box, what does it do
"behind the scenes"? Is it telling my application to end?
The button sends ID_CLICKED_OK to the dialogbox. This maps to the onCmdClicked()
handler, which passes MBOX_CLICKED_OK to stopModal().
As mentioned above, stopModal() breaks out of the modal loop of the FXMessageBox,
thus causing the dialog's execute() function to return, with error code MBOX_CLICKED_OK.
We're assuming you've popped the dialog up with the execute() member function;
the warning/error/info dialogs are supposed to be modal, i.e. block events to
other widgets. If you didn't, then thats your problem, because in that case
the event loop being stopped is the main loop....
Post by Julia Dudascik (Contractor)
2.) If the only way around this is to create a class that inherits from
MessageBox, could you show me a sample on how to do that? I know it might
seem like a silly request, but I am really having a problem with it. I was
able to create other classes, which inherit from FXMainWindow, but for
some
Post by Julia Dudascik (Contractor)
reason FXMessageBox seems to be set-up differently.
FXMessageBox is a convenience-widget for often-encountered little popups that
require a yes/no answer (and a handful of other common choices). Cases where
you need to make your own would include custom layouts, unusual input choices,
and so on).
const char* filename = "precious_data.csv";
if(FXMessageBox::question(this,MBOX_YES_NO,"Overwrite File","Do you
want to overwrite file %s?",filename))==MBOX_CLICKED_YES){
/// Overwrite the file ...
}
The first argument to FXMessageBox::question() would be the owning window, i.e.
the main window or dialog from which this dialog is spawned; this ensures that the
message box knows which other window to stay on top off.
If there is no such window, you can pass the FXApp pointer instead; this would make
the message box a top-level window, and as a consequence have no particular stacking
order w.r.t. other windows (which means it could be below another window!).
I have not found message boxes to be all that problematic, so if you're seeing something
unusual like cliking away the message box closing down the entire application, it is almost
100% sure something else is going on; perhaps some sort of bug elsewhere in the code.
Regards,
-- JVZ
+----------------------------------------------------------------------------+
| Copyright (C) 10:20 07/22/2016 Jeroen van der Zijp. All Rights Reserved. |
+----------------------------------------------------------------------------+
Loading...