Can I access wxWidgets' message loop directly?

1,455 views
Skip to first unread message

DavidA

unread,
Jul 23, 2009, 10:44:21 AM7/23/09
to wx-users
Hi

I haven't tried coding with wxWidgets yet but am considering how it
could be used with our application.

Our app is a framework that runs a series of dynamically linked
functions. The user can specify the functions to be run in an xml
file. The app's own kernel calls each of the desired functions in
turn. Each runs to completion and the next function is called. The app
is a modelling tool and outputs results to text files. It has no user
interface.

We would like to use wxWidgets to add a user interface. We would like
to do this by letting the kernel call wxWidgets just like any other of
the app's functions, in a continuous loop. However, the wxWidgets
samples suggest that all wxWidgets apps consist of a class derived
from wxApp. The main() function of a wxWidgets app is hidden. For our
strategy to work, I guess we would need to activate the message loop
part of the wxWidgets app. This would be like us calling GetMessage()
in a windows app. Is this possible with wxWidgets?

An alternative solution would be to run the user interface as a
separate process and communicate with the main app using some form of
IPC. However, I would like to consider a single application first to
avoid the complexity of IPC.

I hope I have explained this adequately...

David

Mark Gollahon

unread,
Jul 23, 2009, 11:48:45 AM7/23/09
to wx-u...@googlegroups.com
DavidA - you are used to programming linearly. Your programs "Do A",
then "Do B", then "Do C", and so on until its done. When programming a
GUI you have to think in events not functions. "Dispatch Event A", now
"Dispatch Event B", and so on.

The message loop is what turns a normally linear program into an
event-based program. The message loop is what receives any raw events
(like user-interface button presses, menu selections, keyboard key
presses, etc.) and dispatches those events to the correct window (main
window, dialogs, buttons, text boxes on dialogs, etc.).

Therefore, inserting a long-running function into the message loop would
be a bad idea since your UI would stall while the function executes.
The user experience would be quite bad as they would "click-click-click
- HEY Nothing Is Happening! click-click-click" then, suddenly, all of
their clicks do something really, really fast (menus open and close,
windows pop up and go away, etc., based on how your UI is written), then
it would be back to "click-click-click - HEY Nothing Is Happening!" as
the next long-running function starts.

If you want to keep all of this in one application, then you have three
options: use a "Progress" dialog, use the idle handler, or use a worker
thread. (I am sure that the more senior people out there could come up
with a million variations on these....)

Progress dialog ---
Conceptually, this is probably the most simple of the three options.

Your UI allows the user to configure which long running functions to
execute and in what order along with a "GO!" button. The "GO!" button
pops up a dialog box that, once launched, doesn't return control of the
user interface until all of your long-running dynamic functions have
completed.

The down-side to this option is the same as inserting your long-running
functions into the message loop - your GUI is unresponsive while the
functions are running.

Idle Handler ---
This is arguably the best option - especially if you don't want to work
with threads (see last option below). It does have a down-side though.

During message loop processing, there are times when the program has
accepted and dispatched all pending events and there are no events left
"in the pipeline". It is at this time that the message loop will call
"The Idle Handler" to allow the program do to things when there are no
UI events to process.

The down-side to this option is that you must break your long-running
functions into "bite-sided" pieces that will run for no longer than
about one second. This is so the message loop can process any pending
events that occurred during that second (the UI is supposed to stay
responsive to the user).

Worker Thread ---
This is the most straightforward option as a good chunk of the program
is in a very familiar environment - the linear program. However, it,
too, has down-sides that make it the hardest to debug when things go
wrong. This option is certainly *not* for the faint-of-heart!

In this option, the UI is written very similarly to the "Progress
Dialog" option above, but when the "GO!" button is pressed, instead of
the dialog box controlling the execution, it simply launches a new
thread that does the long-running function calling. The UI stays
responsive because the UI is on a different thread than the long-running
functions are.

However, the worker thread down-side comes when you are passing
variables back and forth (i.e. what to call and when as well as log
messages flowing the other way) as well as stopping it *gracefully*
before it has reached the end of its work. If you are not careful, you
can end up in thread "deadlock" or messages getting dropped.

Hope this helps!
MarkG

DavidA

unread,
Jul 23, 2009, 12:00:18 PM7/23/09
to wx-users
Hi Mark

Thanks very much for taking the time to reply in such detail. I
understand what you are saying.

I would like to try the Idle Handler option. Briefly, how do I
implement this in wxWidgets? Do I provide a callback function?

Best regards

David

Nathan Ridge

unread,
Jul 23, 2009, 12:41:23 PM7/23/09
to wx-u...@googlegroups.com

Hi David,

You set up an idle handler just like any other event handler.
The event type is wxEVT_IDLE.

So you connect it like this in your frame's constructor:

Connect(wxID_ANY, wxEVT_IDLE, wxEventHandler(MyFrame::OnIdle));

(or add an entry to the event table), and place the code
in the OnIdle() method.

One thing that I've done in the past that might be easier than
breaking the task into bite-sized pieces, is to do it all in
one call to the idle handler, and call wxYield() from time to time,
which allows wxWidgets to process any pending UI events.
Again, you'll want to call it at least once every second
for the UI not to look like it's hanging.

Regards,
Nate.


----------------------------------------
> Date: Thu, 23 Jul 2009 09:00:18 -0700
> Subject: Re: Can I access wxWidgets' message loop directly?
> From: dand...@talktalk.net
> To: wx-u...@googlegroups.com
_________________________________________________________________
Stay on top of things, check email from other accounts!
http://go.microsoft.com/?linkid=9671355

Mark Gollahon

unread,
Jul 23, 2009, 1:15:56 PM7/23/09
to wx-u...@googlegroups.com
Nathan:

I'd avoid wxYield() like the plague. Use it only if you absolutely have
to.

I've experienced very subtle problems with wxYield() - specifically
making sure *all* of my handlers are always 100% re-entrant (you never
know when your handlers are going to call something that then will call
wxYield() - especially in a large project). To me this is worse than
writing threading code since threading code usually has only 2-3 places
where it interacts with the system at-large. Writing handlers to be
100% re-entrant means you have to be 100% sure about what you are
calling in 100% of all scenarios - then wondering how a customer broke
it because all you get is "I did this and this and it doesn't work" and
there is a third step in there somewhere they didn't tell you about.

Nathan Ridge

unread,
Jul 23, 2009, 1:23:49 PM7/23/09
to wx-u...@googlegroups.com

Mark:

If it's only the idle handler that calls wxYield(), then why does
anything need to be reentrant? Surely other handlers cannot call
the idle handler...

Regards,
Nate.

----------------------------------------
> Subject: RE: Can I access wxWidgets' message loop directly?
> From: mgol...@exacq.com
> To: wx-u...@googlegroups.com
> Date: Thu, 23 Jul 2009 13:15:56 -0400
_________________________________________________________________
Send and receive email from all of your webmail accounts.
http://go.microsoft.com/?linkid=9671356

Mark Gollahon

unread,
Jul 23, 2009, 1:40:05 PM7/23/09
to wx-u...@googlegroups.com
DavidA:

You handle the "idle event" just as any other event - either in your App
class or in some other window. One little detail you should know about
is that you should return "true" from your idle handler if you need
another idle event or "false" if your idle processing is done.

Furthermore, be aware that your breakdown of long-running functions will
need to keep state between idle calls - for example, how many times a
particular piece of code has been called (i.e. what used to be a loop in
the "linear programming" environment).

Also, I'd treat the stateful variable setup/teardown in your dynamic
libraries as just another step in the long-running function (i.e. idle
call #1 is "setup", idle call #2 is "do work", ... , idle call #n is
"teardown" and return false once teardown is done as you're done). A
lot of programmers would actually code step #1 as "setup & do work #1".
You can get away with that if setup is negligible, but if you are
malloc'ing a 1Gig memory buffer and creating two or three files on disk,
the user is going to see it.

Finally, one enhancement you could make to this scenario would be to
include a call in the dynamic libraries that would essentially answer
the question "how many steps do you need to complete?" This would allow
for a "progress indicator" where you could give a message like "5 steps
of 100 complete...". You could even enhance this more by *timing* the
steps and giving an estimated time of completion.

Regards,
MarkG

Vadim Zeitlin

unread,
Jul 23, 2009, 1:40:13 PM7/23/09
to wx-u...@googlegroups.com
On Thu, 23 Jul 2009 07:44:21 -0700 (PDT) DavidA <dand...@talktalk.net> wrote:

D> We would like to use wxWidgets to add a user interface. We would like
D> to do this by letting the kernel call wxWidgets just like any other of
D> the app's functions, in a continuous loop.

If you really do this in a continuous loop your program is consuming 100%
of the CPU time and this is not good. So while it's certainly possible to
do it like you wrote above, this would be a bad idea.

D> However, the wxWidgets samples suggest that all wxWidgets apps consist
D> of a class derived from wxApp.

You can use IMPLEMENT_APP_NO_MAIN() macro or even not use any macros at
all and just create your wxApp object yourself and call wxEntry(). But this
is not the problem.

D> I guess we would need to activate the message loop part of the
D> wxWidgets app. This would be like us calling GetMessage() in a windows
D> app. Is this possible with wxWidgets?

wxWidgets is rather flexible in this aspect, you can implement your own
wxEventLoop-derived class and tell it to use it. You can also hook into the
existing event loop which it runs, e.g. using idle messages as it was
advised in the other replies. The latter is usually the simplest solution
but if you really absolutely need to run the event loop yourself, you can
do this too, just ensure that all messages for wxWidgets windows are passed
to the library.

What is certain is that you do need an event loop for a GUI application,
using a continuous loop like you wrote is not the right way to do it.

Regards,
VZ

--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/

Mark Gollahon

unread,
Jul 23, 2009, 2:08:38 PM7/23/09
to wx-u...@googlegroups.com
Two reasons:

1. Because wxYield() can call the idle handler. If you are already in
the idle handler and call wxYield(), it can dispatch another idle event.
(Same idea if you are in a button handler that calls wxYield() - the
user could have pressed that button for a second time.) The idea here
is that any piece of code that calls wxYield() should itself be
re-entrant, plus those calls before it up to the dispatcher (and one
could argue any calls "below" it as well - see #2).

2. Because handlers could have other, "3rd party", state-keeping
functions in common. (This reason is hard to understand except to those
of you who have been involved in large teams with multiple libraries.)
If those functions have even subtle bugs in how they keep state or they
don't keep state in the same way, then re-entrancy is broken and a
wxYield() will highlight the bug (usually at a customer's site where you
can't get all the information needed to reproduce).

I've just learned to avoid wxYield(). Yes, it can be used in very
limited circumstances, but it is a kludge. If you have to use it, you
can be sure that something in your program is going to break because of
it. And, if you will allow me to invoke Murphy here, it will break in
the most non-obvious way possible.

Kenneth Porter

unread,
Jul 23, 2009, 3:10:02 PM7/23/09
to wx-u...@googlegroups.com
--On Thursday, July 23, 2009 8:44 AM -0700 DavidA <dand...@talktalk.net>
wrote:

> An alternative solution would be to run the user interface as a
> separate process and communicate with the main app using some form of
> IPC. However, I would like to consider a single application first to
> avoid the complexity of IPC.

Will the client also have its own GUI? Do you need to embed your dialogs
into their GUI? If so, it's gonna be tough to get wx's message pump and the
client's pump to play nice together in the same app. I'd be more inclined
to push your GUI to another process. It's really more a packaging problem,
and you've partly solved that by shipping your system as a separate DLL
calling yet other DLLs. Adding a .exe isn't that big a leap.

> We would like to use wxWidgets to add a user interface. We would like
> to do this by letting the kernel call wxWidgets just like any other of
> the app's functions, in a continuous loop.

I've thought about this as well, in my own framework. I don't expose wx to
the client. I'd like to provide a configuration dialog for the client's app
to use, but getting wx's pump to coexist with the native pump in the client
app has stopped me from pursuing that. So I try instead to provide enough
"knobs" as APIs so the client can provide their own configuration GUI.

> The app's own kernel calls each of the desired functions in
> turn. Each runs to completion and the next function is called. The app
> is a modelling tool and outputs results to text files. It has no user
> interface.

Instead of providing the GUI, I'd suggest providing status hooks that can
be called from a GUI thread. Your kernel runs in one of the app's worker
threads. The app can supply a hook that is invoked with current status,
packages it as a message, and posts it to the app's GUI. That makes the
hook code work with any GUI framework the client provides, such as MFC, Qt,
or wx. Your kernel can also monitor an abort flag set by another API so the
client can abort your kernel from a GUI button.

DavidA

unread,
Jul 27, 2009, 6:58:22 AM7/27/09
to wx-users
Hi

Firstly, I would like to thank everyone who has replied to my original
message. I do understand the concepts of GUI programming (having
written some Win32 and MFC programs). Indeed, we could convert our
application into a typical event-driven program, where the modelling
calculation would be run in response to idle messages. This would
require re-architecting our application to make it a 'typical'
wxWidgets application.

However, a significant architectural feature of our app is that all
modules are dynamically linked in response to xml files specified by
the user. Functionality can be linked in or omitted as required. This
gives us a lot of flexibility about how the app is built and
distributed. We very much want to provide a wxWidgets GUI as an
option, such that the wxWidgets libraries need only be linked in if
the GUI is required.

Vadim wrote:

>  You can use IMPLEMENT_APP_NO_MAIN() macro or even not use any macros at
> all and just create your wxApp object yourself and call wxEntry().
>
>  wxWidgets is rather flexible ... you can implement your own
> wxEventLoop-derived class and tell it to use it. You can also hook into the
> existing event loop which it runs, e.g. using idle messages as it was
> advised in the other replies. The latter is usually the simplest solution
> but if you really absolutely need to run the event loop yourself, you can
> do this too, just ensure that all messages for wxWidgets windows are passed
> to the library.

I want to persue the option of implementing my own wxEventLoop-derived
class. I would be very grateful for an outline of the steps required
to do this. What would the program skeleton look like?

Ideally, I would like an example. If anyone can point me to one that
would be great. I did find an example message loop here:

http://www.gamedev.net/community/forums/topic.asp?topic_id=539272

BR

David

Vadim Zeitlin

unread,
Jul 27, 2009, 10:37:51 AM7/27/09
to wx-u...@googlegroups.com
On Mon, 27 Jul 2009 03:58:22 -0700 (PDT) DavidA <dand...@talktalk.net> wrote:

D> However, a significant architectural feature of our app is that all
D> modules are dynamically linked in response to xml files specified by
D> the user. Functionality can be linked in or omitted as required. This
D> gives us a lot of flexibility about how the app is built and
D> distributed. We very much want to provide a wxWidgets GUI as an
D> option, such that the wxWidgets libraries need only be linked in if
D> the GUI is required.

The important question is whether you use some other GUI always or not. If
you do, you need to reconcile the message/event loop you currently use and
the wx one. If you don't, simpler solutions are possible, e.g. you could
start a separate thread running wx event loop when the wx plugin is loaded.
Keep this in mind before reading the rest -- maybe you don't need a custom
event loop after all.

D> I want to persue the option of implementing my own wxEventLoop-derived
D> class. I would be very grateful for an outline of the steps required
D> to do this. What would the program skeleton look like?

You need to derive YourTraits class from wxAppTraits and override the base
class CreateEventLoop() to return an instance of YourEventLoop and also
override wxApp::GetTraits() in YourApp to return an object of YourTraits
class. This will ensure that wxWidgets will create YourEventLoop whenever
it needs an event loop.

At YourEventLoop level you can always override Run() to implement some
completely custom logic. If you don't target wxGTK (which doesn't use
wxEventLoopManual as unfortunately GTK+ API is not flexible enough for
this), you can also override just OnNextIteration() method which is simpler
and is usually enough.

D> Ideally, I would like an example.

Unfortunately I don't know of any simple examples doing this. As defining
a custom event loop usually implies using another framework (not
necessarily a GUI one, e.g. I used this with ACE), it's a bit tricky to
make a sample for it. Still, any contributions would be welcome...

D> If anyone can point me to one that would be great. I did find an example
D> message loop here:
D>
D> http://www.gamedev.net/community/forums/topic.asp?topic_id=539272

This works too but I find the approach above with customizing the event
loop creation directly cleaner.

DavidA

unread,
Jul 27, 2009, 11:36:53 AM7/27/09
to wx-users
Hi Vadim

Thanks for your reply. As a first attempt I used the inherited MainLoop
() method as suggested in the link I posted. That worked ok. Your
solution, though no doubt much better, will need a lot more time for
me to understand. Perhaps I can look at that later.

The next step for me is to replace IMPLEMENT_APP with
IMPLEMENT_APP_NO_MAIN. Please will you suggest to me the correct
prototype for my main function? Would it be WinMain() or should I be
building a console app and just have a main()?

(I am currently building in Visual C++ 2008 Express and hacking the
internat sample).

What code must my main implement to activate wxWidgets?

BR

David

Vadim Zeitlin

unread,
Jul 27, 2009, 1:22:11 PM7/27/09
to wx-u...@googlegroups.com
On Mon, 27 Jul 2009 08:36:53 -0700 (PDT) DavidA <dand...@talktalk.net> wrote:

D> The next step for me is to replace IMPLEMENT_APP with
D> IMPLEMENT_APP_NO_MAIN. Please will you suggest to me the correct
D> prototype for my main function?

This depends on your project, i.e. it's all the same to wx where do you
call it from.

D> Would it be WinMain() or should I be building a console app and just
D> have a main()?

Is your project a GUI or console application when it doesn't use wx?

D> What code must my main implement to activate wxWidgets?

Calling wxEntry() will do everything, i.e. create a new application, new
event loop, run it, ... As I wrote before, you may do it another thread to
keep your main thread unblocked but then you should only use wx from that
other thread. And if you need more control you can use wxEntryStart() &c.

DavidA

unread,
Jul 28, 2009, 7:30:41 AM7/28/09
to wx-users
Hi Vadim

Thanks again.

> D> Would it be WinMain() or should I be building a console app and just
> D> have a main()?
>
>  Is your project a GUI or console application when it doesn't use wx?

I would like to create a Win32 Console application that will have my
own main(). My main() will then call wxWidgets to create a GUI frame.
This way, my app may run as a console app if I don't require a GUI, or
may optionally have a GUI interface. Is that possible?

David

Vadim Zeitlin

unread,
Jul 28, 2009, 8:23:21 AM7/28/09
to wx-u...@googlegroups.com
On Tue, 28 Jul 2009 04:30:41 -0700 (PDT) DavidA <dand...@talktalk.net> wrote:

D> > D> Would it be WinMain() or should I be building a console app and just
D> > D> have a main()?
D> >
D> >  Is your project a GUI or console application when it doesn't use wx?
D>
D> I would like to create a Win32 Console application that will have my
D> own main(). My main() will then call wxWidgets to create a GUI frame.
D> This way, my app may run as a console app if I don't require a GUI, or
D> may optionally have a GUI interface. Is that possible?

Yes, but notice that console applications under Win32 will always create a
console which may be not what you want because even if you delete it when
you launch the GUI it will still briefly appear on screen.

DavidA

unread,
Jul 28, 2009, 10:19:17 AM7/28/09
to wx-users
Hi Vadim

I have hacked together the code below for a Win32 console program that
will display a wxWidgets frame. Presently there are many compile
errors. Please will you check whether my approach is correct?

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

bool running = true;

class MyFrame: public wxFrame
{
public:
MyFrame(const wxString& title, const wxPoint& pos, const wxSize&
size);
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
DECLARE_EVENT_TABLE()
};

class MyApp: public wxApp
{
virtual bool OnInit();
virtual int MainLoop();

MyFrame* mp_frame;
};

enum {ID_Quit = 1, ID_About, };

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_Quit, MyFrame::OnQuit)
END_EVENT_TABLE()

bool MyApp::OnInit()
{
mp_frame = new MyFrame( _T("Demo"), wxPoint(50,50), wxSize
(450,340) );
mp_frame->Show(TRUE);
SetTopWindow(mp_frame);
return TRUE;
}

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const
wxSize& size)
: wxFrame((wxFrame *)NULL, -1, title, pos, size)
{
wxMenu *menuFile = new wxMenu;

menuFile->Append( ID_Quit, _T("E&xit") );

wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append( menuFile, _T("&File") );

SetMenuBar( menuBar );
}

void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
running = false;
Close(TRUE);
}

bool MyApp::OnInit()
{
mp_frame = new MyFrame( _T("TML external message loop demo"),
wxPoint(50,50), wxSize(450,340) );
mp_frame->Show(TRUE);
SetTopWindow(mp_frame);
return TRUE;
}

int main(int argc, char **argv)
{
wxInitializer initializer;
if ( !initializer )
{
fprintf(stderr, "Failed to initialize the wxWidgets library,
aborting.");
return -1;
}

wxUnusedVar(argc);
wxUnusedVar(argv);

wxEntry(argc, argv);

return 0;
}

Vadim Zeitlin

unread,
Jul 28, 2009, 12:38:33 PM7/28/09
to wx-u...@googlegroups.com
On Tue, 28 Jul 2009 07:19:17 -0700 (PDT) DavidA <dand...@talktalk.net> wrote:

D> I have hacked together the code below for a Win32 console program that
D> will display a wxWidgets frame. Presently there are many compile
D> errors.

Wouldn't it be better to fix them first?

D> Please will you check whether my approach is correct?

If you want wx to create MyApp instance you must use
IMPLEMENT_APP_NO_MAIN() macro, otherwise this doesn't risk to happen. Also,
there is no need to use wxInitializer if you call wxEntry() as the latter
will do it itself (OTOH there is no real harm neither).

But frankly, I could have missed something. Sorry but I don't really have
time to review this code, if you have some concrete problems and can't
solve them yourself I'll try to help but I can't really do much otherwise.

DavidA

unread,
Jul 28, 2009, 1:00:24 PM7/28/09
to wx-users
>  But frankly, I could have missed something. Sorry but I don't really have
> time to review this code, if you have some concrete problems and can't
> solve them yourself I'll try to help but I can't really do much otherwise.

Understood. I don't want to waste your time. I now have the compile
errors fixed but the linker fails with many errors. I am suspecting
that the project's preprocessor definitions and the library
specifications are wrong. I am using:

Definitions:
WIN32;_DEBUG;__WXMSW__;__WXDEBUG__;_CONSOLE;wxUSE_GUI=1

Libraries:
C:\wxWidgets-2.8.10\lib\vc_lib

Note, if I use wxUSE_GUI=0 I get a lot of compile errors in wx/
cursor.h such as: error C3861: 'wxIsBusy': identifier not found

Please will you take a brief look at the above to see if anything is
obviously wrong for a console app that may create a form?

David

Vadim Zeitlin

unread,
Jul 28, 2009, 4:13:00 PM7/28/09
to wx-u...@googlegroups.com
On Tue, 28 Jul 2009 10:00:24 -0700 (PDT) DavidA <dand...@talktalk.net> wrote:

D> Understood. I don't want to waste your time. I now have the compile
D> errors fixed but the linker fails with many errors. I am suspecting
D> that the project's preprocessor definitions and the library
D> specifications are wrong.

The best would be to start from a working example, e.g. the minimal wx
sample. Then you can just replace IMPLEMENT_APP() in it with
IMPLEMENT_APP_NO_MAIN() and add your main() function and change the build
to use console subsystem.

D> Definitions:
D> WIN32;_DEBUG;__WXMSW__;__WXDEBUG__;_CONSOLE;wxUSE_GUI=1
D>
D> Libraries:
D> C:\wxWidgets-2.8.10\lib\vc_lib

This looks correct.

D> Note, if I use wxUSE_GUI=0

This would mean that you don't use any wx GUI classes at all which is not
the case.

DavidA

unread,
Jul 29, 2009, 3:47:49 AM7/29/09
to wx-users
Hi Vadim

>  The best would be to start from a working example, e.g. the minimal wx
> sample. Then you can just replace IMPLEMENT_APP() in it with
> IMPLEMENT_APP_NO_MAIN() and add your main() function and change the build
> to use console subsystem.

A problem for me is that I want to develop a console app, but the only
console sample I can find is 'console' and that uses neither
IMPLEMENT_APP() nor IMPLEMENT_APP_NO_MAIN(). Neither does it have a
GUI. So it's not easy to start from a working example.

I'll try modifying 'console' to have a GUI...

David

DavidA

unread,
Jul 29, 2009, 6:25:03 AM7/29/09
to wx-users
Hi Vadim

May I request a little more help please?

I now have a working console app that has a frame, that has my own main
() and an overridden message loop. An outline of my code (much detail
excluded for clarity) is:

void MyLoop() {
// Create new event loop
...

// Run loop
while(true) {
while (PeekMessage( &msg, (HWND)0, 0, 0, PM_REMOVE )) {
if (!eventLoop->PreProcessMessage(&msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// Do something here (set a gauge)
wxGetApp().mp_frame->mp_gauge->SetValue(gaugeValue++);
}
}

int MyApp::MainLoop() { // Overridden loop
MyLoop();
return 0;
}

main() {
wxEntry();
}

This works fine. Now I want to take the loop out of class MyApp and
call it from main():

main() {
MyApp* pMyApp = new(MyApp); // Create my own instance of MyApp
here
wxEntry;
MyLoop();
}

However this fails with an access violation in MyLoop() because
wxGetApp() is no longer valid. This is even though I have instantiated
my App object in main(). I guess wxEntry is destroying MyApp. Is this
likely? How can I prevent the destruction?

David

DavidA

unread,
Jul 29, 2009, 7:22:54 AM7/29/09
to wx-users
I'm now thinking that wxAppPtr is a smart pointer and is destroying
the app object when wxEntry returns. Is there any way around this?

Vadim Zeitlin

unread,
Jul 29, 2009, 8:33:09 AM7/29/09
to wx-u...@googlegroups.com
On Wed, 29 Jul 2009 04:22:54 -0700 (PDT) DavidA <dand...@talktalk.net> wrote:

D> I'm now thinking that wxAppPtr is a smart pointer and is destroying
D> the app object when wxEntry returns. Is there any way around this?

You need to call wxEntryStart() instead of wxEntry() if you don't want to
run the event loop.

I still wonder if you're really trying to do what you need at all though
because whenever you run the event loop it still doesn't return until it's
exited (which usually happens when the last window is closed). I don't see
how calling it from wxEntry() or outside of it can change anything.

DavidA

unread,
Jul 29, 2009, 8:51:42 AM7/29/09
to wx-users
>  You need to call wxEntryStart() instead of wxEntry() if you don't want to
> run the event loop.

Ok, thanks. But EntryStart() does:

bool wxEntryStart(int& argc, wxChar **argv)
{
// do minimal, always necessary, initialization
[snip]
// first of all, we need an application object

// the user might have already created it himself somehow
wxAppPtr app(wxTheApp);
[snip]
}

I think wxAppPtr will destroy my app when wxEntryStart exits. If the
code allows for the user to have pre-created the object why does it
insist on deleting it before leaving?

>  I still wonder if you're really trying to do what you need at all though
> because whenever you run the event loop it still doesn't return until it's
> exited (which usually happens when the last window is closed). I don't see
> how calling it from wxEntry() or outside of it can change anything.

My strategy may well be flawed. But I will use peekMessage() to allow
me to do some idle processing between servicing the GUI. This is
normally done in an overridden message loop eg App::MainLoop(). My
current goal is to call peekMessage() from main() instead of from
within the App object. I just need to be able to run the loop within a
C function instead of an object.

David

Vadim Zeitlin

unread,
Jul 29, 2009, 8:56:06 AM7/29/09
to wx-u...@googlegroups.com
On Wed, 29 Jul 2009 05:51:42 -0700 (PDT) DavidA <dand...@talktalk.net> wrote:

D> >  You need to call wxEntryStart() instead of wxEntry() if you don't want to
D> > run the event loop.
D>
D> Ok, thanks. But EntryStart() does:
D>
D> bool wxEntryStart(int& argc, wxChar **argv)
D> {
D> // do minimal, always necessary, initialization
D> [snip]
D> // first of all, we need an application object
D>
D> // the user might have already created it himself somehow
D> wxAppPtr app(wxTheApp);
D> [snip]
D> }
D>
D> I think wxAppPtr will destroy my app when wxEntryStart exits. If the
D> code allows for the user to have pre-created the object why does it
D> insist on deleting it before leaving?

It doesn't, you're missing "app.release()" call later in this function.

D> >  I still wonder if you're really trying to do what you need at all though
D> > because whenever you run the event loop it still doesn't return until it's
D> > exited (which usually happens when the last window is closed). I don't see
D> > how calling it from wxEntry() or outside of it can change anything.
D>
D> My strategy may well be flawed. But I will use peekMessage() to allow
D> me to do some idle processing between servicing the GUI.

I may be missing something but it does seem flawed to me. You really
should reuse wx idle processing if this is what you want.

D> This is normally done in an overridden message loop eg App::MainLoop().
D> My current goal is to call peekMessage() from main() instead of from
D> within the App object. I just need to be able to run the loop within a C
D> function instead of an object.

In any case I don't see how it possibly might be relevant where is your
main loop called from. There is absolutely no difference between running it
from main() or from anywhere else. Let me be blunt but I think you're
losing your time on immaterial things while disregarding the real problem
you need to solve.

DavidA

unread,
Jul 29, 2009, 10:18:12 AM7/29/09
to wx-users
Hi Vadim

I think I'm there now. Sorry about the numerous red herrings I
mentioned (the smart pointer does not destroy the app).

I now have PeekMessage() running in main(). I can call peekMessage()
(and the translate/dispatch functions) regularly as well as doing
other work.

Thanks for bearing with me and for your help.

David

DavidA

unread,
Jul 29, 2009, 10:38:17 AM7/29/09
to wx-users
Vadim

Sorry, I missed your last message.

>  It doesn't, you're missing "app.release()" call later in this function.

Thanks.

> Let me be blunt but I think you're
> losing your time on immaterial things while disregarding the real problem
> you need to solve.

I appreciate your bluntness but I think that the constraints we have
require our application to work this way. I do understand the
conventional options such as idle processing. Thanks for your warnings
but I think I can proceed (cautiously) in this way.

David
Reply all
Reply to author
Forward
0 new messages