Unresolved external symbol with wxDECLARE_EVENT Topic is solved

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.
Post Reply
sw
Experienced Solver
Experienced Solver
Posts: 56
Joined: Sat Mar 16, 2019 8:09 pm

Unresolved external symbol with wxDECLARE_EVENT

Post by sw »

Hi all,

I have searched through the forums to see if anyone has experienced this issue, but I have not found anything.

I was following the wiki page for creating custom events https://wiki.wxwidgets.org/Custom_Event ... -_Method_4

I am trying to post a event from a dialog to the main (parent) frame. In the dialog header file I have added the macro to declare the event like so:

Code: Select all

wxDECLARE_EVENT(TASK_INSERTED, wxCommandEvent);
This line is placed after all includes and before the class declaration. And in the source file I define the event:

Code: Select all

wxDEFINE_EVENT(TASK_INSERTED, wxCommandEvent);
My main issue is that when I compile the code, the linker complains about a "unresolved external symbol". This is the full error:
LNK2001 unresolved external symbol "class wxEventTypeTag<class wxCommandEvent> const TASK_INSERTED" (?TASK_INSERTED@@3V?$wxEventTypeTag@VwxCommandEvent@@@@B)
This error is coming from the frame obj file.

I don't think I am missing a include as I am including wx/wx.h in both the frame and dialog header files. I am using wxWidgets 3.1.2-1 on Windows 10 with VS2019
User avatar
doublemax
Moderator
Moderator
Posts: 19103
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Unresolved external symbol with wxDECLARE_EVENT

Post by doublemax »

That looks ok to me. Can you show how you use the new event?

https://docs.wxwidgets.org/trunk/overvi ... nts_custom
Use the source, Luke!
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4183
Joined: Sun Jan 03, 2010 5:45 pm

Re: Unresolved external symbol with wxDECLARE_EVENT

Post by PB »

The code you posted should work, the issue must be elswhere.

FWIW, this works as expected

MyDialog.h

Code: Select all

#pragma once

#include <wx/wx.h>

wxDECLARE_EVENT(TASK_INSERTED, wxCommandEvent);

class MyDialog : public wxDialog
{
public:
    MyDialog(wxWindow* parent);
protected: 
    void OnAddTask(wxCommandEvent&);
};
MyDialog.cpp

Code: Select all

#include "MyDialog.h"

MyDialog::MyDialog(wxWindow* parent) 
    : wxDialog(parent, wxID_ANY, "Add Task Dialog")
{                                                                      
    wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
        
    wxButton* button = new wxButton(this, wxID_ANY, "Add Task");
    button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MyDialog::OnAddTask, this);
    mainSizer->Add(button, wxSizerFlags().Expand().DoubleBorder());

    mainSizer->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), wxSizerFlags().Expand().DoubleBorder());
                        
    SetSizerAndFit(mainSizer);
}	

void MyDialog::OnAddTask(wxCommandEvent&)
{
    wxCommandEvent event(TASK_INSERTED, GetId());
    
    event.SetEventObject(this);    
    GetParent()->ProcessWindowEvent(event);
}
MyFrame.cpp

Code: Select all

#include <wx/wx.h>

#include "MyDialog.h"

wxDEFINE_EVENT(TASK_INSERTED, wxCommandEvent);

class MyFrame : public wxFrame
{
public:
    MyFrame() : wxFrame(nullptr, wxID_ANY, "Test", wxDefaultPosition, wxSize(800, 600))          
    {  
        wxPanel* mainPanel = new wxPanel(this);        
        wxBoxSizer* mainPanelSizer = new wxBoxSizer(wxVERTICAL);
        
        wxButton* button = new wxButton(mainPanel, wxID_ANY, "Show Dialog...");
        button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MyFrame::OnShowDialog, this);
        mainPanelSizer->Add(button, wxSizerFlags().Expand().DoubleBorder());
        
        wxTextCtrl* logCtrl = new wxTextCtrl(mainPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 
            wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2);     
        wxLog::SetActiveTarget(new wxLogTextCtrl(logCtrl));                                         
        mainPanelSizer->Add(logCtrl, wxSizerFlags().Expand().DoubleBorder().Proportion(5));

        mainPanel->SetSizer(mainPanelSizer);

        Bind(TASK_INSERTED, &MyFrame::OnAddTask, this);
    }   
protected:            

    void OnShowDialog(wxCommandEvent&)
    {   
        MyDialog dlg(this);

        dlg.ShowModal();
    }

    void OnAddTask(wxCommandEvent&)
    {
        wxLogMessage("Task added.");
    }
};

class MyApp : public wxApp
{
public:   
    bool OnInit() override
    {
        (new MyFrame)->Show();
        return true;
    }
}; wxIMPLEMENT_APP(MyApp);;
Not sure whether something like this, i.e., passing the event from the modal dialog, is a good idea....
sw
Experienced Solver
Experienced Solver
Posts: 56
Joined: Sat Mar 16, 2019 8:09 pm

Re: Unresolved external symbol with wxDECLARE_EVENT

Post by sw »

In the dialog:

Code: Select all

wxCommandEvent taskInsertedEvent(TASK_INSERTED);
wxPostEvent(pParent, taskInsertedEvent);
where pParent is a pointer to the frame class.

In the frame:

Code: Select all

wxBEGIN_EVENT_TABLE(MainFrame, wxFrame)
...
EVT_COMMAND(wxID_ANY, TASK_INSERTED, MainFrame::OnTaskInserted)
...
wxEND_EVENT_TABLE()

void MainFrame::OnTaskInserted(wxCommandEvent& event)
{
    pListCtrl->DeleteAllItems();
    RefreshItems();
}
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4183
Joined: Sun Jan 03, 2010 5:45 pm

Re: Unresolved external symbol with wxDECLARE_EVENT

Post by PB »

Do you have wxDEFINE... above the message table definition?

Does the issue persist when you use Bind() instead of the static event table or just comment out the line in the message table in frame source file?
sw
Experienced Solver
Experienced Solver
Posts: 56
Joined: Sat Mar 16, 2019 8:09 pm

Re: Unresolved external symbol with wxDECLARE_EVENT

Post by sw »

I'm so embarrassed, but I figured it out. I'm using namespaces in my application and I put the wxDEFINE_EVENT inside the namespace of the dialog source file. The frame is also in a namespace, but in a different one hence why the linker was struggling to find the event. Moving it out of the namespace has resolved the linker problem.

Thank you PB, your comment set me on the right path. And thank you doublemax too.
Post Reply