Desperate - How to close wxDialog?

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 675
Joined: Tue Jul 26, 2016 2:00 pm

Desperate - How to close wxDialog?

Post by Wanderer82 »

In my main program I open a dialog:

Code: Select all

ProductDialog dialog(this);
dialog.ShowModal();
In the dialog I want to check something first using an "if"-clause. If this is true, the dialog should be displayed. If not, the "else"-clause should make the dialog close. I've tried everything "this->Close(TRUE)" or "this->Destroy()" or "EndModal(0)"... nothing works. "this"->Destroy" leads to a program crash. "this->Close(TRUE)" blocks the program from further input (meaning the window hasn't been destroyed). And "EndModal(0)" leads to an error message "assert "IsModal()" failed in EndModal(): EndModal() called for non modal dialog".

Code: Select all

ProductDialog::ProductDialog(wxWindow* parent,wxWindowID id,const wxPoint& pos,const wxSize& size)
{
	//(*Initialize(ProductDialog)

	if(Produkte_einlesen("Close") == true)
    {
    (...)
    }

    else
    {
        EndModal(0);
    }

	//*)
}    
    
Thanks for any help :-)
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: Desperate - How to close wxDialog?

Post by apoorv569 »

Wanderer82 wrote: Sat Jul 17, 2021 9:55 pm In my main program I open a dialog:

Code: Select all

ProductDialog dialog(this);
dialog.ShowModal();
In the dialog I want to check something first using an "if"-clause. If this is true, the dialog should be displayed. If not, the "else"-clause should make the dialog close. I've tried everything "this->Close(TRUE)" or "this->Destroy()" or "EndModal(0)"... nothing works. "this"->Destroy" leads to a program crash. "this->Close(TRUE)" blocks the program from further input (meaning the window hasn't been destroyed). And "EndModal(0)" leads to an error message "assert "IsModal()" failed in EndModal(): EndModal() called for non modal dialog".

Code: Select all

ProductDialog::ProductDialog(wxWindow* parent,wxWindowID id,const wxPoint& pos,const wxSize& size)
{
	//(*Initialize(ProductDialog)

	if(Produkte_einlesen("Close") == true)
    {
    (...)
    }

    else
    {
        EndModal(0);
    }

	//*)
}    
    
Thanks for any help :-)
You said if a condition is true, then the dialog should open else dialog should close. This doesn't make sense, if the condition is false, the dialog won't open so there is nothing to close. But here is a example of I would handle this (assuming I understood what you said correctly),

Code: Select all

    wxDialog dlg;
    bool condition = true;

    if (condition)  // if true dialog will show else won't
    {
        switch (dlg.ShowModal())
        {
            case wxID_OK:
                // What should happen when ok button is clicked
                break;
            case wxID_CANCEL:
                // What should happen when cancel button is click, usually nothing
                break;
            default:
                break;
        }
    }
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 675
Joined: Tue Jul 26, 2016 2:00 pm

Re: Desperate - How to close wxDialog?

Post by Wanderer82 »

Well, I think, I get the point in your answer and this (easy) solution definitely didn't leap into my mind ;-)

Actually I was trying to execute the function "Produkte_einlesen()" only inside the .cpp file of my dialog. Otherwise I would have to execute (I mean write) the code for every button in the main window that invokes a dialog separately. Integrated in the function there is an "access control" using a lockfile. If for any reason the lockfile is "locked" the window shouldn't open as the function returns a "false" and hasn't done what it's supposed to do (getting information for the dialog).

At the moment I can't think of any disadvantage using your solution but anyway, I'm interested in my mistake or a solution on how to close a window manually after an if-clause like in my example (without clicking on a button).
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Desperate - How to close wxDialog?

Post by doublemax »

The code flow of your solution is not clear. EndModal() is the right way to close a modal dialog, but it looks like you're calling it from the constructor, which doesn't make any sense. You'll get the assert, because the dialog isn't even shown at that point.
Use the source, Luke!
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 675
Joined: Tue Jul 26, 2016 2:00 pm

Re: Desperate - How to close wxDialog?

Post by Wanderer82 »

I was always thinking around such a thing... I mean that I might be calling EndModal() at the wrong place. So yes, I call it in the constructor, at the end in the "else"-clause.

How could I do what I want without having the dialog window shown before it is closed by the else-clause? Where do I have to put the EndModal() and how do I have to modify the constructor?
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Desperate - How to close wxDialog?

Post by doublemax »

Perform the check whether you want to show the dialog or not, before creating it.
Use the source, Luke!
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 675
Joined: Tue Jul 26, 2016 2:00 pm

Re: Desperate - How to close wxDialog?

Post by Wanderer82 »

Actually I wanted to keep the "check" inside another function to keep the code lean. So I remembered the "MyWorkerfunction" which you suggested in another question of mine. I used it with a CallAfter() in the constructor. If the check is FALSE I'm creating the dialog window without any widgets just to close it the next second in the "MyWorkerfunction" which is executed afterwards.
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Desperate - How to close wxDialog?

Post by doublemax »

If the check is FALSE I'm creating the dialog window without any widgets just to close it the next second in the "MyWorkerfunction" which is executed afterwards.
I didn't totally understand that, but it sounds dirty.

Can you explain the "bigger picture"? Maybe there is a better solution for what you're trying to achieve.
Use the source, Luke!
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 675
Joined: Tue Jul 26, 2016 2:00 pm

Re: Desperate - How to close wxDialog?

Post by Wanderer82 »

I'm still working on my project where teachers can order products. Everything revolves around a lockfile function. When a dialog window is called by the user from the main app, I have to read the products first from files. While doing this I want to make sure that noone else can write into these files at the same time. Inside the dialog constructor the function for reading the products is called. Inside this function the lockfile function is called. If it returns "FALSE" the products aren't read and the dialog shouldn't open respectively should be closed. I try to keep the main app lean, so I don't want to call the "read products"-function for each group of products.
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Desperate - How to close wxDialog?

Post by doublemax »

Hmm, but how do you handle it from a user's point of view? Sometimes when he wants to perform an action, the software just does nothing, or gives an "sorry, i'm busy" message?

Anyway, if you want to perform the check inside the dialog, i'd do it this way:

Code: Select all

MyDialog dlg(...);
if( dlg.IsReady() && dlg.ShowModal() == wxID_OK ) {
   // process dialog data here
}
For that, in the dialog constructor, you set a boolean flag, which is a member variable of the dialog. And you add a IsReady() method to the dialog to check the status of the flag.
Use the source, Luke!
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 675
Joined: Tue Jul 26, 2016 2:00 pm

Re: Desperate - How to close wxDialog?

Post by Wanderer82 »

The case that two users want to access files at the exact same time is extremely rare and only lasts for milliseconds, I'd guess. I have two options in the lockfile function. Either the problem lies in the instance of this user itself. This should never happen as the program should make sure to close the file handle after the reading / writing is done, but it's just to make sure, that nothing can go wrong. So if this case occurs, the user will get a message (which is generated from inside the lockfile function), that some kind of error has occured and he should restart the program. The second case is that another user (another instance of the program) tries to read / write a file at the exact same time. In this case the program waits for 1 second (twice) and checks, whether the handle is now able to open the lockfile. If after 2 seconds this is not the case, this means, that - for example - maybe an administrator is doing some longer work which needs to read / write files for some longer time. The user then will get the message, that it seems that an administrator is doing some maintenance on the program and that he / she should try it again.

I'm not quite sure about your code snippet. Is this what goes in the main.cpp? The constructor etc. for my dialog is in a separate .cpp-file. So I don't have to process dialog data in the main app. Everything happens inside the dialog.cpp. The main app just calls the dialog.
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Desperate - How to close wxDialog?

Post by doublemax »

Wanderer82 wrote: Mon Jul 19, 2021 6:47 pm I'm not quite sure about your code snippet. Is this what goes in the main.cpp? The constructor etc. for my dialog is in a separate .cpp-file. So I don't have to process dialog data in the main app. Everything happens inside the dialog.cpp. The main app just calls the dialog.
The code snippet is just some pseudo-code to show how the use of the dialog would look like after the change.


This is how the changes in the dialog would look like (plus adding the member variable m_isReady)

Code: Select all

ProductDialog::ProductDialog(wxWindow* parent,wxWindowID id,const wxPoint& pos,const wxSize& size)
{
	//(*Initialize(ProductDialog)

    if(Produkte_einlesen("Close") == true)
    {
      m_isReady = true;
    }
    else
    {
        m_isReady = false;
        return;
    }

	//*)
}    

bool ProductDialog::isReady() const { return m_isReady; }
Use the source, Luke!
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 675
Joined: Tue Jul 26, 2016 2:00 pm

Re: Desperate - How to close wxDialog?

Post by Wanderer82 »

This seems to work :-)

I just flipped around the "if"-clause and then, after the "else" I continue to build the dialog window. Does this look alright?

Code: Select all

ProductDialog::ProductDialog(wxWindow* parent,wxWindowID id,const wxPoint& pos,const wxSize& size)
{
    //(*Initialize(ProductDialog)
    if(Produkte_einlesen("Close") == FALSE)
    {
        m_isReady = false;
        return;
    }
    else
    {
    	wxFlexGridSizer* FlexGridSizer2;
	wxBoxSizer* BoxSizer2;
	wxBoxSizer* BoxSizer1;
	wxBoxSizer* BoxSizer[50];
	wxFlexGridSizer* FlexGridSizer1;

	Create(parent, wxID_ANY, _(category), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE, _T("wxID_ANY"));
	SetClientSize(wxDefaultSize);
	Move(wxDefaultPosition);
	BoxSizer1 = new wxBoxSizer(wxVERTICAL);
	//and so on ... 
And then in the main app, I just put a semicolon after the "if"-clause. Also ok?

Code: Select all

void Wall_MatFrame::OnBitmapButton1Click(wxCommandEvent& event)
{
    category = "Papier / Einzelblätter";

    ProductDialog dialog(this);
    if (dialog.isReady() && dialog.ShowModal() == wxID_OK);
}
You also put "wxID_OK" inside the if-clause. I don't have an OK-button. Can I just omit it?
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Desperate - How to close wxDialog?

Post by doublemax »

And then in the main app, I just put a semicolon after the "if"-clause. Also ok?
So you're not evaluating the return value of ShowModal()? In that case i would write it like this:

Code: Select all

if (dialog.isReady()) {
  dialog.ShowModal();
}
While your version does the same, it always looks like an error if there's a semicolon immediately after an "if-clause". So it should be avoided.
Use the source, Luke!
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 675
Joined: Tue Jul 26, 2016 2:00 pm

Re: Desperate - How to close wxDialog?

Post by Wanderer82 »

Ah, ok, that looks more familiar. I was wondering why the wxID_OK part.

Well, for what reason should I evaluate the return value of ShowModal()? The user has to close the dialog himself. In the dialog he can put products into the basket and when he's finished, he closes the dialog window.
Post Reply