f



how use wxthread and custom events in multifile project?

I've a problem creating custom wxevent for communication from a wxthread 
and main GUI. I tried with method 4 that you can found on wiky: 
http://wiki.wxwidgets.org/Custom_Events#Creating_a_Custom_Event_-_Method_4. 
It works fine if I put all (thread, events, GUI) on a single cpp file. 
My real problem is to separate the thread in a new separated file. I'm 
trying but after a month I lost my energy :-)

I'm using CB svn 5696 - mingw32 - wxwidgets 2.8.9 on WXP. Wxwidgets 
example don't use multi files. I've searched on "google code search", 
but I've not undestood where is the problem.

I've 4 files: labMain.cpp , labMain.h , CustomThread.cpp and 
CustomThread.h . I've removed unnecessary parts:

___________________________________________________
labmain.h


#include "CustomThread.h"


class labFrame: public wxFrame
{
     public:
         labFrame(wxWindow* parent,wxWindowID id = -1);
         virtual ~labFrame();
     private:
         //(*Handlers(labFrame)
         void OnQuit(wxCommandEvent& event);         	void 
OnAbout(wxCommandEvent& event);
         void OnButton1Click(wxCommandEvent& event);      void 
OnButton2Click(wxCommandEvent& event);
         //*)
         //void InterceptEvent( MyCustomEvent &event );
         void InterceptEvent( MyCustomEvent &  event );
         //(*Identifiers(labFrame)
         static const long ID_BUTTON1;	static const long ID_BUTTON2; 
static const long ID_STATUSBAR1;
         //*)
         //(*Declarations(labFrame)
         wxButton* Button1;	 wxButton* Button2;	 wxStatusBar* StatusBar1;
         //*)
         DECLARE_EVENT_TABLE()
};
#endif // LABMAIN_H

___________________________________________________
labmain.cpp
#include "labMain.h"

//(*InternalHeaders(labFrame)
#include <wx/intl.h>
#include <wx/string.h>
//*)


#include <wx/utils.h>
#include <wx/msgdlg.h>


//(*IdInit(labFrame)
const long labFrame::ID_BUTTON1 = wxNewId();
const long labFrame::ID_BUTTON2 = wxNewId();
const long labFrame::ID_STATUSBAR1 = wxNewId();
//*)


MyThread  *  LocalThread=NULL; // I DEFINE THE THREAD POINTER


BEGIN_EVENT_TABLE(labFrame,wxFrame)
     //(*EventTable(labFrame)
     //*)
END_EVENT_TABLE()

DEFINE_EVENT_TYPE( MyCustomCommandEvent )


labFrame::labFrame(wxWindow* parent,wxWindowID id)
{
     //(*Initialize(labFrame)
     wxGridSizer* GridSizer1;
     wxBoxSizer* BoxSizer1;

     Create(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, 
wxDEFAULT_FRAME_STYLE, _T("id"));
     BoxSizer1 = new wxBoxSizer(wxHORIZONTAL);
     GridSizer1 = new wxGridSizer(0, 3, 0, 0);
     Button1 = new wxButton(this, ID_BUTTON1, _("1"), wxDefaultPosition, 
wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON1"));
     GridSizer1->Add(Button1, 1, 
wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
     Button2 = new wxButton(this, ID_BUTTON2, _("2"), wxDefaultPosition, 
wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON2"));
     GridSizer1->Add(Button2, 1, 
wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
     BoxSizer1->Add(GridSizer1, 1, 
wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
     SetSizer(BoxSizer1);
     StatusBar1 = new wxStatusBar(this, ID_STATUSBAR1, 0, 
_T("ID_STATUSBAR1"));
     int __wxStatusBarWidths_1[1] = { -1 };
     int __wxStatusBarStyles_1[1] = { wxSB_NORMAL };
     StatusBar1->SetFieldsCount(1,__wxStatusBarWidths_1);
     StatusBar1->SetStatusStyles(1,__wxStatusBarStyles_1);
     SetStatusBar(StatusBar1);
     BoxSizer1->Fit(this);
     BoxSizer1->SetSizeHints(this);

 
Connect(ID_BUTTON1,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&labFrame::OnButton1Click);
 
Connect(ID_BUTTON2,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&labFrame::OnButton2Click);
     //*)

     Connect( wxID_ANY, 
MyCustomCommandEvent,MyCustomEventHandler(labFrame::InterceptEvent), 
NULL, this );  // I USE CONNECT TO INTERCEPT EVENTS FROM THREAD
}

labFrame::~labFrame()
{
     //(*Destroy(labFrame)
     //*)
}

void labFrame::InterceptEvent( MyCustomEvent &event )	// THIS FUNCTION 
WILL INTERCEPT EVENTS FROM THREAD
{
	switch( event.GetId() )
	{
	case Custom_DoFirstThing:
		StatusBar1->SetLabel((wxT("Started thread")+event.GetText())); break;
	case Custom_DoSecondThing:
		/* Do something different */ break;
	//  ...
	}
}

void labFrame::OnQuit(wxCommandEvent& event)
....

void labFrame::OnAbout(wxCommandEvent& event)
....

void labFrame::OnButton1Click(wxCommandEvent& event)
{
   if(!LocalThread)
   {
     StatusBar1->SetLabel(wxT("Allocating new LocalThread ..."));
     //wxEvtHandler * EH=GetEventHandler();
     LocalThread = new MyThread(GetEventHandler()); // THIS I LINE 139 - 
I OBTAIN A ERROR HERE
   }
....
}


void labFrame::OnButton2Click(wxCommandEvent& event)
{
....
}


___________________________________________________
CustomThread.h

#ifndef CUSTOMTHREAD_H
#define CUSTOMTHREAD_H

#include <wx/thread.h>
#include <wx/event.h>
DECLARE_EVENT_TYPE( MyCustomCommandEvent, -1 )


// A custom event that transports a whole wxString.
class MyCustomEvent: public wxCommandEvent
{
public:
	MyCustomEvent( wxEventType commandType = MyCustomCommandEvent, int id = 
0 ) : wxCommandEvent(commandType, id) { }  // You *must* copy here the 
data to be transported
	MyCustomEvent( const MyCustomEvent &event ) : wxCommandEvent(event) { 
this->SetText( event.GetText() ); } // Required for sending with 
wxPostEvent()
	wxEvent* Clone() const { return new MyCustomEvent(*this); }
	wxString GetText() const { return m_Text; }
	void SetText( const wxString& text ) { m_Text = text; }
private:
	wxString m_Text;
};

typedef void (wxEvtHandler::*MyCustomEventFunction)(MyCustomEvent &);

// This #define simplifies the one below, and makes the syntax less ugly 
if you want to use Connect() instead of an event table.
#define MyCustomEventHandler(func) 
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction) 
wxStaticCastEvent(MyCustomEventFunction, &func)
// Define the event table entry. Yes, it really *does* end in a comma.
#define EVT_MYFOO(id, fn)   \
	DECLARE_EVENT_TABLE_ENTRY( MyCustomCommandEvent, id, 
wxID_ANY,(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction) 
wxStaticCastEvent(MyCustomEventFunction, &fn ), (wxObject*) NULL ),
// Optionally, you can do a similar #define for EVT_MYFOO_RANGE.
#define EVT_MYFOO_RANGE(id1,id2, fn) DECLARE_EVENT_TABLE_ENTRY( 
MyCustomCommandEvent, id1, id2, MyCustomEventHandler(fn), (wxObject*) 
NULL ),
// If you want to use the custom event to send more than one sort of 
data, or to more than one place, make it easier by providing named IDs 
in an enumeration.
enum { Custom_DoFirstThing = 1, Custom_DoSecondThing, Custom_DoThirdThing };


class  MyThread : public wxThread
{
private:
protected:
public:
     virtual void* Entry();
     //virtual void OnExit();

     MyThread(wxEvtHandler  *EH);
     ~MyThread();

     wxEvtHandler* ParentH; // I USE IT TO MANTAIN POINTER OF CALLER 
EVTHANDLER

};
#endif


___________________________________________________
CustomThread.cpp

#include "CustomThread.h"

DEFINE_EVENT_TYPE( MyCustomCommandEvent )

MyThread::MyThread(wxEvtHandler *EH) : wxThread(wxTHREAD_JOINABLE)  // 
CONSTRUCTOR
{
   ParentH=EH;
}

MyThread::~MyThread() // DESTRUCTOR
{
}

void * MyThread::Entry()
{
   long int pass=0;
   while(1)
  {
     pass++;
     if (TestDestroy()) break;
     if(!(pass%10))
     {
       MyCustomEvent event( MyCustomCommandEvent, Custom_DoFirstThing );
       wxString bar( wxT("This is a Custom_DoFirstThing event") );
// Add the exciting data. You can put anything you like into the class: 
ints, structs, binary data...
       event.SetText( bar );
       wxPostEvent( ParentH, event ); // SEND CUSTOM EVENT TO GUI MAIN 
THREAD
     }
       wxThread::Sleep(500);
  }
  return(NULL);
}

=====================================================



When i compile it I obtain:

obj\Debug\labMain.o||In function 
`ZN8labFrame14OnButton1ClickER14wxCommandEvent':|
C:\STX\TECNIX\PROGRAMMAZIONE\MULTIPLATFORM\PROGETTI\lab\labMain.cpp | 
139 | undefined reference to `MyThread::MyThread(wxEvtHandler*)'|
||=== Build finished: 1 errors, 0 warnings ===|

Why "undefined reference"??????
  #include "CustomThread.h" is present on labMain.h and codeblock 
code-completion recognize correctly MyThread.

I think that thread is not the problem. I think there is a problem with 
DEFINE / DECLARE customevent but I don't understand what exactly is wrong.



I will appreciate any help you can give me.

Thank you.



Stefano
0
Stefano
7/23/2009 10:07:49 PM
comp.soft-sys.wxwindows 21076 articles. 0 followers. Post Follow

1 Replies
5511 Views

Similar Articles

[PageSpeed] 25

I resolved myself.
1) Undefined reference is a stupid error on linking files (sorry for
it).
2) The real important issue to remember using wxthread and
customevents, is that you have to put DECLARE_EVENT_TYPE
( MyCustomCommandEvent, -1 ) only in CustomThread.h and
DEFINE_EVENT_TYPE( MyCustomCommandEvent ) in CustomThread.cpp.

I hope this example will be usefull for you.
0
Smania2000
7/24/2009 10:38:39 PM
Reply: