参考wxWidgets官方Hello World in wxWidgets编写一个简单的wxWidgets入门。
从小的成功积累到大的成功
编译&执行环境
OS | CPU | IDE |
---|---|---|
Win10 | x64 | VS2015+clang+VSCode |
Hello World
程序从界面来说主要分为两大类:CLI(控制台)和GUI(图形界面)。
控制台是一个简单的命令行程序,没有界面,执行没有界面,便于与其它命令组合,非常适合自动化批量执行。GUI则是一个包含界面的程序,易于非程序员操作和使用。下面使用wxWidgets各实现HelloWorld。
控制台/终端
#define WXUSINGDLL
#define __WXMSW__
#define _UNICODE
#include <wx/wx.h>
int main(){
wxPrintf(wxT("HelloWorld"));
}
执行结果:HelloWorld
对话框
#define WXUSINGDLL
#define __WXMSW__
#define _UNICODE
#include <wx/wx.h>
int main(){
wxMessageBox(wxT("HelloWorld"));
}
执行结果:在VisualStdio中,
WXUSINGDLL
、__WXMSW__
和_UNICODE
三个宏通常设置在项目属性页的预处理定义中。
窗口程序
通常,使用wxWidgets就是要实现比较复杂的GUI界面,这种界面通常称为窗口。下面展示非常简单的一个窗口程序。
#define WXUSINGDLL
#define __WXMSW__
#define _UNICODE
#include <wx/wx.h>
class MyFrame: public wxFrame {
public:
MyFrame(): wxFrame(NULL, wxID_ANY, "Hello World") {}
};
class MyApp: public wxApp {
public:
virtual bool OnInit(){
MyFrame *pframe = new MyFrame();
pframe->Show( true );
return true;
}
};
wxIMPLEMENT_APP(MyApp);
执行结果:特点:
- 没有
main()
函数,实际上是包含在wxWidgets框架中看不到。 - 一个应用程序类
App
,一个框架类Frame
。 -
Frame
在App
的OnInit()
函数中实例化。
注意:这里
Frame
没有销毁,可能会内存泄露(通常这么处理也不会有太大问题,因为窗口关闭时,OS会收回所有资源)。
- 解决方法一:
把Frame
指针作为App
的成员变量,在App
析构函数中释放Frame
动态内存。
#define WXUSINGDLL
#define __WXMSW__
#define _UNICODE
#include <wx/wx.h>
class MyFrame: public wxFrame {
public:
MyFrame(): wxFrame(NULL, wxID_ANY, "Hello World") {}
};
class MyApp: public wxApp {
public:
~MyApp(){
wxDELETE(pframe);
wxASSERT(not pframe);
}
virtual bool OnInit(){
pframe = new MyFrame();
pframe->Show( true );
return true;
}
private:
MyFrame* pframe{nullptr};
};
wxIMPLEMENT_APP(MyApp);
- 解决方法二:
把Frame
对象作为App
的成员变量,Frame
随App
生存周期自动的创建和消亡。
#define WXUSINGDLL
#define __WXMSW__
#define _UNICODE
#include <wx/wx.h>
class MyFrame: public wxFrame {
public:
MyFrame(): wxFrame(NULL, wxID_ANY, "Hello World") {}
};
class MyApp: public wxApp {
public:
virtual bool OnInit(){
frame.Show(true);
return true;
}
private:
MyFrame frame;
};
wxIMPLEMENT_APP(MyApp);
添加状态栏
#define WXUSINGDLL
#define __WXMSW__
#define _UNICODE
#include <wx/wx.h>
class MyFrame: public wxFrame {
public:
MyFrame(): wxFrame(NULL, wxID_ANY, "Hello World") {
CreateStatusBar();
SetStatusText( "Welcome to wxWidgets!" );
}
};
class MyApp: public wxApp {
public:
virtual bool OnInit(){
frame.Show(true);
return true;
}
private:
MyFrame frame;
};
wxIMPLEMENT_APP(MyApp);
执行结果:添加菜单
#define WXUSINGDLL
#define __WXMSW__
#define _UNICODE
#include <wx/wx.h>
enum
{
ID_Hello = 1
};
class MyFrame: public wxFrame {
public:
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!" );
}
};
class MyApp: public wxApp {
public:
virtual bool OnInit(){
frame.Show(true);
return true;
}
private:
MyFrame frame;
};
wxIMPLEMENT_APP(MyApp);
执行结果:菜单添加事件
#define WXUSINGDLL
#define __WXMSW__
#define _UNICODE
#pragma comment(lib,"vcruntime.lib")
#include <wx/wx.h>
enum
{
ID_Hello = 1
};
class MyFrame: public wxFrame {
public:
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, [=](wxCommandEvent&){wxLogMessage("Hello world from wxWidgets!");}, ID_Hello);
Bind(wxEVT_MENU, [=](wxCommandEvent&){
wxMessageBox( "This is a wxWidgets' Hello world sample","About Hello World", wxOK | wxICON_INFORMATION );
}, wxID_ABOUT);
Bind(wxEVT_MENU, [=](wxCommandEvent&){ Close(true);}, wxID_EXIT);
}
};
class MyApp: public wxApp {
public:
virtual bool OnInit(){
frame.Show(true);
return true;
}
private:
MyFrame frame;
};
wxIMPLEMENT_APP(MyApp);
注意:这里的菜单栏和菜单项不要手动delete,Frame销毁时负责销毁。
右键菜单
#define WXUSINGDLL
#define __WXMSW__
#define _UNICODE
#include <wx/wx.h>
#pragma comment(lib,"vcruntime.lib")
class MyFrame: public wxFrame {
public:
MyFrame(): wxFrame(NULL, wxID_ANY, "Hello World") {}
void OnPopupMenu(wxMouseEvent& event){
wxMenu menu;
menu.Append(wxID_ANY,wxT("Test1"));
menu.Append(wxID_ANY,wxT("Test2"));
this->PopupMenu(&menu);
}
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_RIGHT_DOWN(MyFrame::OnPopupMenu)
END_EVENT_TABLE()
class MyApp: public wxApp {
public:
virtual bool OnInit(){
MyFrame* pFrame = new MyFrame;
pFrame->Show( true );
return true;
}
};
wxIMPLEMENT_APP(MyApp);
#define WXUSINGDLL
#define __WXMSW__
#define _UNICODE
#include <wx/wx.h>
#pragma comment(lib,"vcruntime.lib")
class MyPopupMenu: public wxMenu {
public:
MyPopupMenu():wxMenu(){
Append(wxID_ANY,wxT("Test1"));
Append(wxID_ANY,wxT("Test2"));
}
};
class MyFrame: public wxFrame {
public:
MyFrame(): wxFrame(NULL, wxID_ANY, "Hello World") {}
void OnPopupMenu(wxMouseEvent& event){
MyMenu menu;
PopupMenu(&menu);
}
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_RIGHT_DOWN(MyFrame::OnPopupMenu)
END_EVENT_TABLE()
class MyApp: public wxApp {
public:
virtual bool OnInit(){
MyFrame* pFrame = new MyFrame;
pFrame->Show( true );
return true;
}
};
wxIMPLEMENT_APP(MyApp);
动态菜单
#define WXUSINGDLL
#define __WXMSW__
#define _UNICODE
#include <wx/wx.h>
#include <vector>
#include <tuple>
using namespace std;
#pragma comment(lib,"vcruntime.lib")
class MyPopupMenu: public wxMenu {
enum{
ID_CREATE_PROJECT,
ID_CREATE_GROUP,
ID_CREATE_MARKPOINT,
ID_CREATE_FOV_SINGLE,
ID_CREATE_FOV_MAPPED,
ID_COPY_PASTE,
ID_DELETE,
ID_SET_REPORT,
ID_PROPERTY,
ID_TEST
};
public:
MyPopupMenu():wxMenu(){
typedef void (MyPopupMenu::*MenuFunc)(wxCommandEvent&);
typedef tuple<int,wxString,MenuFunc> MenuItem;
vector<MenuItem> items = {
make_tuple(ID_CREATE_PROJECT,wxT("创建工程"),&MyPopupMenu::OnCreateProject),
make_tuple(ID_CREATE_GROUP, wxT("创建Group"),&MyPopupMenu::OnCreateGroup),
make_tuple(ID_CREATE_MARKPOINT,wxT("创建MarkPoint"),&MyPopupMenu::OnCreateMarkPoint),
make_tuple(ID_CREATE_FOV_SINGLE,wxT("创建FovSingle"),&MyPopupMenu::OnCreateFovSingle),
make_tuple(ID_CREATE_FOV_MAPPED,wxT("创建FovMapped"),&MyPopupMenu::OnCreateFovMapped),
};
for(auto& item : items){
MenuFunc pFunc;
wxString label;
int id;
tie(id,label,pFunc) = item;
wxMenuItem* pItem = new wxMenuItem(this,id,label);
Connect(id,wxEVT_MENU,(wxObjectEventFunction)(wxEventFunction)static_cast<wxCommandEventFunction>(pFunc),NULL,this);
Append(pItem);
}
}
void OnCreateProject(wxCommandEvent& event);
void OnCreateGroup(wxCommandEvent& event);
void OnCreateMarkPoint(wxCommandEvent& event);
void OnCreateFovSingle(wxCommandEvent& event);
void OnCreateFovMapped(wxCommandEvent& event);
};
void MyPopupMenu::OnCreateProject(wxCommandEvent& event){
wxMessageBox(wxT("Context"), wxT("创建工程"),wxOK | wxICON_INFORMATION,nullptr);
}
void MyPopupMenu::OnCreateGroup(wxCommandEvent& event){
wxMessageBox(wxT("Context"), wxT("创建Group"),wxOK | wxICON_INFORMATION,nullptr);
}
void MyPopupMenu::OnCreateMarkPoint(wxCommandEvent& event){
wxMessageBox(wxT("Context"), wxT("创建工程"),wxOK | wxICON_INFORMATION,nullptr);
}
void MyPopupMenu::OnCreateFovSingle(wxCommandEvent& event){
wxMessageBox(wxT("Context"), wxT("创建工程"),wxOK | wxICON_INFORMATION,nullptr);
}
void MyPopupMenu::OnCreateFovMapped(wxCommandEvent& event){
wxMessageBox(wxT("Context"), wxT("创建工程"),wxOK | wxICON_INFORMATION,nullptr);
}
class MyFrame: public wxFrame {
public:
MyFrame(): wxFrame(NULL, wxID_ANY, "Hello World") {}
void OnPopupMenu(wxMouseEvent& event){
MyPopupMenu menu;
PopupMenu(&menu);
}
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_RIGHT_DOWN(MyFrame::OnPopupMenu)
END_EVENT_TABLE()
class MyApp: public wxApp {
public:
virtual bool OnInit(){
oFrame.Show( true );
return true;
}
private:
MyFrame oFrame;
};
wxIMPLEMENT_APP(MyApp);
其中,Connect(id,wxEVT_MENU,(wxObjectEventFunction)(wxEventFunction)static_cast<wxCommandEventFunction>(pFunc),NULL,this);
可以使用Bind()
,更加简单Bind(wxEVT_MENU,pFunc,this,id);
同样,以下三行代码
wxMenuItem* pItem = new wxMenuItem(this,id,label);
Connect(id,wxEVT_MENU,(wxObjectEventFunction)(wxEventFunction)static_cast<wxCommandEventFunction>(pFunc),NULL,this);
Append(pItem);
可以简写成
Append(id,label);
Bind(wxEVT_MENU,pFunc,this,id);
进一步优化
#define WXUSINGDLL
#define __WXMSW__
#define _UNICODE
#include <wx/wx.h>
#include <vector>
#include <tuple>
using namespace std;
#pragma comment(lib,"vcruntime.lib")
class MyMenuHandler;
typedef void (MyMenuHandler::*MenuFunc)(wxCommandEvent&);
typedef tuple<int,wxString,MenuFunc> MenuItem;
class MyMenuHandler{
enum{
ID_CREATE_PROJECT,
ID_CREATE_GROUP,
ID_CREATE_MARKPOINT,
ID_CREATE_FOV_SINGLE,
ID_CREATE_FOV_MAPPED,
ID_COPY_PASTE,
ID_DELETE,
ID_SET_REPORT,
ID_PROPERTY,
ID_TEST
};
private:
vector<MenuItem> items;
void OnCreateProject(wxCommandEvent& event){
wxMessageBox(wxT("Context"), wxT("创建工程"),wxOK | wxICON_INFORMATION,nullptr);
}
void OnCreateGroup(wxCommandEvent& event){
wxMessageBox(wxT("Context"), wxT("创建Group"),wxOK | wxICON_INFORMATION,nullptr);
}
void OnCreateMarkPoint(wxCommandEvent& event){
wxMessageBox(wxT("Context"), wxT("创建工程"),wxOK | wxICON_INFORMATION,nullptr);
}
void OnCreateFovSingle(wxCommandEvent& event){
wxMessageBox(wxT("Context"), wxT("创建工程"),wxOK | wxICON_INFORMATION,nullptr);
}
void OnCreateFovMapped(wxCommandEvent& event){
wxMessageBox(wxT("Context"), wxT("创建工程"),wxOK | wxICON_INFORMATION,nullptr);
}
public:
MyMenuHandler():items({
make_tuple(ID_CREATE_PROJECT,wxT("创建工程"),&MyMenuHandler::OnCreateProject),
make_tuple(ID_CREATE_GROUP, wxT("创建Group"),&MyMenuHandler::OnCreateGroup),
make_tuple(ID_CREATE_MARKPOINT,wxT("创建MarkPoint"),&MyMenuHandler::OnCreateMarkPoint),
make_tuple(ID_CREATE_FOV_SINGLE,wxT("创建FovSingle"),&MyMenuHandler::OnCreateFovSingle),
make_tuple(ID_CREATE_FOV_MAPPED,wxT("创建FovMapped"),&MyMenuHandler::OnCreateFovMapped)
}){}
vector<MenuItem>& GetHandlers(){
return items;
}
};
class MyPopupMenu: public wxMenu {
public:
enum{
MENU_ID,MENU_LABEL,MENU_HAMDLE
};
MyPopupMenu(wxWindow* parent,MyMenuHandler&& handler):MyPopupMenu(parent,handler){}
MyPopupMenu(wxWindow* parent,MyMenuHandler& handler):wxMenu(){
for(auto& item : handler.GetHandlers()){
Append(get<MENU_ID>(item),get<MENU_LABEL>(item));
Bind(wxEVT_MENU,get<MENU_HAMDLE>(item),&handler,get<MENU_ID>(item));
}
parent->PopupMenu(this);
}
};
class MyFrame: public wxFrame {
public:
MyFrame(): wxFrame(NULL, wxID_ANY, "Hello World") {}
void OnPopupMenu(wxMouseEvent& event){
MyPopupMenu menu(this,MyMenuHandler{});
}
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_RIGHT_DOWN(MyFrame::OnPopupMenu)
END_EVENT_TABLE()
class MyApp: public wxApp {
public:
virtual bool OnInit(){
oFrame.Show( true );
return true;
}
private:
MyFrame oFrame;
};
wxIMPLEMENT_APP(MyApp);