I am a hobby programmer still learning C++ and wxWidgets. I use Code::Blocks 20.3, wxWidgets 3.1.4, and MinGW 17.1 on a Windows 10 Pro computer.
I am trying to make a virtual wxListCtrl work in Code::Blocks, I followed the code in the ListCtrl sample and a simple example in the wxWidgets Discussion Forum. The sample (1 file) code on both compiles and works. When I start a new project in Code::Blocks, the GUI APP and MAIN is coded in separate files. Perhaps I need to do more, but cannot find what it is. The project compiles with zero errors and warnings, but it shows below error on startup. I tried moving SetItemCount() above AppendCollumn(), but that did not help. There is no error when I comment both AppendColumn() out, but then of course the list is empty.
Can someone please help me with what is missing in my code?
Thank you, Ruud
Error:
A debugging check in this application has failed
../../src/cpmmon.listctrlcmn.cpp(259):
assert "Assert Failure" failed in OnGetItemText():
wxListCtrl::OnGetItemText not supposed to be called
GUI code:
GUIFrame::GUIFrame( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
wxBoxSizer* bSizer1;
bSizer1 = new wxBoxSizer( wxVERTICAL );
m_listCtrl1 = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxLC_VIRTUAL );
bSizer1->Add( m_listCtrl1, 1, wxALL|wxEXPAND, 10 );
this->SetSizer( bSizer1 );
this->Layout();
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( GUIFrame::OnClose ) );
}
GUIFrame::~GUIFrame()
{
// Disconnect Events
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( GUIFrame::OnClose ) );
}
Main Code:
#include "VlistMain.h"
const wxChar *SMALL_VIRTUAL_VIEW_ITEMS[][2] =
{
{ wxT("Cat"), wxT("meow") },
{ wxT("Sheep"), wxT("baaah") }
};
VlistFrame::VlistFrame(wxFrame *frame) : GUIFrame(frame)
{
m_listCtrl1->AppendColumn("Animal");
m_listCtrl1->AppendColumn("Sound");
m_listCtrl1->SetItemCount(WXSIZEOF(SMALL_VIRTUAL_VIEW_ITEMS));
}
wxString VlistFrame::OnGetItemText(long item, long column) const
{
return SMALL_VIRTUAL_VIEW_ITEMS[item][column];
}
Event table:
wxBEGIN_EVENT_TABLE(MyListCtrl, wxListCtrl)
EVT_LIST_ITEM_SELECTED(wxAny, MyListCtrl::OnSelected)
wxEND_EVENT_TABLE()
Here's a second answer that uses wxFormbuilder's subclass feature. The advantage of this approach is that it will let you set up event handlers with wxFormbuilder. First we'll need to have a slightly different declaration for the constructor for the derived class
This add's more parameters to the constructor so that it will be compatible with the code generated by wxFormbuilder. As in the other answer, this should be placed in a new header file that is added to the project.
Next in a code file, add the body for the constructor
Note that this forces the the subclass to have the style
wxLC_VIRTUAL | wxLC_REPORT
and will ignore any style entered in wxFormbuilder. So if you want to change the style, you should change it in the code above.Alternately you could change
wxLC_VIRTUAL | wxLC_REPORT
tostyle
. Then the style options entered in wxFormbuilder will be used. But then it's up to you to make sure those options always include wxLC_REPORT and wxLC_VIRTUAL and do not contain any other options that are incompatible with those two.Next, in wxFormbuilder, add a list control to your form and on the object properties tab, set the subclass options to
(you can leave the forward_declare option checked or unchecked - it doesn't make any difference).
Now you can add any event handlers for your list control just like with any other widget: