wxDialog won't close

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: 670
Joined: Tue Jul 26, 2016 2:00 pm

wxDialog won't close

Post by Wanderer82 »

I'm really totally unable to close a wxDialog. I don't know the differences between EndModaL(0), EndModal(wxID_CANCEL), return;
I'm so frustrated. My wxDialog won't close although no matter which statement I use. The interesting thing is that if I click the button a second time the dialog will close. Maybe someone has an idea. This is an OnClickButton handler and at the end it should close the dialog.

Code: Select all

void Printer_List::OnButton10Click(wxCommandEvent& event)
{
    wxArrayString Chosen_Printers;
    wxArrayInt Chosen_Printers_Items;

    int i = 0;
    int items_Anzahl = ListBox2->GetCount();

    if(items_Anzahl == 0) //wenn keine Drucker gewählt sind, kommt eine Meldung.
    {
        wxMessageDialog checkSelection(0,("Es wurden keine Drucker gewählt."),"",wxYES|wxNO);
        checkSelection.SetYesNoLabels(_("OK"),_("Erneut auswählen"));
        if(checkSelection.ShowModal() == wxID_YES)
        {
            _User.UserCancel = 1;
            EndModal(wxID_CANCEL);
            return;
        }
        else
        {
            return;
        }
    }

    Chosen_Printers = ListBox2->GetStrings();

    i = 0;
    while(i < items_Anzahl)
    {
        wxBusyInfo wait ("Drucker werden installiert ...");
        Install_Printer(Chosen_Printers[i]);
        Sleep(3000);
        _User.UserDrucker_installiert[i] = Chosen_Printers[i];
        i = i + 1;
        _User.UserCancel = 1;
    }
    EndModal(wxID_CANCEL);
    return;
}
The wxDialog is called from this function:

Code: Select all

void Printer_Install()
{
    {wxBusyInfo wait("Zugeordnete Drucker werden gesucht...");

        Sleep(2000);
    }
    if(_User.UserDrucker[0] == "")
    {
        wxMessageDialog checkPrinter(0,("Leider wurde kein diesem Benutzer zugeordneter Drucker gefunden."),"",wxYES|wxNO);
        checkPrinter.SetYesNoLabels(_("Drucker aus Liste wählen"),_("Einrichtung überspringen"));
        if(checkPrinter.ShowModal() == wxID_YES)
        {
            Printer_List dialog(0);
            dialog.ShowModal();
        }
    }
    else
    {
        if(_User.UserDrucker[1] == "")
        {
            wxMessageDialog checkPrinter(0,("Der Drucker \"" + _User.UserDrucker[0] + "\" wurde automatisch ermittelt.\n\nSoll der Drucker installiert werden?"),"",wxYES|wxNO);
            checkPrinter.SetYesNoLabels(_("Drucker installieren"),_("Andere/n Drucker suchen"));
            if(checkPrinter.ShowModal() == wxID_YES)
            {
                {wxBusyInfo wait("Drucker wird installiert...");
                Install_Printer(_User.UserDrucker[0]);
                Sleep(5000);
                _User.UserDrucker_installiert[0] = _User.UserDrucker[0];
                }
                Standarddrucker dialog(0);
                dialog.ShowModal();
            }
            else
            {
                Printer_List dialog(0);
                dialog.ShowModal();
                if(_User.UserDrucker_installiert[0] == "")
                {
                    return;
                }
                else
                {
                    Standarddrucker dialog2(0);
                    dialog.ShowModal();
                }
            }
        }
        else
        {
            MorePrinters dialog(0);
            dialog.ShowModal();
            if(_User.UserDrucker_installiert[0] == "")
            {
                return;
            }
            else
            {
                Standarddrucker dialog2(0);
                dialog.ShowModal();
            }
        }
    }
}
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDialog won't close

Post by doublemax »

I can't spot any obvious mistake, but without knowing which code path is taken, it's also hard to know where to look.

First thing you should test: Put

Code: Select all

EndModal(wxID_CANCEL);
return;
directly at the beginning of OnButton10Click() and see what happens.
Use the source, Luke!
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

Re: wxDialog won't close

Post by Wanderer82 »

Did it and the dialog was closed immediately.

In my main app / window I call the function that I provided above.

The interesting thing is that if I click the button to install the printers twice (so after the first installation I click again and install again) then the window closes as it should.
Last edited by Wanderer82 on Sun Jun 26, 2022 8:28 pm, edited 1 time in total.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDialog won't close

Post by doublemax »

Wanderer82 wrote: Sun Jun 26, 2022 8:21 pm Did it and the dialog was closed immediately.
That's a good start.

I have a suspicion (more of a wild guess). Make sure all other dialogs are not only closed, but also destroyed before closing the dialog itself.

Change code like this:

Code: Select all

wxMessageDialog checkSelection(0,("Es wurden keine Drucker gewählt."),"",wxYES|wxNO);
checkSelection.SetYesNoLabels(_("OK"),_("Erneut auswählen"));
if(checkSelection.ShowModal() == wxID_YES)
{
    _User.UserCancel = 1;
    EndModal(wxID_CANCEL);
    return;
}

To:

Code: Select all

int ret = 0;
{
  wxMessageDialog checkSelection(0,("Es wurden keine Drucker gewählt."),"",wxYES|wxNO);
  checkSelection.SetYesNoLabels(_("OK"),_("Erneut auswählen"));
  ret = checkSelection.ShowModal();
}

if(ret == wxID_YES)
{
  _User.UserCancel = 1;
  EndModal(wxID_CANCEL);
  return;
}
The additional block makes sure that the wxMessageDialog is destroyed before you call EndModal().

BTW: The value you pass to EndModal() is just the return value of ShowModal() in the calling function.
Use the source, Luke!
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

Re: wxDialog won't close

Post by Wanderer82 »

Unfortunately that didn't help.

You can see the wxDialog disappear very quickly and then reappear as if it is called again from somewhere. The strange this is that it happens only once.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDialog won't close

Post by doublemax »

Put a wxLogMessage output in the Printer_List constructor. Maybe it does actually close and is opened again. Than the issue would be one level higher, in the code that shows the Printer_List dialog.
Use the source, Luke!
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

Re: wxDialog won't close

Post by Wanderer82 »

So I put it right under

Code: Select all

Printer_List::Printer_List(wxWindow* parent,wxWindowID id,const wxPoint& pos,const wxSize& size)
{
	//(*Initialize(Printer_List)
And what is "output"? Is this a string or how do I declare / define that and where do I find this output afterwards?
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDialog won't close

Post by doublemax »

wxLogMessage just shows a message on screen. In this case it's just a simple debugging tool that lets us see if it's called once or twice.
Use the source, Luke!
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

Re: wxDialog won't close

Post by Wanderer82 »

But when I put it there I get an error:

statement cannot resolve address of overloaded function|

Ah you mean it's like a wxMessageBox where I have to put a string... that works ;-)

Hm, as I have rearranged my program (main window) somehow my problem has strangely disappeared. But I still have another one that I haven't mentioned yet. If a user opens the printer list from the wxDialog that pops up if a user has more than 1 printer and he chooses 2 or more printers from the list, after the second printer install the program crashes without an error. If he chooses only 1 printer, everything is fine. If the chooses only from the printers in the wxDialog itself, everything works fine.

Here is the code for my wxDialog where the user has the choise to choose from the found 2 or 3 printers or if he wants he can open the list of all printers as well:

Code: Select all

#include "MorePrinters.h"
#include "User_Info.h"
#include "Funktionen.h"

//(*InternalHeaders(MorePrinters)
#include <wx/font.h>
#include <wx/intl.h>
#include <wx/string.h>
//*)

//(*IdInit(MorePrinters)
const long MorePrinters::ID_STATICTEXT1 = wxNewId();
const long MorePrinters::ID_STATICTEXT2 = wxNewId();
const long MorePrinters::ID_CHECKBOX1 = wxNewId();
const long MorePrinters::ID_CHECKBOX2 = wxNewId();
const long MorePrinters::ID_CHECKBOX3 = wxNewId();
const long MorePrinters::ID_BUTTON1 = wxNewId();
const long MorePrinters::ID_BUTTON2 = wxNewId();
const long MorePrinters::ID_BUTTON3 = wxNewId();
const long MorePrinters::ID_PANEL1 = wxNewId();
//*)

BEGIN_EVENT_TABLE(MorePrinters,wxDialog)
	//(*EventTable(MorePrinters)
	//*)
END_EVENT_TABLE()

MorePrinters::MorePrinters(wxWindow* parent,wxWindowID id,const wxPoint& pos,const wxSize& size)
{
	//(*Initialize(MorePrinters)
	wxBoxSizer* BoxSizer4;
	wxBoxSizer* BoxSizer2;
	wxBoxSizer* BoxSizer1;
	wxBoxSizer* BoxSizer3;

	Create(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
	BoxSizer1 = new wxBoxSizer(wxHORIZONTAL);
	Panel1 = new wxPanel(this, ID_PANEL1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("ID_PANEL1"));
	BoxSizer2 = new wxBoxSizer(wxVERTICAL);
	StaticText1 = new wxStaticText(Panel1, ID_STATICTEXT1, _("Es wurden mehrere Drucker automatisch ermittelt.\n\n Zur Installation gewünschte Drucker markieren:"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT1"));
	wxFont StaticText1Font(12,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL,false,wxEmptyString,wxFONTENCODING_DEFAULT);
	StaticText1->SetFont(StaticText1Font);
	BoxSizer2->Add(StaticText1, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, wxDLG_UNIT(Panel1,wxSize(5,0)).GetWidth());
	StaticText2 = new wxStaticText(Panel1, ID_STATICTEXT2, _("Hinweis: Standarddrucker kann im nächsten Schritt gewählt werden\nHinweis 2: Der Grosskopierer Papercut (Sharp) ist bereits vorinstalliert"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER, _T("ID_STATICTEXT2"));
	wxFont StaticText2Font(10,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL,false,_T("Arial"),wxFONTENCODING_DEFAULT);
	StaticText2->SetFont(StaticText2Font);
	BoxSizer2->Add(StaticText2, 0, wxBOTTOM|wxALIGN_CENTER_HORIZONTAL, 15);
	BoxSizer4 = new wxBoxSizer(wxHORIZONTAL);
	CheckBox1 = new wxCheckBox(Panel1, ID_CHECKBOX1, _(_User.UserDrucker[0]), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX1"));
	CheckBox1->SetValue(false);
	BoxSizer4->Add(CheckBox1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	CheckBox2 = new wxCheckBox(Panel1, ID_CHECKBOX2, _(_User.UserDrucker[1]), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX2"));
	CheckBox2->SetValue(false);
	BoxSizer4->Add(CheckBox2, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	if(_User.UserDrucker[2] != "")
    {
        CheckBox3 = new wxCheckBox(Panel1, ID_CHECKBOX3, _(_User.UserDrucker[2]), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX3"));
        CheckBox3->SetValue(false);
        BoxSizer4->Add(CheckBox3, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    }
	BoxSizer2->Add(BoxSizer4, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	BoxSizer3 = new wxBoxSizer(wxHORIZONTAL);
	Button1 = new wxButton(Panel1, ID_BUTTON1, _("OK"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON1"));
	BoxSizer3->Add(Button1, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	Button2 = new wxButton(Panel1, ID_BUTTON2, _("Andere(n) Drucker suchen"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON2"));
	BoxSizer3->Add(Button2, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	Button3 = new wxButton(Panel1, ID_BUTTON3, _("Einrichtung abbrechen"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON3"));
	BoxSizer3->Add(Button3, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	BoxSizer2->Add(BoxSizer3, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	Panel1->SetSizer(BoxSizer2);
	BoxSizer2->Fit(Panel1);
	BoxSizer2->SetSizeHints(Panel1);
	BoxSizer1->Add(Panel1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
	SetSizer(BoxSizer1);
	BoxSizer1->Fit(this);
	BoxSizer1->SetSizeHints(this);
	Center();

    Connect(ID_BUTTON1,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&MorePrinters::OnButton1Click);
	Connect(ID_BUTTON2,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&MorePrinters::OnButton2Click);
    Connect(ID_BUTTON3,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&MorePrinters::OnButton3Click);

	//*)
}

MorePrinters::~MorePrinters()
{
	//(*Destroy(MorePrinters)
	//*)
}

void MorePrinters::OnButton1Click(wxCommandEvent& event)
{
    _User.UserCancel = 0;
    int Printer_Count = 2;
    if(_User.UserDrucker[3] != "")
    {
        Printer_Count = 3;
    }

    if(Printer_Count == 2)
    {
        if(CheckBox1->GetValue() == false && CheckBox2->GetValue() == false)
        {
            wxMessageDialog checkSelection(0,("Es wurden keine Drucker gewählt."),"",wxYES|wxNO);
            checkSelection.SetYesNoLabels(_("Keine Drucker installieren"),_("Drucker erneut wählen"));
            if(checkSelection.ShowModal() == wxID_YES)
            {
                _User.UserCancel = 1;
                EndModal(wxID_CANCEL);
                return;
            }
            else
            {
                //_User.UserCancel = 1;
                return;
            }
        }
    }

    if(Printer_Count == 3)
    {
        if(CheckBox1->GetValue() == false && CheckBox2->GetValue() == false && CheckBox3->GetValue() == false)
        {
            wxMessageDialog checkSelection(0,("Es wurden keine Drucker gewählt."),"",wxYES|wxNO);
            checkSelection.SetYesNoLabels(_("OK"),_("Drucker erneut wählen"));
            if(checkSelection.ShowModal() == wxID_YES)
            {
                _User.UserCancel = 1;
                EndModal(wxID_CANCEL);
                return;
            }
            else
            {
                //_User.UserCancel = 1;
                return;
            }
        }
    }

    int i = 0; //Zähler, um UserDrucker_installiert zu füllen; wird nur hochgezählt, wenn ein Drucker installiert wird, sonst bleibt es null, wichtig!
    if(CheckBox1->GetValue() == true)
    {
        Install_Printer(_User.UserDrucker[0]);
        wxBusyInfo wait("Drucker werden installiert...\nEs kann eine Bestätigung zur Treiberinstallation nötig sein!");
        _User.UserDrucker_installiert[i] = _User.UserDrucker[0];
        i = i + 1;
        Sleep(5000);
    }

    if(CheckBox2->GetValue() == true)
    {
        Install_Printer(_User.UserDrucker[1]);
        wxBusyInfo wait("Drucker werden installiert...\nEs kann eine Bestätigung zur Treiberinstallation nötig sein!");
        _User.UserDrucker_installiert[i] = _User.UserDrucker[1];
        i = i + 1;
        Sleep(5000);
    }

    if(Printer_Count == 3)
    {
        if(CheckBox3->GetValue() == true)
        {
            Install_Printer(_User.UserDrucker[2]);
            wxBusyInfo wait("Drucker werden installiert...\nJe nach Drucker kann eine Bestätigung zur Treiberinstallation nötig sein!");
            _User.UserDrucker_installiert[i] = _User.UserDrucker[2];
            Sleep(5000);
        }
    }

    if(_User.UserCancel == 0)
    {
        EndModal(wxID_CANCEL);
        Standarddrucker dialog3(this);
        dialog3.ShowModal();
    }

    _User.UserCancel = 1;
    EndModal(wxID_CANCEL);
    return;
}
void MorePrinters::OnButton2Click(wxCommandEvent& event)
{
    Printer_List dialog2(0);
    dialog2.ShowModal();

    EndModal(wxID_CANCEL);

    Standarddrucker dialog4(this);
    dialog4.ShowModal();

    //return;
}

void MorePrinters::OnButton3Click(wxCommandEvent& event)
{
    _User.UserCancel = 1;
    EndModal(wxID_CANCEL);
    return;
}
Last edited by Wanderer82 on Sun Jun 26, 2022 9:44 pm, edited 2 times in total.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDialog won't close

Post by doublemax »

wxMessageBox should work too in this case, it might even be better...
Use the source, Luke!
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

Re: wxDialog won't close

Post by Wanderer82 »

I posted after you had posted ;-) So, I have another problem as you can see :roll:

I have to add that the acton in happens on "OnButton2Click"
Last edited by Wanderer82 on Sun Jun 26, 2022 9:59 pm, edited 1 time in total.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDialog won't close

Post by doublemax »

That sounds like an issue that's easy to find when using a debugger. I think it's time for you to learn how to use one ;)

If i had to guess, it's probably an invalid index somewhere. E.g. in expressions like "_User.UserDrucker[2]" or "_User.UserDrucker_installiert[ i ]".
Use the source, Luke!
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

Re: wxDialog won't close

Post by Wanderer82 »

Hm, I'll look after that. But I mean I call this dialog the same as when I call it in the other cases. Actually there should be no difference.

EDIT:

Okay, I really have no idea now what's going on. Now I tried to leave this "extra" dialog from which the printer list was opened and get back to the original dialog. So it's actually the exact same code as with the other printer installs but still I get a crash.

Ok, I now know for sure that the problem is laying in this extra dialog. Eventhough I don't do anything else than clicking a button and returning to the dialog before I get the crash. But when I don't go into the extra dialog, everything works fine.
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

Re: wxDialog won't close

Post by Wanderer82 »

Hm, I'm getting closer...

The problem seems is in fact to be in _User.UserDrucker_installiert[].

This is an array which I initialized in a User class like this: UserDrucker_installiert[60] = {""}
Now I changed this to only UserDrucker_installiert[60]; without further giving values to it. It's interesting now because until now during the printer installation the printer name stayed inside the variable, eg. if there were two printers chosen [0] and [1] was filled with the name. And after the installation part the value in [1] was missing. Now that I took away the {""}" declaration the value in [1] remains. But still there seems to be a problem in the next dialog where I need these values because I make radio buttons to let the user choose a standard printer from the printers that are installed. Although the values are in the correct place of the array the program crashes in this loop and now it happens all the times not only when I used this extra wxDialog inbetween.

Code: Select all

while(_User.UserDrucker_installiert[i] != "")
    {
        wxMessageBox(_User.UserDrucker_installiert[i]);
        RadioButton[i+2] = new wxRadioButton(Panel1, ID_RADIOBUTTON[i+2], _(_User.UserDrucker_installiert[i]), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_RADIOBUTTON[i+2]"));
        BoxSizer3->Add(RadioButton[i+2], 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
        i = i + 1;
    }
Now I also get a warning:

array subscript is above array bounds [-Warray-bounds]|
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

Re: wxDialog won't close

Post by Wanderer82 »

Okay the problem is fixed. The RadioButton array that I created didn't have a value when I initialized it. Now at least the dialog pops up but now when I want to set the default printer the program crashes. But maybe I will finde out... hopefully ;-)
Post Reply