News:

When registered with our forums, feel free to send a "here I am" post here to differ human beings from SPAM bots.

Main Menu

wxSmith use bad constructor for wxStaticBoxSizer

Started by LR83, January 07, 2026, 11:17:45 AM

Previous topic - Next topic

LR83

The documentation say that the child of a wxStaticBoxSizer should be the wxBoxSizer and not the owner of the wxStaticBoxSizer.
On Linux, for example, I can see the following warning on the console:
Element wxStaticText of wxStaticBoxSizer should be created as child of its wxStaticBox and not of wxDialog.

I test several builder on a very simple case: a dialog window with a wxStaticBoxSizer that contain a wxStaticText and a wxTextCtrl.
With wxSmith:
QuoteDialogFormSmith::DialogFormSmith(wxWindow* parent,wxWindowID id)
{
    //(*Initialize(DialogFormSmith)
    wxStaticBoxSizer* StaticBoxSizer1;

    Create(parent, id, _("Test with wxSmith"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE, _T("id"));
    StaticBoxSizer1 = new wxStaticBoxSizer(wxHORIZONTAL, this, _("StaticBoxSizer"));
    StaticText1 = new wxStaticText(this, wxID_ANY, _("Label"), wxDefaultPosition, wxDefaultSize, 0);
    StaticBoxSizer1->Add(StaticText1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    TextCtrl1 = new wxTextCtrl(this, wxID_ANY, _("Text"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
    StaticBoxSizer1->Add(TextCtrl1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    SetSizer(StaticBoxSizer1);
    StaticBoxSizer1->SetSizeHints(this);
    //*)
}

with wxFormBuilder:
QuoteDialogFormBuilder::DialogFormBuilder( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
   this->SetSizeHints( wxDefaultSize, wxDefaultSize );

   wxStaticBoxSizer* sbSizer1;
   sbSizer1 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("StaticBoxSizer") ), wxHORIZONTAL );

   m_staticText1 = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("MyLabel"), wxDefaultPosition, wxDefaultSize, 0 );
   m_staticText1->Wrap( -1 );
   sbSizer1->Add( m_staticText1, 0, wxALL, 5 );

   m_textCtrl1 = new wxTextCtrl( sbSizer1->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
   sbSizer1->Add( m_textCtrl1, 0, wxALL, 5 );


   this->SetSizer( sbSizer1 );
   this->Layout();
   sbSizer1->Fit( this );

   this->Centre( wxBOTH );
}

With wxGlade:
QuoteDialogFormGlade::DialogFormGlade(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style):
    wxDialog(parent, id, title, pos, size, wxDEFAULT_DIALOG_STYLE)
{
    // begin wxGlade: DialogFormGlade::DialogFormGlade
    SetTitle(wxT("Test with wxGlade"));
    wxStaticBoxSizer* sizer_1 = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, wxT("StaticBoxSizer")), wxHORIZONTAL);
    wxStaticText* label_1 = new wxStaticText(sizer_1->GetStaticBox(), wxID_ANY, wxT("Label"));
    sizer_1->Add(label_1, 0, 0, 0);
    text_ctrl_1 = new wxTextCtrl(sizer_1->GetStaticBox(), wxID_ANY, wxEmptyString);
    sizer_1->Add(text_ctrl_1, 0, 0, 0);

    SetSizer(sizer_1);
    sizer_1->Fit(this);
    Layout();
    // end wxGlade
}

The codes generated by wxFormBuilder and wxGlade are good: no warning.
I join a complete project for testing


LR83

We can correct the code simply by:
- replace this by StaticBoxSizer1->GetStaticBox() in the wxStaticText and wxTextCtrl constructor
- add the include <wx/statbox.h>

LR83

I try to find a patch to correct this.
First, we can add a temporary wxStaticBox when we add the wxStaticBoxSizer.
In the file wxsstaticboxsizer.cpp we replace in OnBuildSizerCreatingCode() function this code:
Quotecase wxsCPP:
        {
            AddHeader(_T("<wx/sizer.h>"),GetInfo().ClassName,hfInPCH);
            AddHeader(_T("<wx/statbox.h>"),GetInfo().ClassName,hfInPCH);
            Codef(_T("%C(%s, %W, %t);\n"),
                    (Orient!=wxHORIZONTAL)?_T("wxVERTICAL"):_T("wxHORIZONTAL"),
                    Label.wx_str());
            Codef(_T("wxStaticBox *SB_%s = %s->GetStaticBox();\n"),GetVarName().wx_str(),GetVarName().wx_str());
            return;
        }

The problem now is to replace, in all constructors of the children of wxStaticBoxSizer, the parent with this temporary wxStaticBox.
I don't know how to do it right now.

Miguel Gimenez

wxSmith is complex and the original developer is no longer around. I plan to fix this, but I currently have no free time.

LR83

The main difficulty lies in the fact that wxStaticBoxSizer is both a sizer and a container. In the current code, wxStaticBoxSizer is classified as a sizer, and there is no category for an object that is both a sizer and a container.
The difficulty lies in finding the owner of the child elements of wxStaticBoxSizer. Currently, it is the parent of the wxStaticBoxSizer that is found, and that is the problem.
The problem is clear, the solution less so!
We will probably need to create a new category and the wxsStaticBoxSizer class will need to inherit from wxsSizer and wxsContainer  :P

Miguel Gimenez


LR83

Great, work fine  :)
But I suggest using a temporary variable because wxStaticBoxSizer can have many children.
So, code could be:
In wxStaticBoxSizer.cpp:
        case wxsCPP:
        {
            AddHeader(_T("<wx/sizer.h>"),GetInfo().ClassName,hfInPCH);
            AddHeader(_T("<wx/statbox.h>"),GetInfo().ClassName,hfInPCH);
            Codef(_T("%C(%s, %W, %t);\n"),
                    (Orient == wxHORIZONTAL) ? _T("wxHORIZONTAL") : _T("wxVERTICAL"),
                    Label.wx_str());
            Codef(_T("wxStaticBox *SB_%s = %s->GetStaticBox();\n"),GetVarName().wx_str(),GetVarName().wx_str());
            return;
        }


in wxSizer.cpp:
        if (GetInfo().ClassName == "wxStaticBoxSizer")
        {
            // Use the static box as parent, as required by wxWidgets since 2.9.1
            wxsCoderContext* context = GetCoderContext();
            const wxString saveParent(context->m_WindowParent);
            context->m_WindowParent = "SB_" + GetVarName();
            Child->BuildCode(context);
            context->m_WindowParent = saveParent;
        }
        else
        {
            // Using same parent as we got, sizer is not a parent window
            Child->BuildCode(GetCoderContext());
        }


Bug Killer

Quote from: Miguel Gimenez on January 12, 2026, 03:59:40 PM
Fixed in r13767.

Works fine on AlmaLinux 9 with wxWidgets 3.3.1. Don't forget to modify slightly all the dialogs, frames and panels. I just add a space somewhere and remove it.

ollydbg

Quote from: naplis87 on May 01, 2026, 10:08:10 PM
Using Delta Executor, users can experience smooth script execution with fewer errors. Its optimized system improves performance and ensures a stable environment, helping users complete tasks quickly without facing technical problems.

spam reported.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.