[Home]  [Prev]  [Next]    A guide, a tutorial for developing well-designed cross-platform applications

11. Miscellaneous

There are several functions which aren't directly visible in the GUI of an application and therefore often get forgotten.


11.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 achieved 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

Don't forget to add the crashprint sources to your project, they aren't currently part of wxWidgets but from wxCode.

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

}


11.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;
}


11.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;
}