Search code examples
c++wxwidgets

How can I correctly open my WxFrame loaded from an XML resource file?


I'm relatively new to both C++ and Wx, so I've been doing a lot of blundering around trying to get this to work over the past few hours, but I seem to have hit a figurative brick wall with this issue.

This code compiles with no errors, but when run, it does nothing. It simply remains running until terminated (e.g. with Ctrl-C), but a window never opens.

Here is the C++ source:

#include <wx/wxprec.h>

#ifndef WX_PRECOMP
    #include <wx/wx.h>
#endif

#include <wx/xrc/xmlres.h>


class MyApp : public wxApp {
public:
    virtual bool OnInit();
};

wxIMPLEMENT_APP(MyApp);

bool MyApp::OnInit() {
    wxXmlResource::Get()->InitAllHandlers();
    wxXmlResource::Get()->Load("res.xrc");

    wxFrame MainFrame;
    wxXmlResource::Get()->LoadFrame(&MainFrame, NULL, "MainFrame");
    MainFrame.Show(true);

    return true;
}

And here is the accompanying XML file, res.xrc, which should produce just an empty frame containing a sizer within a panel:

<?xml version="1.0" ?>

<resource>
    <object class="wxFrame" name="MainFrame" title="Test">
        <object class="wxPanel" name="TopLevelPanel">        
        
           <object class="wxBoxSizer" name="TopLevelSizer">
                <orient>wxVERTICAL</orient>
           </object>
        </object>
    </object>
</resource> 

Introducing an error into the XML - for example, adding some spurious characters which are not valid XML - does cause a window to open, and it looks like this (under Linux): enter image description here

How can I modify my code so that the window will open correctly?


Solution

  • Your MainFrame gets destroyed when you reach the end of the function, which is not at all what you want for a frame which is supposed to exist for a long time. The simplest correct thing to do is

    wxFrame* MainFrame = wxXmlResource::Get()->LoadFrame(NULL, "MainFrame");
    if ( !MainFrame ) {
        wxLogError("Failed to load the main frame from the resources.");
        return false;
    }
    MainFrame->Show();
    

    i.e. just let XRC create a new frame for you (the overload taking the pointer is mostly useful when creating this frame itself, i.e. for passing this in it).