一、Hello World
//HelloWorldApp.h
#ifndef INCLUDED_HELLOWORLDAPP_H
#define INCLUDED_HELLOWORLDAPP_H
// The HelloWorldApp class. This class shows a window
// containing a statusbar with the text "Hello World"
class HelloWorldApp : public wxApp
{
public:
virtual bool OnInit();
};
DECLARE_APP(HelloWorldApp)
#endif // INCLUDED_HELLOWORLDAPP_H
//HelloWorldApp.cpp
// For compilers that don't support precompilation, include "wx/wx.h"
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
# include "wx/wx.h"
#endif
#include "HelloWorldApp.h"
IMPLEMENT_APP(HelloWorldApp)
// This is executed upon startup, like 'main()' in non-wxWidgets programs.
bool HelloWorldApp::OnInit()
{
wxFrame *frame = new wxFrame((wxFrame*) NULL, -1, _T("Hello wxWidgets World"));
frame->CreateStatusBar();
frame->SetStatusText(_T("Hello World"));
frame->Show(true);
SetTopWindow(frame);
return true;
}
对于主窗口,使用wxFrame类。 此类提供了一个窗口,用户可以更改其大小和位置。 它具有粗边框和标题栏。 另外,您可以为其提供菜单栏,状态栏和工具栏。
当编译器支持预编译头时,可以使用wxprec.h。 如果没有,则应包括wx.h,其中包括wxWindow的所有必需头文件。 您还可以为每个控件分别包含每个头文件。
宏DECLARE_APP和IMPLEMENT_APP为我们执行以下操作:
①当需要一个平台时,它将创建一个main()或WinMain()方法。
②它创建全局方法wxGetApp()。 您可以使用此函数来检索对一个应用程序对象的引用:HelloWorldApp &app = ::wxGetApp();
二、Using WxFrame
wxFrame类为我们提供了一个框架窗口。 框架窗口是可以更改其大小的窗口。 它具有粗边框,标题栏,并且可以选择包含菜单栏,工具栏或状态栏。 框架可以充当其他控件的容器,但另一个框架或对话框除外。 wxFrame是从wxWindow派生的。
在本章中,我们将创建一个小型文本编辑器。
1.Creating a frame
通常,我们会创建派生自wxFrame的类。 这样,可以向自己的框架类添加功能。
//TextFrame.h
#ifndef _TEXTFRAME_H
#define _TEXTFRAME_H
class TextFrame : public wxFrame
{
public:
/**
* Constructor. Creates a new TextFrame
*/
TextFrame(const wxChar *title, int xpos, int ypos, int width, int height);
/**
* Destructor
*/
~TextFrame();
};
#endif //_TEXTFRAME_H
从TextFrame构造函数调用wxFrame的构造函数。
//TextFrame.c
// For compilers that don't support precompilation, include "wx/wx.h";
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "TextFrame.h"
TextFrame::TextFrame(const wxChar *title, int xpos, int ypos, int width, int height)
: wxFrame((wxFrame *) NULL, -1, title, wxPoint(xpos, ypos), wxSize(width, height))
{
}
TextFrame::~TextFrame()
{
}
2.The Frame Constructor
//TextEditorApp.h
#ifndef TEXTEDITORAPP_H
#define TEXTEDITORAPP_H
class TextEditorApp : public wxApp
{
public:
/** Initialize the application */
virtual bool OnInit();
};
DECLARE_APP(TextEditorApp)
#endif // TEXTEDITORAPP_H
//TextEditorApp.c
// For compilers that don't support precompilation, include "wx/wx.h"
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "TextEditorApp.h"
#include "TextFrame.h"
IMPLEMENT_APP(TextEditorApp)
bool TextEditorApp::OnInit()
{
TextFrame *frame = new TextFrame(
wxT("Simple Text Editor"), 100, 100, 400, 300);
frame->Show(TRUE);
SetTopWindow(frame);
return true;
}
这之前都很简单,就是和Hello World那里一样。创建了一个空白窗体。
3.Adding A Control
step1-The TextFrame Definition
现在已经创建了框架窗口,需要添加一个用于处理文本的控件。 需要使用 wxTextCtrl类。 框架类已经包含此控件。此代码显示了TextFrame类的新定义。 唯一更改的是添加了wxTextCtrl类型的成员。 该成员在构造函数中初始化。
#ifndef _TEXTFRAME_H
#define _TEXTFRAME_H
class TextFrame : public wxFrame
{
public:
/**
* Constructor. Creates a new TextFrame
*/
TextFrame(const wxString& title, int xpos, int ypos, int width, int height);
/**
* Destructor
*/
~TextFrame();
private:
wxTextCtrl *m_pTextCtrl;
};
#endif // _TEXTFRAME_H
Step 2 - The TextFrame Implementation
以下代码显示了TextFrame类的新构造函数。 wxTextCtrl成员的父级是TextFrame,因此我们将其传递给’this’指针。 文本’Type some text…'将显示为默认文本。 请注意,wxTextCtrl的构造函数看起来与wxFrame的构造函数相似。 从wxWindow派生的每个类都遵循相同的构造函数模式。
同样,没有用于删除wxTextCtrl指针的代码。 不必要(实际上是不允许的),因为TextFrame是父级,在销毁它时会自动删除其所有子级。
wxTE_MULTILINE是文本控件的特定窗口样式。 此样式表示wxTextCtrl允许多行。
// For compilers that supports precompilation , include "wx/wx.h"
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
# include "wx/wx.h"
#endif
#include "TextFrame.h"
TextFrame::TextFrame(const wxString& title, int xpos, int ypos, int width, int height)
: wxFrame((wxFrame *) NULL, -1, title, wxPoint(xpos, ypos), wxSize(width, height))
{
m_pTextCtrl = new wxTextCtrl(this, -1, wxT("Type some text..."),
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);
// More will be added here later
Layout();
}
TextFrame::~TextFrame()
{
}
运行此项目时,将有一个应用程序,该应用程序显示一个窗口,可以在其中输入一些文本。 尝试剪切,粘贴。
之所以调用Layout()是因为Windows并不总是在合适的时间发送size-event,以使wxWidgets能够捕获OnSize处理程序(在此它本身调用Layout())。
4.Adding A Menubar
菜单在任何应用程序中都起着重要作用。 它们作为一个位置,大多数用户知道他们可以找到对应用程序中任何功能或模式的访问。 wxWidgets提供了三个主要类来管理应用程序中的菜单:wxMenuBar,wxMenu和wxMenuItem。
每个菜单项都需要一个唯一的ID。 #define不用于定义常量(例如#define MENU_FILE_MENU 1),因为这不能保证唯一的ID。 忽略某些值很容易,而且当你必须插入新ID时也很难维护。 如果未使用枚举定义菜单ID,则第二种流行的ID定义方法是使用wxNewId()函数返回未使用的ID。
//TextFrame.h
#ifndef _TEXTFRAME_H
#define _TEXTFRAME_H
class TextFrame : public wxFrame
{
public:
/** Constructor. Creates a new TextFrame */
TextFrame(const wxChar *title, int xpos, int ypos, int width, int height);
private:
wxTextCtrl *m_pTextCtrl;
wxMenuBar *m_pMenuBar;
wxMenu *m_pFileMenu;
wxMenu *m_pHelpMenu;
};
#endif _TEXTFRAME_H
菜单栏在TextFrame的构造函数中创建,如下所示。 使用wxMenu的Append方法将菜单项添加到菜单。 创建菜单后,可以使用wxMenuBar的Append将其附加到菜单栏。
//TextFrame.c
// For compilers that supports precompilation , includes "wx/wx.h"
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "TextFrame.h"
TextFrame::TextFrame(const wxChar *title, int xpos, int ypos, int width, int height)
: wxFrame((wxFrame *) NULL, -1, title, wxPoint(xpos, ypos), wxSize(width, height))
{
m_pTextCtrl = new wxTextCtrl(this, -1, _T("Type some text..."),
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);
m_pMenuBar = new wxMenuBar();
// File Menu
m_pFileMenu = new wxMenu();
m_pFileMenu->Append(wxID_OPEN, _T("&Open"));
m_pFileMenu->Append(wxID_SAVE, _T("&Save"));
m_pFileMenu->AppendSeparator();//添加一个分割符
m_pFileMenu->Append(wxID_EXIT, _T("&Quit"));
m_pMenuBar->Append(m_pFileMenu, _T("&File"));
// About menu
m_pHelpMenu = new wxMenu();
m_pHelpMenu->Append(wxID_ABOUT, _T("&About"));
m_pMenuBar->Append(m_pHelpMenu, _T("&Help"));
SetMenuBar(m_pMenuBar);
}
实际上就是wxMenuBar下添加了两个wxMenu,一个是File,一个是Help。其中File下有Open,Save和Quit三个子菜单,Help下有About一个子菜单。
5.Adding A Statusbar
将状态栏添加到框架甚至更加容易。 调用wxFrame方法CreateStatusBar,并且框架具有状态栏。 作为参数,将传递一个数字,该数字用于在状态栏中创建单独的字段。 使用SetStatusText可以更改字段的文本。
//TextFrame.c
CreateStatusBar(3);
SetStatusText(wxT("Ready"), 0);
这将创建一个包含3个字段的状态栏。 第一个字段将包含文本“Ready”。
状态栏也可用于显示所选菜单的描述。 下面的代码显示了如何更改“添加菜单栏”中的代码。 选择菜单后,相关描述将显示在状态栏的第一个字段中。
TextFrame.c
// File menu
m_pFileMenu = new wxMenu();
m_pFileMenu->Append(wxID_OPEN, _T("&Open"), _T("Opens an existing file"));
m_pFileMenu->Append(wxID_SAVE, _T("&Save"), _T("Save the content"));
m_pFileMenu->AppendSeparator();
m_pFileMenu->Append(wxID_EXIT, _T("&Quit"), _T("Quit the application"));
m_pMenuBar->Append(m_pFileMenu, _T("&File"));
// About menu
m_pHelpMenu = new wxMenu();
m_pHelpMenu->Append(wxID_ABOUT, _T("&About"), _T("Shows information about the application"));
m_pMenuBar->Append(m_pHelpMenu, _T("&Info"));
6.Processing Menu Events
既然框架上有菜单,那么当用户选择菜单时,就需要一种实现操作的方法。 菜单的每个选择都会生成一个事件。
关于事件部分后面再说。提供添加事件后的最终版本
//TextFrame.h
#ifndef _TEXTFRAME_H
#define _TEXTFRAME_H
class TextFrame : public wxFrame
{
public:
/** Constructor. Creates a new TextFrame */
TextFrame(const wxChar* title, int xpos, int ypos, int width, int height);
/** Processes menu File|Open */
void OnMenuFileOpen(wxCommandEvent& event);
/** Processes menu File|Save */
void OnMenuFileSave(wxCommandEvent& event);
/** Processes menu File|Quit */
void OnMenuFileQuit(wxCommandEvent& event);
/** Processes menu About|Info */
void OnMenuHelpAbout(wxCommandEvent& event);
protected:
DECLARE_EVENT_TABLE()
private:
wxTextCtrl* m_pTextCtrl;
wxMenuBar* m_pMenuBar;
wxMenu* m_pFileMenu;
wxMenu* m_pHelpMenu;
};
#endif _TEXTFRAME_H
//TextFrame.c
// For compilers that supports precompilation , includes "wx/wx.h"
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "TextFrame.h"
TextFrame::TextFrame(const wxChar* title, int xpos, int ypos, int width, int height)
: wxFrame((wxFrame*)NULL, -1, title, wxPoint(xpos, ypos), wxSize(width, height))
{
m_pTextCtrl = new wxTextCtrl(this, -1, _T("Type some text..."),
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);
CreateStatusBar(3);
SetStatusText(_T("Ready"), 0);
m_pMenuBar = new wxMenuBar();
// File menu
m_pFileMenu = new wxMenu();
m_pFileMenu->Append(wxID_OPEN, _T("&Open"), _T("Opens an existing file"));
m_pFileMenu->Append(wxID_SAVE, _T("&Save"), _T("Save the content"));
m_pFileMenu->AppendSeparator();
m_pFileMenu->Append(wxID_EXIT, _T("&Quit"), _T("Quit the application"));
m_pMenuBar->Append(m_pFileMenu, _T("&File"));
// About menu
m_pHelpMenu = new wxMenu();
m_pHelpMenu->Append(wxID_ABOUT, _T("&About"), _T("Shows information about the application"));
m_pMenuBar->Append(m_pHelpMenu, _T("&Info"));
SetMenuBar(m_pMenuBar);
Layout();
}
// If you're doing an application by inheriting from wxApp
// be sure to change wxFrame to wxApp (or whatever component
// you've inherited your class from).
BEGIN_EVENT_TABLE(TextFrame, wxFrame)
EVT_MENU(wxID_OPEN, TextFrame::OnMenuFileOpen)
EVT_MENU(wxID_SAVE, TextFrame::OnMenuFileSave)
EVT_MENU(wxID_EXIT, TextFrame::OnMenuFileQuit)
EVT_MENU(wxID_ABOUT, TextFrame::OnMenuHelpAbout)
END_EVENT_TABLE()
void TextFrame::OnMenuFileOpen(wxCommandEvent& event)
{
wxFileDialog* OpenDialog = new wxFileDialog(this, _T("Choose a file"), _(""), _(""), _("*.*"), wxFD_OPEN);
if (OpenDialog->ShowModal() == wxID_OK)
{
m_pTextCtrl->LoadFile(OpenDialog->GetPath()) ?
SetStatusText(_T("Loaded")) :
SetStatusText(_T("Load Failed"));
}
OpenDialog->Close(); // Or OpenDialog->Destroy() ?
}
void TextFrame::OnMenuFileSave(wxCommandEvent& event)
{
wxFileDialog* SaveDialog = new wxFileDialog(this, _T("Choose a file"), _(""), _(""), _("*.*"), wxFD_SAVE);
if (SaveDialog->ShowModal() == wxID_OK)
{
m_pTextCtrl->SaveFile(SaveDialog->GetPath()) ?
SetStatusText(_T("Saved")) :
SetStatusText(_T("Save Failed"));
}
SaveDialog->Close();
}
void TextFrame::OnMenuFileQuit(wxCommandEvent& event)
{
Close(false);
}
void TextFrame::OnMenuHelpAbout(wxCommandEvent& event)
{
wxLogMessage(_T("The Simple Text Editor"));
}