10. Miscellaneous
There are several functions which aren't directly visible in the GUI of an application and therefore often get forgotten.
10.1 Crash report
Since some OpenSource seems to crash (IMO happens too often) it's necessary to report the crash stack trace with as much as possible information. This can be achived under GTK with wxCrashPrint, of course only if the debug symbols are available. Under Windows it's possible through the use of the BlackBox.dll (see here).
Sample code: Crashprint
#if defined(__linux__)
#include "wx/crashprint.h" // CrashPrint backtrace
#endif
...
#if defined(__linux__)
//! crashprint
wxCrashPrint g_crashprint;
#endif
...
class App: public wxApp {
public:
//! the main function called durning application start
virtual bool OnInit ();
#if defined(__linux__)
//! fatal exeption handling
void OnFatalException();
#endif
...
}
bool App::OnInit () {
#if defined(__linux__)
// fatal exceptions handling
wxHandleFatalExceptions (true);
#endif
...
}
#if defined(__linux__)
void App::OnFatalException () {
g_crashprint.Report();
}
#endif
Sample code: BackBox.dll
#include <wx/dynlib.h> // dynamic library support
...
class App: public wxApp {
public:
//! the main function called durning application start
virtual bool OnInit ();
//! application exit function
virtual int OnExit ();
...
private:
#if defined(__WINDOWS__)
//! BlackBox dll (crash handling)
wxDynamicLibrary m_blackboxDll;
#endif
...
}
bool App::OnInit () {
#if defined(__WINDOWS__)
// BlackBox dll (crash handling)
m_blackboxDll.Load (_T("BlackBox.dll"));
#endif
...
}
int App::OnExit () {
#if defined(__WINDOWS__)
// unload BlackBox dll
if (m_blackboxDll.IsLoaded()) m_blackboxDll.Unload ();
#endif
...
}
10.2 Command line
The command line is usually associated with non-GUI application but that isn't true. When a system allows starting an app with parameters these are sent to the application as a command line. Therefore any app should handle command lines. The following sample shows how to handle filenames sent through the command line.
Sample code
#include <wx/cmdline.h> // command line support
class App: public wxApp {
friend class AppFrame;
...
//! command line
wxArrayString *m_fnames;
bool ProcessCmdLine (wxChar** argv, int argc = 0);
};
bool App::OnInit () {
...
// get and process command line
m_fnames = new wxArrayString();
ProcessCmdLine (argv, argc);
...
}
int App::OnExit () {
...
// delete command line fnames
if (m_fnames) delete m_fnames;
...
}
bool App::ProcessCmdLine (wxChar** argv, int argc) {
// get and process command line
static const wxCmdLineEntryDesc cmdLineDesc[] = {
{wxCMD_LINE_PARAM, NULL, NULL, _T("input files"),
wxCMD_LINE_VAL_STRING,
wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE},
{wxCMD_LINE_NONE}
};
wxCmdLineParser parser (cmdLineDesc, argc, argv);
// get filenames from the command line
m_fnames->Clear();
if (parser.Parse() == 0) {
for (size_t paramNr=0; paramNr < parser.GetParamCount(); paramNr++) {
m_fnames->Add (parser.GetParam (paramNr));
}
}
return true;
}
10.3 Drop files onto application
Usually an application which opens files should also allow dropping files onto it. Be carefully where (onto which window) files can be dropped.
Sample code
static wxString g_appname;
class AppFrame: public wxFrame {
friend class DropFiles;
...
};
class DropFiles: public wxFileDropTarget {
public:
//! constructor
DropFiles (AppFrame *frame) {m_frame = frame;}
virtual bool OnDropFiles (wxCoord x, wxCoord y, const wxArrayString& filenames);
private:
AppFrame *m_frame;
};
AppFrame::AppFrame (...
...
// initialize drop files
SetDropTarget (new DropFiles (this));
...
};
bool DropFiles::OnDropFiles (wxCoord x, wxCoord y, const wxArrayString& filenames) {
for (size_t n = 0; n < filenames.Count(); n++) {
if (wxFileName(filenames[n]).IsDir()) {
wxMessageBox (_("It is currently not allowed to drop \n"
"directories onto the editor!"),
_("Error"), wxOK | wxICON_EXCLAMATION);
return FALSE;
}
}
m_frame->FileOpen (filenames);
m_frame->m_book->SetFocus();
wxString title = g_appname + " " + m_frame->m_edit->GetFilename();
m_frame->SetTitle (title);
return TRUE;
}