目录
- wxWidgets的头文件
- 事件
- main入口函数
- 状态栏
- 事件处理程序
wxWidgets的头文件
首先必须包含wxWidgets的头文件。
1、可以在一个文件一个文件的基础上完成(如wx/window.h)
2、使用一个全局包含(wx/wx.h),其中包括大多数常用的头文件(虽然不是所有的头文件,因为wxWidgets的头文件太多,无法拉入所有的头文件)。
对于支持预编译头文件的平台,如WX_PRECOMP所示,这个全局头文件wx/wx.h已经包含在wx/wxprec.h中,所以我们可以只需要包含wx/wxprec.h。
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
事件
实际上,每个应用都应该定义一个派生自wxApp的新类。通过重写wxApp的OnInit()虚方法,程序可以被初始化,例如创建一个新的主窗口。
现在程序如下了
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
// application class
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
主窗口是通过从wxFrame派生一个类并在构造函数中为其提供一个菜单和一个状态栏来创建的。此外,任何希望响应“事件”(如鼠标单击、菜单消息或按钮)的类都必须使用下面的宏声明一个事件表。
class MyFrame : public wxFrame
{
public:
MyFrame();
private:
void OnHello(wxCommandEvent& event);
void OnExit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
};
最后,对这类事件的响应是通过“事件处理程序”完成的,它只是函数(或功能词,如果使用c++ 11则包括lambdas),接受与被处理事件对应的类型的事件参数,例如wxCommandEvent用于来自简单控件的事件,如按钮、文本字段和菜单项。
对三个菜单项做出反应:自定义的“Hello”,以及“Exit”和“About”项(任何程序通常都应该实现后两者)。注意,这些处理程序不需要是虚拟的或公共的。
为了能够对菜单命令做出反应,它必须被赋予一个唯一的标识符,可以定义为const变量或enum元素。后者经常被使用,因为通常需要许多这样的常量:
enum
{
ID_Hello = 1
};
不需要为“About”和“Exit”定义标识符,因为wxWidgets已经预先定义了标准值,如wxID_ABOUT和wxID_EXIT。您应该尽可能地使用它们,因为它们可以由特定的平台以特殊的方式处理。
main入口函数
和所有程序一样,必须有一个“main”函数。在wxWidgets下,main是在wxIMPLEMENT_APP()宏中实现的,它创建指定类的应用程序实例并开始运行GUI事件循环。它可以简单地这样使用:
wxIMPLEMENT_APP(MyApp);
如上所述,wxApp::OnInit()在启动时被调用,应该用来初始化程序,可能会显示一个“启动画面”并创建主窗口(或几个)。默认情况下,框架是隐藏创建的,以允许在显示它们之前创建子窗口。因此,我们需要显式地显示它们。最后,从这个方法返回true,表示成功初始化:
bool MyApp::OnInit()
{
MyFrame *frame = new MyFrame();
frame->Show(true);
return true;
}
现在程序如下了
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
// application class
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
MyFrame *frame = new MyFrame();
frame->Show(true);
return true;
}
在主窗口(或稍后)的构造函数中,创建了一个包含菜单项的菜单,以及一个将显示在主窗口底部的状态栏。两者都必须绑定到具有各自调用的帧。
MyFrame::MyFrame()
: wxFrame(NULL, wxID_ANY, "Hello World")
{
wxMenu *menuFile = new wxMenu;
menuFile->Append(ID_Hello, "&Hello...\tCtrl-H",
"Help string shown in status bar for this menu item");
menuFile->AppendSeparator();
menuFile->Append(wxID_EXIT);
wxMenu *menuHelp = new wxMenu;
menuHelp->Append(wxID_ABOUT);
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append(menuFile, "&File");
menuBar->Append(menuHelp, "&Help");
SetMenuBar(menuBar);
CreateStatusBar();
SetStatusText("Welcome to wxWidgets!");
』
下面是2个菜单项
wxMenu *menuFile = new wxMenu;
menuFile->Append(ID_Hello, "&Hello...\tCtrl-H",
"Help string shown in status bar for this menu item");
menuFile->AppendSeparator();
menuFile->Append(wxID_EXIT);
wxMenu *menuHelp = new wxMenu;
menuHelp->Append(wxID_ABOUT);
SetMenuBar(menuBar);
状态栏
CreateStatusBar();
SetStatusText("Welcome to wxWidgets!");
注意,我们不需要为标准菜单项wxID_ABOUT和wxID_EXIT指定标签——它们将被赋予标准(甚至正确翻译)标签和标准加速器,以适应当前平台,使我们的程序行为更加本机。因此,您应该尽可能重用标准id(参见Stock Items)。
事件处理程序
我们还必须将我们的事件处理程序连接到我们想在其中处理的事件。为此,我们调用Bind()将所有带有指定ID的菜单事件(由wxEVT_MENU事件类型标识)发送到给定函数。传递给Bind()的参数为
1、事件类型,例如wxEVT_MENU, wxEVT_BUTTON, wxEVT_SIZE,或wxWidgets使用的许多其他事件之一。
2、一个指针,指向要调用的方法和要调用它的对象。在本例中,我们只需调用自己的函数,并将this指针传递给对象本身。我们可以调用另一个对象的方法,或者非成员函数的方法——实际上,任何可以用wxCommandEvent调用的对象都可以在这里使用。
3、一个可选标识符,允许我们只选择wxEVT_MENU类型的一些事件,即来自具有给定ID的菜单项的事件,而不是在提供的处理程序中处理所有事件。这主要用于菜单项,很少用于其他类型的事件。
Bind(wxEVT_MENU, &MyFrame::OnHello, this, ID_Hello);
Bind(wxEVT_MENU, &MyFrame::OnAbout, this, wxID_ABOUT);
Bind(wxEVT_MENU, &MyFrame::OnExit, this, wxID_EXIT);
下面是标准的事件处理程序实现。OnExit()通过调用Close()关闭主窗口。参数true表示其他窗口没有否决权,例如在询问“您真的想关闭吗?”之后。如果没有其他主窗口,应用程序将退出。
void MyFrame::OnExit(wxCommandEvent& event)
{
Close(true);
}
MyFrame::OnAbout()将显示一个包含一些文本的小窗口。在本例中是一个典型的“关于”窗口,其中包含有关程序的信息。
void MyFrame::OnAbout(wxCommandEvent& event)
{
wxMessageBox("This is a wxWidgets Hello World example",
"About Hello World", wxOK | wxICON_INFORMATION);
}
自定义菜单命令处理程序的实现可以执行程序需要执行的任何任务,在这种情况下,我们将简单地显示来自它的一条消息,以适合Hello World示例:
void MyFrame::OnHello(wxCommandEvent& event)
{
wxLogMessage("Hello world from wxWidgets!");
}
在c++ 11程序中,使用未命名的lambdas而不是函数作为事件处理程序是很方便的,特别是在处理来自控件的事件时,因为这允许将创建控件的代码和处理其事件的代码放在同一个位置。例如,在这里,我们可以用just替换wxID_EXIT处理程序
Bind(wxEVT_MENU, [=](wxCommandEvent&) { Close(true); }, wxID_EXIT);
全部程序如下
// wxWidgets "Hello World" Program
// For compilers that support precompilation, includes "wx/wx.h".
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
class MyFrame : public wxFrame
{
public:
MyFrame();
private:
void OnHello(wxCommandEvent& event);
void OnExit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
};
enum
{
ID_Hello = 1
};
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
MyFrame *frame = new MyFrame();
frame->Show(true);
return true;
}
MyFrame::MyFrame()
: wxFrame(NULL, wxID_ANY, "Hello World")
{
wxMenu *menuFile = new wxMenu;
menuFile->Append(ID_Hello, "&Hello...\tCtrl-H",
"Help string shown in status bar for this menu item");
menuFile->AppendSeparator();
menuFile->Append(wxID_EXIT);
wxMenu *menuHelp = new wxMenu;
menuHelp->Append(wxID_ABOUT);
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append(menuFile, "&File");
menuBar->Append(menuHelp, "&Help");
SetMenuBar( menuBar );
CreateStatusBar();
SetStatusText("Welcome to wxWidgets!");
Bind(wxEVT_MENU, &MyFrame::OnHello, this, ID_Hello);
Bind(wxEVT_MENU, &MyFrame::OnAbout, this, wxID_ABOUT);
Bind(wxEVT_MENU, &MyFrame::OnExit, this, wxID_EXIT);
}
void MyFrame::OnExit(wxCommandEvent& event)
{
Close(true);
}
void MyFrame::OnAbout(wxCommandEvent& event)
{
wxMessageBox("This is a wxWidgets Hello World example",
"About Hello World", wxOK | wxICON_INFORMATION);
}
void MyFrame::OnHello(wxCommandEvent& event)
{
wxLogMessage("Hello world from wxWidgets!");
}
运行结果如下