Access a wxMenuBar through a function(pass pointer,address)

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
GianT
Earned some good credits
Earned some good credits
Posts: 124
Joined: Wed Mar 16, 2005 5:44 pm
Location: Guadeloupe, French West Indies
Contact:

Access a wxMenuBar through a function(pass pointer,address)

Post by GianT » Mon Jun 27, 2005 5:34 pm

Hi, I have created a wxMenubar in my main cpp file, and I want to pass it in parameter to another function which itself pass it again in parameter to another function, and I want that this last function could access the menubar, to make stuff like wxmenubar1->EnableTop(1,true);

Here is the way I pass it through the first function:

Code: Select all

th = new ThreadServer(WxMenuBar1);
and to the 2nd function:

Code: Select all

f->open_session_auto( WxMenuBar1);
In each functio, the parameter is taken like that:

Code: Select all

wxMenuBar* WxMenuBar1
I have no compilation error, but in the last function, when I try to access the menubar:

Code: Select all

WxMenuBar1->EnableTop(1,true);
I get a segmentation fault. I think that I don't pass the parameter the right way. Pointer or address error I think. Can u help me?

Jorg
Moderator
Moderator
Posts: 3971
Joined: Fri Aug 27, 2004 9:38 pm
Location: Delft, Netherlands
Contact:

Post by Jorg » Mon Jun 27, 2005 6:02 pm

I assume you are doing this in a different thread? This is not recommended. wxWidgets as many toolkits is not thread safe.

I would suggest create a mechanism where you post to an "non present" menu item, which ID you only handle in the event list but is never created. In that menu handler, update the thread status which reflects on the GUI.

- Jorgen
Forensic Software Engineer
Netherlands Forensic Insitute
http://english.forensischinstituut.nl/
-------------------------------------
Jorg's WasteBucket
http://www.xs4all.nl/~jorgb/wb

GianT
Earned some good credits
Earned some good credits
Posts: 124
Joined: Wed Mar 16, 2005 5:44 pm
Location: Guadeloupe, French West Indies
Contact:

Post by GianT » Mon Jun 27, 2005 6:20 pm

Jorg wrote:I assume you are doing this in a different thread? This is not recommended. wxWidgets as many toolkits is not thread safe.

I would suggest create a mechanism where you post to an "non present" menu item, which ID you only handle in the event list but is never created. In that menu handler, update the thread status which reflects on the GUI.

- Jorgen
I'm not sure to understand. You mean that I should create a kind of virtual menu item and set an event on it? If it's the real meaning, I would have to create a custom event...and this does not resolve my problem, cause I have to treat the request in a thread. How could I send this event from the thread to the main api???

Otherwise, do you really think that I got this segfault cause of the thread? I don't think so, I think it's because the last funtion does not access the memory block it should (or a stuff like that)..

Jorg
Moderator
Moderator
Posts: 3971
Joined: Fri Aug 27, 2004 9:38 pm
Location: Delft, Netherlands
Contact:

Post by Jorg » Mon Jun 27, 2005 6:27 pm

Do this:

Code: Select all

EVT_MENU(ID_SOME_MENUITEM, wxSomeWindow::OnMenuItem)
where ID_SOME_MENUITEM does not exist as a menu item. Simply declare the event.

Then in the thread, post a message to the main window:

Code: Select all

wxCommandEvent event;
event.SetId(ID_SOME_MENUITEM);
event.SetClientData(... /* ptr to some thread data */ ..);
wxPostEvent(mainForm, event);
Now when the event is processed it should be in the GUI context and you can sync the GUI with the thread status.

If you don't believe your solution crashes, that is fine by me. I am just saying accessing GUI elements in a thread is a *no* *no*. It is strongly discouraged. So, if you cannot solve your mysterious segfault, at least you can try if this approach works ;-)

- Jorgen
Forensic Software Engineer
Netherlands Forensic Insitute
http://english.forensischinstituut.nl/
-------------------------------------
Jorg's WasteBucket
http://www.xs4all.nl/~jorgb/wb

GianT
Earned some good credits
Earned some good credits
Posts: 124
Joined: Wed Mar 16, 2005 5:44 pm
Location: Guadeloupe, French West Indies
Contact:

Post by GianT » Mon Jun 27, 2005 7:59 pm

I don't manage to use wxPostEvent..I'm not sure I can access the main frame from the thread.
Jorg wrote:wxPostEvent(mainForm, event);
You wrote "mainForm", what does it represent in fact? I know that wxPostEvent waits for a wxEvtHandler object in its first argument, but I'm lost, I don't know what I should write instead of mainForm.

Here is the event table of the main frame:

Code: Select all

BEGIN_EVENT_TABLE(newProgramFrame,wxFrame)
// ...
    EVT_MENU(ID_SOME_MENUITEM, newProgramFrame::OnMenuItem)
// ...
END_EVENT_TABLE()

GianT
Earned some good credits
Earned some good credits
Posts: 124
Joined: Wed Mar 16, 2005 5:44 pm
Location: Guadeloupe, French West Indies
Contact:

Post by GianT » Mon Jun 27, 2005 8:15 pm

I work with wxdev-cpp, so some files are created by themselves. I think I found in the file newProgramFrameApp.cpp what I should write instead of mainForm, "myFrame". But I have no access to this in the thread (myFrame undeclared). how can I acces it?

Code of newProgramFrameApp.cpp:

Code: Select all

#include "newProgramFrameApp.h"
#include "newProgramFrame.h"

IMPLEMENT_APP(newProgramFrameApp)

bool newProgramFrameApp::OnInit()
{
	newProgramFrame *myFrame = new  newProgramFrame(NULL);
	SetTopWindow(myFrame);
	myFrame->Show(TRUE);		
	return TRUE;
}
 
int newProgramFrameApp::OnExit()
{
	return 0;
}

Jorg
Moderator
Moderator
Posts: 3971
Joined: Fri Aug 27, 2004 9:38 pm
Location: Delft, Netherlands
Contact:

Post by Jorg » Mon Jun 27, 2005 8:40 pm

I would give it to the thread on the time you create it instead of the menubar. Keep hold of the wxFrame (or rather make it a wxWindow pointer so you can change to a dialog later or whatever), and then post to it from the point your thread has to signal to the main frame / form.

Regards,
- Jorgen
Forensic Software Engineer
Netherlands Forensic Insitute
http://english.forensischinstituut.nl/
-------------------------------------
Jorg's WasteBucket
http://www.xs4all.nl/~jorgb/wb

GianT
Earned some good credits
Earned some good credits
Posts: 124
Joined: Wed Mar 16, 2005 5:44 pm
Location: Guadeloupe, French West Indies
Contact:

Post by GianT » Mon Jun 27, 2005 9:38 pm

Ok, 3 things:

- First one: I don't know how to give it to the thread. In the thread sample, I saw that it should be something like

Code: Select all

th = new ThreadServer(this);
with "this" giving the current newProgramFrame object, but the problem is that I donc't manage to make "this" be the current newProgrameFrame object...

- Second one: SetClientData method is very unknown of me. How could I give it various arguments, and how could I get them back? I tried to use the method GetClientData, as it is defined as void *, I thought that I could do a stuff like

Code: Select all

wxString login = event.GetClientData();
but it didn't work and generated compiler errors...

- Third one: I'm getting really mad...This really seem to be a good idea, but I'm frustrated cause I don't manage to make it work. :evil:

GianT
Earned some good credits
Earned some good credits
Posts: 124
Joined: Wed Mar 16, 2005 5:44 pm
Location: Guadeloupe, French West Indies
Contact:

Post by GianT » Tue Jun 28, 2005 1:08 am

I think I managed to give to the thread the main newProgramFrame object, thanks to the thread sample of wxWidgets. But the problem is that the event never arrives!!!It is sent but I don't know where it finishes.
Here is the way I deined the function which creates the thread:

Code: Select all

ThreadServer * OnClientConnect(wxSocketBase* sock);
Below you can see how I create the thread:

Code: Select all

ThreadServer *newProgramFrame::OnClientConnect(wxSocketBase* sock)
{
//...some code
       th = new ThreadServer(this);
//...some code
}
This is the constructor of ThreadServer:

Code: Select all

ThreadServer::ThreadServer(newProgramFrame *myFrame ): wxThread()
{

    this->myFrame=myFrame;
}
And here is in the entry function of the thread how I send the event:

Code: Select all

                        event.SetId(ID_SOME_MENUITEM);
                         wxPostEvent(myFrame, event);
I never reach the function supposed to deal with the event.

Post Reply