Dll App and Events 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
some_exp_from84
In need of some credit
In need of some credit
Posts: 6
Joined: Sun Oct 08, 2006 9:33 pm

Dll App and Events

Post by some_exp_from84 » Sun Oct 08, 2006 10:12 pm

Hello, ALL!

I wrote some small application and dll using wxWidgets 2.6.3.
The main application creates main window, dynamically loads the dll library and calls it’s functions. One of the dll’s function creates button on main application window. After that it try to connect event handler of this button to some function. For now - all god. But when I click on this button nothing appears – connected function doesn’t calls! Why?

dll.h

Code: Select all

#include <wx/wx.h>

#ifdef __WXMSW__
	#ifndef _EXPORT_
	#define _EXPORT_ extern "C" __declspec(dllexport)
	#endif
#endif

/* Exported functions */
_EXPORT_ wxButton*  CreateButton(wxWindow* parent, wxWindowID id, wxString& label, wxPoint& pos, wxSize& size);

/* Not exported */
HANDLE ThreadId;
 
class DLLApp : public wxApp
  {
 	public:
 	  bool OnInit();
 	  
 	  void ButtonClick(wxEvent& event);
  };
dll.cpp

Code: Select all

#include <wx/wx.h>
#include "dll.h"

#ifdef __BORLANDC__
  #pragma hdrstop
#endif

IMPLEMENT_APP_NO_MAIN(DLLApp)

DWORD WINAPI ThreadProc(LPVOID lpParameter)
  {
     wxApp::SetInstance(new DLLApp());
     wxEntry(GetModuleHandle(NULL), NULL, NULL, SW_SHOW);
     return true;
  }

bool APIENTRY DllMain(HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved) 
  {
	switch (ul_reason_for_call)
      { 
    	case DLL_PROCESS_ATTACH:
        	ThreadId = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
        break;
     	case DLL_THREAD_ATTACH: break;
     	case DLL_THREAD_DETACH: break;
     	case DLL_PROCESS_DETACH:
        	wxEntryCleanup();
        break; 
     }
 
     return TRUE;
  }


/* Exporting functions */
wxButton* CreateButton(wxWindow* parent, wxWindowID id, wxString& label, wxPoint& pos, wxSize& size)
  {
  	wxButton* btn = new wxButton(parent, id, label, pos, size);
  	
  	//This connects WDEvtFunc::ButtonClick to the new button EventHandler, but it doesn't work
  	btn->Connect(wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DLLApp::ButtonClick));
  		
  	return btn;
  }
  
/* Not exported functions */  
bool DLLApp::OnInit()
  {
    return true;
  }
  
void DLLApp::ButtonClick(wxEvent& WXUNUSED(event))	
  {
  	wxMessageBox("I'm here!", "Confirm", wxOK);
  }
exe.h

Code: Select all

#include <wx/dynlib.h>
#include <wx/wx.h>

enum	
  {
  	MAINFRAMEID = 1,
  	MAINPANELID,
  	CBUTTONID,
  	LBUTTONID,
  	NBUTTONID,
  };

typedef wxButton*  (*CreateFuncPtr)(wxWindow*, wxWindowID, wxString&, wxPoint&, wxSize&);
  

class WDPanel : public wxPanel 
  {
  	public:
  	  WDPanel(wxWindow* parent, wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL, const wxString& name = "panel");
  	
  	  wxButton    *LButton;
  	  wxButton    *CButton;
  };

class WDTopWindow : public wxFrame	
  {
  	public:
  	  WDTopWindow(wxWindowID id, const wxString& title, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE, const wxString& name = "frame");
  	
  	  WDPanel *MainPanel;	
  };
    
class WDApp : public wxApp	
  {
  	public:
  	  bool OnInit();	
  	  
  	  void LButtonClick(wxEvent& event);	
  	  void CButtonClick(wxEvent& event);	
  	  
  	  WDTopWindow		*MainFrame;	
  	  wxDynamicLibrary	*Libs;		
  	  
  	  wxButton* NewBtnPtr;
  };
  
exe.cpp

Code: Select all

#ifdef __BORLANDC__
  #pragma hdrstop
#endif

#include "exe.h"

IMPLEMENT_APP(WDApp)	

bool WDApp::OnInit()
  {
  	MainFrame = new WDTopWindow(MAINFRAMEID, "->   >-", wxDefaultPosition, wxSize(150, 300));
  	
  	MainFrame->Show();
  	SetTopWindow(MainFrame);
  	
  	Libs = new wxDynamicLibrary();
  	
  	return true;
  }

void WDApp::LButtonClick(wxEvent& WXUNUSED(event))
  {
  	WDApp *AppObjPtr = &wxGetApp();
  	
  	AppObjPtr->Libs->Load("dll");
  	
  	if (wxGetApp().Libs->IsLoaded())
  	  {
  	  	AppObjPtr->MainFrame->MainPanel->LButton->Disable();
  	  	AppObjPtr->MainFrame->MainPanel->CButton->Enable();
  	  	AppObjPtr->MainFrame->SetTitle("->>-");
  	  }
  	else
  	  {
  	  	wxMessageBox("Can't find dll.DLL!", "Confirm", wxOK);
  	  }
  }

void WDApp::CButtonClick(wxEvent& WXUNUSED(event))
  {
  	WDApp *AppObjPtr = &wxGetApp();
  	
  	if (AppObjPtr->Libs->HasSymbol("CreateButton"))
  	  {
  	  	CreateFuncPtr procPtr;
  	  	
  	  	procPtr = (CreateFuncPtr)(AppObjPtr->Libs->GetSymbol("CreateButton"));
  	  	
  	  	int width, height = 100;
	  	AppObjPtr->MainFrame->MainPanel->GetClientSize(&width, &height);
  	  	
  		AppObjPtr->NewBtnPtr = procPtr(AppObjPtr->MainFrame->MainPanel, NBUTTONID, "Push me!", wxPoint(5, 120), wxSize(width-10, 40));
  	  	
  		AppObjPtr->MainFrame->MainPanel->CButton->Disable();
  	  }
  	else
  	  {
  	  	wxMessageBox("Can't find function CreateButton!", "Confirm", wxOK);
  	  }
  }
  
WDTopWindow::WDTopWindow(wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
  :wxFrame((wxWindow*)NULL, id, title, pos, size, style, name)
  {
  	int width, height = 100;
  	
  	GetClientSize(&width, &height);
  	
  	MainPanel = new WDPanel(this, MAINPANELID, wxPoint(0, 0), wxSize(width, height), wxTAB_TRAVERSAL, "panel");
  }
  
WDPanel::WDPanel(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
  :wxPanel(parent, id, pos, size, style, name)
  {
  	int width, height = 100;
  	
  	GetClientSize(&width, &height);
  	
  	LButton = new wxButton(this, LBUTTONID, "Load DLL!",			wxPoint(5, 5),   wxSize(width-10, 20));
  	CButton = new wxButton(this, CBUTTONID, "Create!",				wxPoint(5, 30),  wxSize(width-10, 20));
  	
  	CButton->Disable();
  	
  	LButton->Connect(wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(WDApp::LButtonClick));
  	CButton->Connect(wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(WDApp::CButtonClick));
  }

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 4425
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Post by ONEEYEMAN » Mon Oct 09, 2006 5:07 am

some_exp_from84,
Did you define the event table somewhere?

Thank you.

P.S.: Also, did you try the debugger? Maybe you didn't put the DLL in the same dir as executable? Is it loaded? Is the function being executed?

some_exp_from84
In need of some credit
In need of some credit
Posts: 6
Joined: Sun Oct 08, 2006 9:33 pm

Post by some_exp_from84 » Mon Oct 09, 2006 7:30 am

ONEEYEMAN wrote:
Did you define the event table somewhere?
No, I need creates controls (such as button) dynamically and dynamically connects their EventHandlers to some functions. So event table is not suitable for me.
Also, did you try the debugger? Maybe you didn't put the DLL in the same dir as executable? Is it loaded? Is the function being executed?
DLL loaded normally. After loading I call function “CreateButton” from this DLL and button successfully creates on a main window. The function “CreateButton” connects EventHandler of a new button to function “DLLApp::ButtonClick”:

Code: Select all

btn->Connect(wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DLLApp::ButtonClick));
But when I click on this button, function “DLLApp::ButtonClick” doesn’t calls! This is a trouble.

Thank you!

tiwag
Earned some good credits
Earned some good credits
Posts: 123
Joined: Tue Dec 21, 2004 8:51 pm
Location: Austria

Post by tiwag » Mon Oct 09, 2006 12:40 pm

instead of defining

Code: Select all

void ButtonClick(wxEvent& event); 

void LButtonClick(wxEvent& event);     
void CButtonClick(wxEvent& event);      


you need to define them as

Code: Select all

void ButtonClick(wxCommandEvent& event); 

void LButtonClick(wxCommandEvent& event);     
void CButtonClick(wxCommandEvent& event);      

also changed the CreateFuncPtr definiton in exe.h to

Code: Select all

typedef wxButton*  (*CreateFuncPtr)(wxWindow*, wxWindowID, const wxString&, const wxPoint&, const wxSize&);
in order to compile with g++ without errors

then your sample builds and runs fine

HTH, tiwag
Last edited by tiwag on Mon Oct 09, 2006 1:16 pm, edited 1 time in total.
-tiwag

some_exp_from84
In need of some credit
In need of some credit
Posts: 6
Joined: Sun Oct 08, 2006 9:33 pm

Post by some_exp_from84 » Mon Oct 09, 2006 1:14 pm

Using

Code: Select all

void ButtonClick(wxCommandEvent& event);
instead of this

Code: Select all

void ButtonClick(wxEvent& event);
good note, but it is not enough.

I use Borland C++ compiler 5.5. Program builds with some warnings (“temporary use…”), but runs fine. Problem with button, which creates by “CreateButton” function from dll – doesn’t calls function “DLLApp::ButtonClick” when I click on this new button!

May be problem in wxWidgets version/compiler?

Thank you!

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 4425
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Post by ONEEYEMAN » Mon Oct 09, 2006 4:35 pm

Just to test this:
Can you define the wxButton derived class with the event table, and use this one instead.
Also, did you try to debug the "Connect()" function?

Thank ou.

some_exp_from84
In need of some credit
In need of some credit
Posts: 6
Joined: Sun Oct 08, 2006 9:33 pm

Post by some_exp_from84 » Mon Oct 09, 2006 7:01 pm

Can you define the wxButton derived class with the event table, and use this one instead.
Ok, i tried use event table, but it is not resolve the problem.

Now I write next function:

Code: Select all

void ConnectToBtnClk(wxEvtHandler* EvtHandler)
  {
       EvtHandler->Connect(wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DLLApp::ButtonClick));
  }
and place it in dll. It connects EvtHandler of some button to “DLLApp::ButtonClick” function. In main app I call this function for two buttons EvtHandlers:

Code: Select all

typedef void*      (*ConnectToBtnClkPtr)(wxEvtHandler*);
...
ConnectToBtnClkPtr procPtr;
  	  	
procPtr = (ConnectToBtnClkPtr)(AppObjPtr->Libs->GetSymbol("ConnectToBtnClk"));
  	  	
//For button, created by main app
procPtr((wxEvtHandler*)(AppObjPtr->MainFrame->MainPanel->CButton));
//For button, created by dll app
procPtr((wxEvtHandler*)(AppObjPtr->NewBtnPtr));
CButton created by main app and NewBtnPtr created by dll app.

Now builds and run. After executing above code EvtHandlers of CButton and NewBtnPtr connects to “DLLApp::ButtonClick” function. When I click on CButton “DLLApp::ButtonClick” function calls and wxMessageBox appears! But when I click on button created by DLLApp nothing happens :cry: . I conclude that connected function don’t calls only for controls which created by DLLApp. Why?

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 4425
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Post by ONEEYEMAN » Mon Oct 09, 2006 7:08 pm

Probably because you DLL doesn't know anything about your APP?
Like I said earlier, try to use wxButton-derived class. It is much easier and less painful....
You can even put this class in the DLL, and create the instance of this class in yopur app and DLL independantly.

This approach works for me - I am using wxToolBar-derived class in .exe and .dll....

Thank you.

some_exp_from84
In need of some credit
In need of some credit
Posts: 6
Joined: Sun Oct 08, 2006 9:33 pm

Post by some_exp_from84 » Mon Oct 09, 2006 8:04 pm

Probably because you DLL doesn't know anything about your APP?

May be! But what the DLL must know about APP?
Like I said earlier, try to use wxButton-derived class. It is much easier and less painful....
You can even put this class in the DLL, and create the instance of this class in yopur app and DLL independantly.
My APP is a sample, which uses .dll. For real task the dll uses by another application. This application shouldn’t know what classes contains this dll, it just know what functions exports and calls when needed. So the interface between APP and DLL must simple as possible and doesn’t affect to APP.exe source code very strong. I want understand what need to using of my DLL by this APP.

Thank you for reply!

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 4425
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Post by ONEEYEMAN » Mon Oct 09, 2006 10:13 pm

some_exp_from84 wrote:
Probably because you DLL doesn't know anything about your APP?

May be! But what the DLL must know about APP?
You are connecting the event in the main application. Your DLL does not know about that...

some_exp_from84 wrote:
Like I said earlier, try to use wxButton-derived class. It is much easier and less painful....
You can even put this class in the DLL, and create the instance of this class in yopur app and DLL independantly.
My APP is a sample, which uses .dll. For real task the dll uses by another application. This application shouldn

tiwag
Earned some good credits
Earned some good credits
Posts: 123
Joined: Tue Dec 21, 2004 8:51 pm
Location: Austria

Post by tiwag » Tue Oct 10, 2006 3:50 am

[quote="some_exp_from84"]Using

Code: Select all

void ButtonClick(wxCommandEvent& event);
instead of this

Code: Select all

void ButtonClick(wxEvent& event);
good note, but it is not enough.

I use Borland C++ compiler 5.5. Program builds with some warnings (
-tiwag

Saurabh
Earned some good credits
Earned some good credits
Posts: 117
Joined: Thu Sep 07, 2006 10:25 am
Location: India
Contact:

Post by Saurabh » Tue Oct 10, 2006 6:41 am

May be this is not a good solution but anyways.....You can keep a dummy function inside the main application. Now you connect the button event to this dummy function.....Next you can link the desired function in dll to be called from in this dummy function using function pointers or whatever....I believe this can solve some of ur problem

some_exp_from84
In need of some credit
In need of some credit
Posts: 6
Joined: Sun Oct 08, 2006 9:33 pm

Post by some_exp_from84 » Tue Oct 10, 2006 1:24 pm

if you are using CodeBlocks and MinGW gcc too, i can upload the project if you're interested.
tiwag, please send me this project by e-mail: [email protected].
Thank you for any help!

tiwag
Earned some good credits
Earned some good credits
Posts: 123
Joined: Tue Dec 21, 2004 8:51 pm
Location: Austria

Post by tiwag » Tue Oct 10, 2006 1:33 pm

some_exp_from84 wrote:
if you are using CodeBlocks and MinGW gcc too, i can upload the project if you're interested.
tiwag, please send me this project by e-mail: [email protected].
Thank you for any help!
you can dl it there

http://tiwag.cb.googlepages.com/wx_dll_app_event.zip

brgds, tiwag
-tiwag

swmp
Experienced Solver
Experienced Solver
Posts: 84
Joined: Tue Mar 21, 2006 1:08 pm

Post by swmp » Tue Jan 09, 2007 1:44 am

Have you sloved this problem?

Can you tell how? I also meet it.

Thanks very much! :shock:

Post Reply