Writing Your First Application-Common Dialogs
Besides creating your own dialog windows, in wxWidgets it is easy to use whats called "common dialogs". Common dialogs are pre-made dialogs for various operations. The advantage is that there is less work involved in creating the dialogs, and the dialogs inherit the look and feel of the operating system on which your application runs. This is a big advantage for creating portable applications.
There are common dialogs ranging from a simple message box, to a user input box, to a full, file selection dialog. We cover the file selection dialog for opening and saving files here. If you would like to see what other ones are available there is some good information in the manual.
Initializing the file selection dialog isn't hard--we just declare a new wxFileDialog object and initialize it with the following arguments:
- A parent window. We'll just use this.
- The title for the dialog window.
- The default directory. We'll just use an empty string.
- The default file name. Again we'll use a empty string.
- A wildcard for the file types we'll be using in this format: "File type (*.ext)|*.ext|"
- The dialog style. Use either wxFD_OPEN if you intend to open a file, wxFD_MULTIPLE to allow multiple file selections, wxFD_SAVE if it is intended to save a file, and wxFD_OVERWRITE_PROMPT to prompt the user for confirmation if they attempt to overwrite a file.
When we want to get the data for the file the user selected, we first check to see if wxFileDialog->ShowModal() returns wxID_OK (meaning the user pressed the "OK" button). Then we use GetDirectory to return the directory the in which the file is located, GetFilename to return the file name without the directory, GetFilenames if we set wxMULTIPLE when creating the dialog, and GetPath to return the full path to the file chosen. Heres an example of an improved OpenFile() function:
void MainFrame::OpenFile(wxCommandEvent& WXUNUSED(event))
{
wxFileDialog* OpenDialog = new wxFileDialog(
this, _("Choose a file to open"), wxEmptyString, wxEmptyString,
_("Text files (*.txt)|*.txt|C++ Source Files (*.cpp, *.cxx)|*.cpp;*.cxx|
C Source files (*.c)|*.c|C header files (*.h)|*.h"),
wxFD_OPEN, wxDefaultPosition);
// Creates a "open file" dialog with 4 file types
if (OpenDialog->ShowModal() == wxID_OK) // if the user click "Open" instead of "Cancel"
{
CurrentDocPath = OpenDialog->GetPath();
// Sets our current document to the file the user selected
MainEditBox->LoadFile(CurrentDocPath); //Opens that file
SetTitle(wxString("Edit - ") <<
OpenDialog->GetFilename()); // Set the Title to reflect the file open
}
// Clean up after ourselves
OpenDialog->Destroy();
}
And here is the source to create this:
#include <wx/string.h>
#include <wx/menu.h>
#include <wx/textctrl.h>
// MainApp is the class for our application, it just acts
// as a container for the window or frame in MainFrame.
class MainApp: public wxApp
{
public:
virtual bool OnInit();
};
// MainFrame is the class for our window, it
// contains the window and all objects in it.
class MainFrame: public wxFrame
{
public:
MainFrame( const wxString &title, const wxPoint &pos, const wxSize &size );
void Quit( wxCommandEvent& event );
void NewFile( wxCommandEvent& event );
void OpenFile( wxCommandEvent& event );
void SaveFile( wxCommandEvent& event );
void SaveFileAs( wxCommandEvent& event );
void CloseFile( wxCommandEvent& event );
wxTextCtrl *MainEditBox;
wxMenuBar *MainMenu;
// The Path to the file we have open
wxString CurrentDocPath;
DECLARE_EVENT_TABLE()
};
enum
{
// declares an id which will be used to call our button
TEXT_Main = wxID_HIGHEST + 1,
MENU_New,
MENU_Open,
MENU_Close,
MENU_Save,
MENU_SaveAs,
MENU_Quit
};
BEGIN_EVENT_TABLE ( MainFrame, wxFrame )
EVT_MENU(MENU_New, MainFrame::NewFile)
EVT_MENU(MENU_Open, MainFrame::OpenFile)
EVT_MENU(MENU_Close, MainFrame::CloseFile)
EVT_MENU(MENU_Save, MainFrame::SaveFile)
EVT_MENU(MENU_SaveAs, MainFrame::SaveFileAs)
EVT_MENU(MENU_Quit, MainFrame::Quit)
END_EVENT_TABLE()
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
# include <wx/wx.h>
#endif
#include "base.h"
IMPLEMENT_APP(MainApp) // Initializes the MainApp class...
// .. and tells our program to run it
bool MainApp::OnInit()
{
// Create an instance of our frame, or window
MainFrame *MainWin = new MainFrame(
_("Edit"), wxPoint(1, 1), wxSize(300, 200));
MainWin->Show(TRUE); // show the window
SetTopWindow(MainWin); // and finally, set it as the main window
return TRUE;
}
MainFrame::MainFrame(const wxString &title, const wxPoint &pos, const wxSize &size)
: wxFrame((wxFrame*) NULL, -1, title, pos, size)
{
CreateStatusBar(2);
MainMenu = new wxMenuBar();
wxMenu *FileMenu = new wxMenu();
FileMenu->Append(MENU_New,
_("&New"), _("Create a new file"));
FileMenu->AppendSeparator();
FileMenu->Append(MENU_Open,
_("&Open"), _("Open an existing file"));
FileMenu->Append(MENU_Close,
_("&Close"), _("Close the current document"));
FileMenu->AppendSeparator();
FileMenu->Append(MENU_Save,
_("&Save"), _("Save the current document"));
FileMenu->Append(MENU_SaveAs,
_("Save &As"), _("Save the current document under a new file name"));
FileMenu->AppendSeparator();
FileMenu->Append(MENU_Quit,
_("&Quit"), _("Quit the editor"));
MainMenu->Append(FileMenu, _("&File"));
SetMenuBar(MainMenu);
MainEditBox = new wxTextCtrl(
this, TEXT_Main, _("Hi!"), wxDefaultPosition, wxDefaultSize,
wxTE_MULTILINE | wxTE_RICH , wxDefaultValidator, wxTextCtrlNameStr);
Maximize(); // Maximize the window
}
void MainFrame::NewFile(wxCommandEvent& WXUNUSED(event))
{
// Clear the edit box
MainEditBox->Clear();
// reset the path of our current open file
CurrentDocPath = wxT("C:/");
// Set the Title to reflect the file open
SetTitle(_("Edit - untitled *"));
}
void MainFrame::OpenFile(wxCommandEvent& WXUNUSED(event))
{
wxFileDialog *OpenDialog = new wxFileDialog(
this, _("Choose a file to open"), wxEmptyString, wxEmptyString,
_("Text files (*.txt)|*.txt|C++ Source Files (*.cpp, *.cxx)|*.cpp;*.cxx|
C Source files (*.c)|*.c|C header files (*.h)|*.h"),
wxFD_OPEN, wxDefaultPosition);
// Creates a "open file" dialog with 4 file types
if (OpenDialog->ShowModal() == wxID_OK) // if the user click "Open" instead of "cancel"
{
CurrentDocPath = OpenDialog->GetPath();
// Sets our current document to the file the user selected
MainEditBox->LoadFile(CurrentDocPath); //Opens that file
// Set the Title to reflect the file open
SetTitle(wxString("Edit - ") << OpenDialog->GetFilename());
}
}
void MainFrame::CloseFile(wxCommandEvent& WXUNUSED(event))
{
// Clear the Text Box
MainEditBox->Clear();
// Reset the current File being edited
CurrentDocPath = wxT("C:/");
// Set the Title to reflect the file open
SetTitle(_("Edit - untitled *"));
}
void MainFrame::SaveFile(wxCommandEvent& WXUNUSED(event))
{
// Save to the already-set path for the document
MainEditBox->SaveFile(CurrentDocPath);
}
void MainFrame::SaveFileAs(wxCommandEvent& WXUNUSED(event))
{
wxFileDialog *SaveDialog = new wxFileDialog(
this, _("Save File As _?"), wxEmptyString, wxEmptyString,
_("Text files (*.txt)|*.txt|C++ Source Files (*.cpp)|*.cpp|
C Source files (*.c)|*.c|C header files (*.h)|*.h"),
wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
// Creates a Save Dialog with 4 file types
if (SaveDialog->ShowModal() == wxID_OK) // If the user clicked "OK"
{
CurrentDocPath = SaveDialog->GetPath();
// set the path of our current document to the file the user chose to save under
MainEditBox->SaveFile(CurrentDocPath); // Save the file to the selected path
// Set the Title to reflect the file open
SetTitle(wxString("Edit - ") << SaveDialog->GetFilename());
}
// Clean up after ourselves
SaveDialog->Destroy();
}
void MainFrame::Quit(wxCommandEvent& WXUNUSED(event))
{
Close(TRUE); // Close the window
}