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/
> 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.
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.
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.
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.
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.
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.
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.
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.