views:

199

answers:

3

We have a command line application that could benefit from a GUI. We want to add some plotting functionality and have identified a plotting library that uses MFC. Initially we developed a separate app, but we'd rather have the GUI in the same process space.

I was thinking of possibly a GUI in an MFC DLL that could be hosted in the production app AND in a testing app.

The questions are:

  • What are the steps necessary to add an MFC GUI to a win32 command line app
  • Is it possible to make a GUI in an MFC DLL and how can it be done? (so that different apps can reuse the same GUI)

EDIT

I should add that this is an unmanaged app (and needs to stay that way - it needs to be highly performant, makes extensive use of templates, boost, custom allocators, internally developed thread serialization, etc)

RESULTS:

Nick D's answer worked great - especially the follow-up link in his comment with the details about a regular MFC DLL.

Note that we will be using Qt for the next iteration. Modifying our build environment and getting used to a a new framework was just too much this time around.

+3  A: 

You can call/reuse GUI code in a dll. (I even use Delphi forms in my C++ projects)

A very simple dll example:

// The DLL exports foo() function
void foo()
{
    AFX_MANAGE_STATE( AfxGetStaticModuleState() );

    CDlgFoo dlg;
    dlg.DoModal();
}

In the console program you'll have code like this:

h = ::LoadLibrary( "my.dll" );
::DisableThreadLibraryCalls( h ); 
pfoo = (foo_type*)::GetProcAddress( h, (const char*)1 );
if ( pfoo ) pfoo();
Nick D
Ah, the dreaded afx_manage_state - I recall that vaguely from 1995 or so...
Tim
Great - is there anything else I have to do in the non-mfc app? It will just work? I would imagine I would start a new thread for that thread/gui function? What is the name of the exported method I need to call in GetProcAddress (assuming a dlg based gui)?
Tim
in my example `GetProcAddress(h, "foo")` should also work. I don't think you need an extra thread for the gui code, but that depends on your needs.
Nick D
@tim, check out this tutorial: http://www.codeguru.com/cpp/cpp/cpp_mfc/tutorials/article.php/c4017/
Nick D
+1  A: 

First, you will have to surrender WinMain().

If you still want to retain the command-line arguments functionality, process command arguments in InitInstance() of your App class.

Pavel Radzivilovsky
What do you mean by "surrender" winmain? The exe is a comman line exe - no gui, no event loop - just a main
Tim
I meant to surrender the app entry point. That is, main() for your CLI app and WinMain() for the GUI app. MFC, being a framework rather than a library, implements WinMain() entry point of its own and you cannot have two.
Pavel Radzivilovsky
So I can't just call into a dll or something and start a new thread for it to use as its GUI thread/event loop?
Tim
+1  A: 

The straight forward approach would be to add a switch to your program and given a certain value it will launch the gui, otherwise use the command line options. Something like "app.exe -mode=gui". If you don't see this command arg on program launch, fall back to the old command line behavior.

Regarding the DLL, you could write all the UI functionality in a DLL and use it from your "production app" where you have a message loop running and a WinMain. But what's the point? If it's for testing purposes why not just separate the presentation from the logic and test the logic alone. How do you intend to test the UI in your test app anyway? Simulate button clicks?

Idan K
+1 for different run "modes - gui/no gui. I was thinking of that too - we'd want to run with gui on or off without recompiling. The testing is really so that I don't need the live app - the gui is pretty minimal - a histogram - the main exe collects lots and lots of data and has some significant resource dependencies. I want a lightweight test app that can feed it timple data.
Tim
to me this looks like a perfect example where you need to move the logic to a library (dll) and use the library in the test/production app.
Idan K
and while we're on the subject of GUI, any reason for picking MFC? I highly suggest Qt (you get cross platform for free, you never know...). I also found some plotting widgets here http://qwt.sourceforge.net/ and I bet there are more.
Idan K
I understand Qt is great, but we have more experience with MFC and the charting library we use has been tested with mfc. We were trying wxwidgets, but the learning curve for using a new UI framework was not helping out. I looked at lots of pl I'd love to use Qt and that plotting library, but we have some time pressure and we are unfamiliar.
Tim
This is also the reason I want to keep the GUI separate - as we know we are going to go cross-platform eventually. We will migrate to another plotting and UI framework - just not for v1 (or at least that is the current plan)
Tim
I'll look into qt again. Since our initial release GUI requirements are scaled back we might be able to do all the things we need with minimal learning.
Tim
I am also a little wary of the licensing of qt.
Tim
@tim, if you can avoid MFC for GUI development do it ;-) I don't know about Qt but Delphi's framework is a joy to use.
Nick D
I don't think you have anything to worry about Qt's licensing, it is LGPL. if you plan on going cross platform sometime in the future, all the more reason to avoid MFC as much as you can :) I think you'll be surprised at how clean Qt is and how relatively fast you can get into it.
Idan K