Writing Your First Application-Using The WxTextCtrl

From WxWiki
Jump to navigation Jump to search

Hi and welcome to the third lesson of this tutorial. In this lesson we will be learning to use the wxWindows text control, and add menus and a status bar to our frame. I'm going to take a different approach to these tutorials now. We've gotten far enough into the series (and the code has gotten long enough) so I will now be giving you code for doing smaller functions in the beginning, and at the end of the tutorial I will give you the complete code to the program. Of course, trying to put together the code from the bits and pieces I give you before typing it into your compiler certainly wouldn't hurt (yeah, like your really going to do that) ;)

Firstly, lets add a status bar! This isn't as hard as it may sound, and can actually be done with one simple line of code:

  MainFrame::MainFrame(const wxString &title, const wxPoint &pos, const wxSize &size) \
                       : wxFrame((wxFrame *) NULL, -1, title, pos, size)
  {
  
  CreateStatusBar(2);
  
  ...
  
  }

There, wasn't that hard? The first and only argument is just how many sections the status bar can have. If you only want to display one message in the status bar at a time set it to '1';, if you want more, set it to another number.

Now, lets replace that ugly button with a nice text box. ( My goal for this tutorial is to eventually create a nice, simple text editor ) Instead of including wx/button.h we include wx/textctrl.h, and change the classname from wxButton to wxTextCtrl.

In "base.h":

  ...
  
  class MainFrame: public wxFrame // MainFrame is the class for our window,
  { // It contains the window and all objects in it
  
  public: 
  
    MainFrame( const wxString &title, const wxPoint &pos, const wxSize &size );
    wxTextCtrl *MainEditBox;
  
  ...
  
  };

In "base.cpp":

  ...
  
  MainFrame::MainFrame(const wxString &title, const wxPoint &pos, const wxSize &size)
  : wxFrame((wxFrame *) NULL, -1, title, pos, size)
  {
  // Initialize our text box with an id of TEXT_Main, and the label "hi"
  MainEditBox = new wxTextCtrl(this, TEXT_Main, "Hi!", wxDefaultPosition, wxDefaultSize,  
    wxTE_MULTILINE | wxTE_RICH , wxDefaultValidator, wxTextCtrlNameStr);
  
  ...

I won't go into detail on the initialization of this object as it is pretty much the same as the constructor for wxButton. However, if you would like to learn more about the styles it can take, there is some more information in the manual. The wxTextCtrl class has many helpful functions, but we'll be looking at just three. These three are: LoadFile("filename.txt"), SaveFile("filename.txt"), and Clear(). You should be able to guess that LoadFile() loads the contents of the file name given into the text control, SaveFile() saves the contents of the textbox to the given file name, and Clear() clears the contents of the text control.

Now to add the menu bar. It is not hard to add a menu bar to the current frame, and the events for menu items work just the same as the one for the button we created in the last lesson. First off, we include , and create an instance of a menu bar with:

  MainMenu = new wxMenuBar();

Now we need a menu to put on it, we'll start with the traditional file menu:

  wxMenu *FileMenu = new wxMenu();

Now that we've declared a menu, and the menu bar, lets add some items to it. We can add a quit option ( using the id of MENU_Quit ) by typing:

  FileMenu->Append(MENU_Quit, "&Quit", "Quit the editor");
  /* Adds a menu item with the label "Quit", id of MENU_Quit, and set the status bar caption to 
  "Quit the editor" when the mouse hovers over it.
  We can also use FileMenu->AppendSeparator() to add a menu separator */

Now, we simply append the File menu to our Menu Bar, and tell the frame that "MainMenu" should be its menu bar.

  MainMenu->Append(FileMenu, "&File");
  SetMenuBar(MainMenu);

Now, if we use the source code below, we get an application that looks like this:

  #ifndef __BASE_H // Make sure to only declare these classes once
  #define __BASE_H
  #include <wx/frame.h>
  #include <wx/textctrl.h>

  class MainApp: public wxApp // MainApp is the class for our application
  { // MainApp just acts as a container for the window,
  public: // or frame in MainFrame
    virtual bool OnInit();
  };

  class MainFrame: public wxFrame // MainFrame is the class for our window,
  { // It contains the window and all objects in it
  public:
    MainFrame( const wxString& title, const wxPoint& pos, const wxSize& size );
    wxTextCtrl *MainEditBox;
    wxMenuBar *MainMenu;
    void Quit(wxCommandEvent& event);
    void NewFile(wxCommandEvent& event);
    void OpenFile(wxCommandEvent& event);
    void SaveFile(wxCommandEvent& event);
    void SaveFileAs(wxCommandEvent& event);
    void CloseFile(wxCommandEvent& event);

    DECLARE_EVENT_TABLE()
  };

  enum
  {
    TEXT_Main = wxID_HIGHEST + 1, // declares an id which will be used to call our button
    MENU_New,
    MENU_Open,
    MENU_Close,
    MENU_Save,
    MENU_SaveAs,
    MENU_Quit
  };

  #endif
  #include <wx/wxprec.h>
  #ifndef WX_PRECOMP
  #include <wx/wx.h>
  #endif

  #include "base.h"

  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()


  IMPLEMENT_APP(MainApp) // Initializes the MainApp class and tells our program
  // to run it
  bool MainApp::OnInit()
  {
    MainFrame *MainWin = new MainFrame(wxT("Hello World!"), wxPoint(1,1),
    wxSize(300, 200)); // Create an instance of our frame, or window
    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, wxT("&New"),
      wxT("Create a new file"));
    FileMenu->Append(MENU_Open, wxT("&Open"),
      wxT("Open an existing file"));
    FileMenu->Append(MENU_Close, wxT("&Close"),
      wxT("Close the current document"));
    FileMenu->Append(MENU_Save, wxT("&Save"),
      wxT("Save the current document"));
    FileMenu->Append(MENU_SaveAs, wxT("Save &As"),
      wxT("Save the current document under a new file name"));
    FileMenu->Append(MENU_Quit, wxT("&Quit"),
      wxT("Quit the editor"));

    MainMenu->Append(FileMenu, wxT("File"));
    SetMenuBar(MainMenu);

    MainEditBox = new wxTextCtrl(this, TEXT_Main,
      wxT("Hi!"), wxDefaultPosition, wxDefaultSize,
      wxTE_MULTILINE | wxTE_RICH , wxDefaultValidator, wxTextCtrlNameStr);
      Maximize();
  }

  void MainFrame::NewFile(wxCommandEvent& WXUNUSED(event))
  {
  }

  void MainFrame::OpenFile(wxCommandEvent& WXUNUSED(event))
  {
    MainEditBox->LoadFile(wxT("base.h"));
  }

  void MainFrame::CloseFile(wxCommandEvent& WXUNUSED(event))
  {
    MainEditBox->Clear();
  }

  void MainFrame::SaveFile(wxCommandEvent& WXUNUSED(event))
  {
    MainEditBox->SaveFile(wxT("base.h"));
  }

  void MainFrame::SaveFileAs(wxCommandEvent& WXUNUSED(event))
  {
  }

  void MainFrame::Quit(wxCommandEvent& WXUNUSED(event))
  {
    Close(TRUE); // Tells the OS to quit running this process
  }