Search code examples
c++wxwidgets

Can't figure out how to pass arguments to a bind function


After several tries of trying to pass arguments in a scroll event function, It's not working.

I'm making a custom scroll panel and need the bind function to trigger when the user scrolls down, in order to do that I need to pass variables that are going to be used inside the panel. This wasn't an issue with the wxScrolledWindow since I didn't have to bind anything and could just make a function for it and call it directly.

Some of these arguments I don't necessarily need to pass in as I can get them by using event.GetEventObject(); but the rest like m which is a map I need to pass on.

Among the solutions I've tried shown below, I thought of making a hidden panel with the map already inside or near the "scroll panel" so I can access it using the event.GetEventObject(); but I'm leaving it as a last-ditch effort (if that would even work). I'm really hoping there's an easier way. Any help is appreciated.

Attempt #1

ScrolledWindow->Bind(wxEVT_SCROLLWIN_PAGEDOWN, &MyFrame::ScrolledWindowCreate, this)(m, ScrolledWindow, ScrolledWindowMain, ScrolledWindowSizer, initalWindowWidth));

Attempt #2

// Saw a thread that said parameters should be put outside

ScrolledWindow->Bind(wxEVT_SCROLLWIN_PAGEDOWN, &MyFrame::ScrolledWindowCreate, this)(m, ScrolledWindowContainerSub, ScrolledWindowMain, ScrolledWindowSizer, initalWindowWidth);

Attempt #3

// Tried to pass the arguments as the userData as in the WxWidgets documentation, the WxWidgets forums suggested it, but I looked and apparently, I need to pass in a wxObject? I don't know how a set of arguments is supposed to be turned into a wxObject 

ScrolledWindow->Bind(wxEVT_SCROLLWIN_PAGEDOWN, &MyFrame::ScrolledWindowCreate, this, -1, (m, ScrolledWindowContainerSub, ScrolledWindowMain, ScrolledWindowSizer, initalWindowWidth);

Update:

So I found out that you need to store the arguments as wxClientData, I believe I've done so successfully but I still don't know how to extract the individual items from it.

struct CustomData final : public wxClientData {

    int PanelNum = 20;
    std::list<std::string> TagList{ "Paid", "Needs invoice" };
    std::map<std::string, std::variant<std::string, std::list<std::string>>> m{ {"TIME","8:69"}, {"HEADER","Title"},{"TAGS", TagList},{"CONTENT", "Hey this is content!"} };
    wxPanel* ScrolledWindowContainerSub;
    wxPanel* ScrolledWindowMain;
    wxBoxSizer* ScrolledWindowSizer;
    int initalWindowWidth = 1300;
};


 // Panels that are set as arguments below are defined here 
// wxPanel* ScrolledWindowContainerSub = ...; etc...

CustomData* const myData{ new CustomData() };
    myData->PanelNum, m, ScrolledWindowContainerSub, ScrolledWindowMain, ScrolledWindowSizer, initalWindowWidth;
    ScrolledWindowContainerSub->SetClientObject(myData);
    ScrolledWindowContainerSub->Bind(wxEVT_SCROLL_BOTTOM, &MyFrame::ScrolledWindowScrolled, this);


void MyFrame::ScrolledWindowScrolled(wxScrollEvent& event) {

wxObject* Obj = event.GetEventObject();
wxClientData* ObjClientData = static_cast<wxEvtHandler*>(Obj)->GetClientObject();


wxPanel* ObjStaticChild = dynamic_cast<wxPanel*>(ObjClientData); // Which panel will this give me? I've put two as parameters

};


Solution

  • Bind() does support passing pointers to arbitrary "user data", but this is not the best way to do it and is only supported for backwards compatibility and to ease migration of the very old code predating Bind().

    Instead, consider making the data you need part of some object -- typically something deriving from a window class and representing the window you're binding to, but not necessarily so -- and bind to a member function of this object, in which you will have access to all the data you need.

    Remember that you don't need to bind to the object generating the event, or its parent. You can use anything you want, including a lambda, for example.