- wxWidgets工程配置
参考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
int main(){
wxPrintf(wxT("HelloWorld"));
}
执行结果:HelloWorld
对话框
#define WXUSINGDLL
#define __WXMSW__
#define _UNICODE
#include
int main(){
wxMessageBox(wxT("HelloWorld"));
}
执行结果:
在VisualStdio中,
WXUSINGDLL
、__WXMSW__
和_UNICODE
三个宏通常设置在项目属性页的预处理定义中。
窗口程序
通常,使用wxWidgets就是要实现比较复杂的GUI界面,这种界面通常称为窗口。下面展示非常简单的一个窗口程序。
#define WXUSINGDLL
#define __WXMSW__
#define _UNICODE
#include
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
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
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
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
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
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
#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
#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
#include
#include
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 MenuItem;
vector
其中,Connect(id,wxEVT_MENU,(wxObjectEventFunction)(wxEventFunction)static_cast
可以使用Bind()
,更加简单Bind(wxEVT_MENU,pFunc,this,id);
同样,以下三行代码
wxMenuItem* pItem = new wxMenuItem(this,id,label);
Connect(id,wxEVT_MENU,(wxObjectEventFunction)(wxEventFunction)static_cast(pFunc),NULL,this);
Append(pItem);
可以简写成
Append(id,label);
Bind(wxEVT_MENU,pFunc,this,id);
进一步优化
#define WXUSINGDLL
#define __WXMSW__
#define _UNICODE
#include
#include
#include
using namespace std;
#pragma comment(lib,"vcruntime.lib")
class MyMenuHandler;
typedef void (MyMenuHandler::*MenuFunc)(wxCommandEvent&);
typedef tuple 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