I have a command-line application written in C++ and built with gcc/make that runs on MacOS. This application does not have its own GUI and it not supposed to have any root windows -- it's a console app meant to be controlled by another application.
However, there is a need to show a file selection dialog at one point, which makes this a bit of a hybrid.
I've used wxWidgets to create the dialog, but it fails to get input. I've seen in the various FAQs and user groups that a bundle is probably required. When I tried to create a bundle it didn't solve the problem.
Here's how wxWidgets is initialized:
#ifdef __WXMAC__
if (!wxEntryStart(argc, argv))
{
cout << "Failed to initialize wxWidgets." << endl;
return 0;
}
#endif
clientApp = new MainClass();
clientApp->Run(argc, argv);
#ifdef __WXMAC__
wxEntryCleanup();
#endif
When I try to show a browse file dialog, using this code, it shows the file chooser but does not respond, acting like it has no message pump:
#ifdef __WXMAC__
wxFileDialog* dlg = new wxFileDialog( NULL, _("Upload File"), _(""), _(""),
_("All Files (*.*)|*.*"), wxFD_OPEN|wxFD_FILE_MUST_EXIST );
if (dlg->ShowModal() == wxID_CANCEL )
{
INFOLOG("File upload dialog has been cancelled." << endl )
return false;
}
#endif
Since the FAQs say that creating a bundle is a way to automagically create a message pump and make a GUI responsive. I tried creating a bundle:
myapp.app --> Contents --> MacOS --> myapp (executable file) --> cert.crt (ssl certificate used by app) --> Resources --> myapp.icns --> Info.plist (points ot myapp as executable and uses myapp.icns as icon)
The application controlling this is not one I have control over and has to run it in exactly this way:
myapp
The controlling app needs to read the console output of this app and that is primarily why this has been a console-only app.
Since the executable is a few directories deeper, I tried creating a shell script in the root directory above the bundle to run the application and calling it myapp. Myapp just runs myapp.app/Contents/MacOS/myapp, forwarding the commandline parameters.
This didn't work. The browse file window is created and just sits there, giving me the rainbow spinwheel every time I mouse over it.
What can I do to get a message pump going? Is there a call I can add to the wxWidgets code or do I need to do something differnently with the bundle? Does having the shell script launch 开发者_Go百科the app that is inside the bundle completely defeat the "message pump magic" that the bundle is supposed to give, and if so, is there a sensible workaround? Do I just need to create some sort of pseudo-parent for the wxFileDialog?
I've heard reports that an alternative to creating an application bundle is to use the following code (which I never recommend to anyone over a bundle, but it sounds like your situation is a good reason to use it):
#include <ApplicationServices/ApplicationServices.h>
ProcessSerialNumber PSN;
GetCurrentProcess(&PSN);
TransformProcessType(&PSN,kProcessTransformToForegroundApplication);
This is of course platform specific, so wrap it accordingly.
Do you have a derived wxApp, and wxApp::OnInit()? These are likely still required to initialize the event loop.
You can make your app a full GUI app and just hide the main window using wxWindow::Show( false ). This will give you your working message pump. You should still be able to catch stdout and stderror.
精彩评论