zwx_helper
阅读原文时间:2023年07月09日阅读:2

通过重载c++operator,实现一种轻松的wxWidgets界面编程风格,如html编写页面一样直观容易。

举一例,一个界面页有四块区,如果是开发html的话,是从头到脚一气书写

我的目标是,让c++开发的代码书写也一气呵成

Frame* frame = new Frame;
layout::begin(new layout)
(layout::begin(new layout)
(new button) [ onclick = [] (event&) {} ]
(layout::end)
)
(layout::begin(new layout)
(new button) [ onclick = [] (event&) {} ]
(layout::end)
)
(layout::begin(new layout)
(new button) [ onclick = [] (event&) {} ]
(layout::end)
)
(layout::begin(new layout)
(new button) [ onclick = [] (event&) {} ]
(layout::end)
)
(layout::end, [=] (layout& layout) {
frame->SetLayout(layout);
});

菜单布局编写直观自然,处理器函数绑定同时到位

Frame* frame = new Frame;
menu::begin(new MenuBar)
("File",
menu::begin(new Menu)
            (ID_OPEN, "open", [=] (event&) { })
(ID_NEW, "new", [=] (event&) { })
(menu::end)
)
("About",
menu::begin(new Menu)
             (ID_HELP, "help", [=] (event&) { })
(menu::end)
)
(menu::end, [=] (MenuBar* mb) {
frame->SetMenuBar(mb);
});

理想总是美好的,现在回到现实中的界面开发,让人眼痛的c++代码,

1 必须在多处代码操作,步骤烦多,分散在多处代码。

2 布局编写不符合人的思维-将整体拆分再拆分,而是从枝节末端创建一层一层往上添加挂钩。

MFC,WTL与wxWidgets的开发步骤类似,这里只关注wxWidgets,

1 在头文件中,自定义窗口类声明事件(窗口消息)分派函数;

2 在源文件中,添加事件(窗口消息)分派函数的实现宏;

3 添加一个事件(窗口消息)处理器函数,

3-1 在头文件中,声明为自定义窗口类的成员函数

3-2 在源文件中,实现该函数

3-3 在源文件中,在那个TABLE宏里添加事件id,处理器函数

4 在某个窗口容器的初始化回调中,创建事件id对应的子窗口/控件,设置相关的id

5 过了一段时间后,维护某个控件的处理器函数

5-1 在布局代码中找到这个控件,看到它相关的id

5-2 在源代码找到分派事件的窗口类,在它的TABLE宏里众多条目中找出对应项

5-3 最后才定位到目标处理器函数

做一样事情,却要在多处代码文件中跳转切换,只要漏了一步又会浪费时间调试一翻,实在烦人烦心。

// MyFrame.h

enum
{
ID_SOME
};

class MyFrame : public wxFrame
{
public:
void hanlde_some_event(wxEvent&);
private:
wxDECLARE_EVENT_TABLE()
}

// MyFrame.cpp

wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_XXXX(ID_SOME, &MyFrame::handle_some_event)
wxEND_EVENT_TABLE()

void MyFrame::handle_some_event(wxEvent&)
{
// todo
}

MyFrame::MyFrame()
{
// ….
this->Add(new wxSomeWindow(this, ID_SOME, …);
// ….
}

下面是用zwx_helper重写官方layout sample布局的代码的对比

先是官方代码

layout.h https://github.com/wxWidgets/wxWidgets/blob/master/samples/layout/layout.h

layout.cpp https://github.com/wxWidgets/wxWidgets/blob/master/samples/layout/layout.cpp

// ----------------------------------------------------------------------------
// MyFrame
// ----------------------------------------------------------------------------

wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(LAYOUT_ABOUT, MyFrame::OnAbout)
EVT_MENU(LAYOUT_QUIT, MyFrame::OnQuit)

EVT_MENU(LAYOUT_TEST_PROPORTIONS, MyFrame::TestProportions)
EVT_MENU(LAYOUT_TEST_SIZER, MyFrame::TestFlexSizers)
EVT_MENU(LAYOUT_TEST_NB_SIZER, MyFrame::TestNotebookSizers)
EVT_MENU(LAYOUT_TEST_GB_SIZER, MyFrame::TestGridBagSizer)
EVT_MENU(LAYOUT_TEST_SET_MINIMAL, MyFrame::TestSetMinimal)
EVT_MENU(LAYOUT_TEST_NESTED, MyFrame::TestNested)
EVT_MENU(LAYOUT_TEST_WRAP, MyFrame::TestWrap)
wxEND_EVENT_TABLE()

// Define my frame constructor
MyFrame::MyFrame()
: wxFrame(NULL, wxID_ANY, "wxWidgets Layout Demo")
{
SetIcon(wxICON(sample));

// Make a menubar  
wxMenu \*file\_menu = new wxMenu;

file\_menu->Append(LAYOUT\_TEST\_PROPORTIONS, "&Proportions demo...\\tF1");  
file\_menu->Append(LAYOUT\_TEST\_SIZER, "Test wx&FlexSizer...\\tF2");  
file\_menu->Append(LAYOUT\_TEST\_NB\_SIZER, "Test &notebook sizers...\\tF3");  
file\_menu->Append(LAYOUT\_TEST\_GB\_SIZER, "Test &gridbag sizer...\\tF4");  
file\_menu->Append(LAYOUT\_TEST\_SET\_MINIMAL, "Test Set&ItemMinSize...\\tF5");  
file\_menu->Append(LAYOUT\_TEST\_NESTED, "Test nested sizer in a wxPanel...\\tF6");  
file\_menu->Append(LAYOUT\_TEST\_WRAP, "Test wrap sizers...\\tF7");

file\_menu->AppendSeparator();  
file\_menu->Append(LAYOUT\_QUIT, "E&xit", "Quit program");

wxMenu \*help\_menu = new wxMenu;  
help\_menu->Append(LAYOUT\_ABOUT, "&About", "About layout demo...");

wxMenuBar \*menu\_bar = new wxMenuBar;

menu\_bar->Append(file\_menu, "&File");  
menu\_bar->Append(help\_menu, "&Help");

// Associate the menu bar with the frame  
SetMenuBar(menu\_bar);

#if wxUSE_STATUSBAR
CreateStatusBar();
SetStatusText("wxWidgets layout demo");
#endif // wxUSE_STATUSBAR

wxPanel\* p = new wxPanel(this, wxID\_ANY);

// we want to get a dialog that is stretchable because it  
// has a text ctrl in the middle. at the bottom, we have  
// two buttons which.

wxBoxSizer \*topsizer = new wxBoxSizer( wxVERTICAL );

// 1) top: create wxStaticText with minimum size equal to its default size  
topsizer->Add(  
    new wxStaticText( p, wxID\_ANY, "An explanation (wxALIGN\_RIGHT)." ),  
    wxSizerFlags().Align(wxALIGN\_RIGHT).Border(wxALL & ~wxBOTTOM, ));  
topsizer->Add(  
    new wxStaticText( p, wxID\_ANY, "An explanation (wxALIGN\_LEFT)." ),  
    wxSizerFlags().Align(wxALIGN\_LEFT).Border(wxALL & ~wxBOTTOM, ));  
topsizer->Add(  
    new wxStaticText( p, wxID\_ANY, "An explanation (wxALIGN\_CENTRE\_HORIZONTAL)." ),  
    wxSizerFlags().Align(wxALIGN\_CENTRE\_HORIZONTAL).Border(wxALL & ~wxBOTTOM, ));

// 2) top: create wxTextCtrl with minimum size (100x60)  
topsizer->Add(  
    new wxTextCtrl( p, wxID\_ANY, "My text (wxEXPAND).", wxDefaultPosition, wxSize(,), wxTE\_MULTILINE),  
    wxSizerFlags().Expand().Border(wxALL, ));

// 2.5) Gratuitous test of wxStaticBoxSizers  
wxBoxSizer \*statsizer = new wxStaticBoxSizer(  
    new wxStaticBox(p, wxID\_ANY, "A wxStaticBoxSizer"), wxVERTICAL );  
statsizer->Add(  
    new wxStaticText(p, wxID\_ANY, "And some TEXT inside it"),  
    wxSizerFlags().Border(wxALL, ));  
topsizer->Add(  
    statsizer,  
    wxSizerFlags().Expand().Border(wxALL, ));

// 2.7) And a test of wxGridSizer  
wxGridSizer \*gridsizer = new wxGridSizer(, , );  
gridsizer->Add(new wxStaticText(p, wxID\_ANY, "Label"),  
            wxSizerFlags().Align(wxALIGN\_RIGHT | wxALIGN\_CENTER\_VERTICAL));  
gridsizer->Add(new wxTextCtrl(p, wxID\_ANY, "Grid sizer demo"),  
            wxSizerFlags().Align(wxGROW | wxALIGN\_CENTER\_VERTICAL));  
gridsizer->Add(new wxStaticText(p, wxID\_ANY, "Another label"),  
            wxSizerFlags().Align(wxALIGN\_RIGHT | wxALIGN\_CENTER\_VERTICAL));  
gridsizer->Add(new wxTextCtrl(p, wxID\_ANY, "More text"),  
            wxSizerFlags().Align(wxGROW | wxALIGN\_CENTER\_VERTICAL));  
gridsizer->Add(new wxStaticText(p, wxID\_ANY, "Final label"),  
            wxSizerFlags().Align(wxALIGN\_RIGHT | wxALIGN\_CENTER\_VERTICAL));  
gridsizer->Add(new wxTextCtrl(p, wxID\_ANY, "And yet more text"),  
            wxSizerFlags().Align(wxGROW | wxALIGN\_CENTER\_VERTICAL));  
topsizer->Add(  
    gridsizer,  
    wxSizerFlags().Proportion().Expand().Border(wxALL, ));

#if wxUSE_STATLINE
// 3) middle: create wxStaticLine with minimum size (3x3)
topsizer->Add(
new wxStaticLine( p, wxID_ANY, wxDefaultPosition, wxSize(,), wxHORIZONTAL),
wxSizerFlags().Expand());
#endif // wxUSE_STATLINE

// 4) bottom: create two centred wxButtons  
wxBoxSizer \*button\_box = new wxBoxSizer( wxHORIZONTAL );  
button\_box->Add(  
    new wxButton( p, wxID\_ANY, "Two buttons in a box" ),  
    wxSizerFlags().Border(wxALL, ));  
button\_box->Add(  
    new wxButton( p, wxID\_ANY, "(wxCENTER)" ),  
    wxSizerFlags().Border(wxALL, ));

topsizer->Add(button\_box, wxSizerFlags().Center());

p->SetSizer( topsizer );

// don't allow frame to get smaller than what the sizers tell it and also set  
// the initial size as calculated by the sizers  
topsizer->SetSizeHints( this );  

}

最后是我的代码

std::shared_ptr sptr_delegate;

bool MyApp::OnInit()
{
if (!wxApp::OnInit())
return false;

MyFrame\* frame = new MyFrame;  
sptr\_delegate = std::shared\_ptr<MyFrameDelegate>(new MyFrameDelegate(frame));  
MyFrameDelegate\* delegate = sptr\_delegate.get();  
wxPanel\* p = new wxPanel((wxWindow\*)frame, wxID\_ANY);  
wxMenuBar\* mb =  
menu::begin(new wxMenuBar)  
            ("&File",  
             menu::begin(new wxMenu)  
                (LAYOUT\_TEST\_PROPORTIONS, "&Proportions demo...\\tF1", &MyFrame::TestMenuCommand, frame)  
                (LAYOUT\_TEST\_SIZER, "Test wx&FlexSizer...\\tF2", &MyFrame::TestMenuCommand, frame)  
                (LAYOUT\_TEST\_NB\_SIZER, "Test &notebook sizers...\\tF3", &MyFrame::TestMenuCommand, frame)  
                (LAYOUT\_TEST\_GB\_SIZER, "Test &gridbag sizer...\\tF4", frame, \[=\](wxCommandEvent& event) { frame->TestMenuCommand(event); })  
                (LAYOUT\_TEST\_SET\_MINIMAL, "Test Set&ItemMinSize...\\tF5")  
                (LAYOUT\_TEST\_NESTED, "Test nested sizer in a wxPanel...\\tF6", frame, \[=\](wxCommandEvent& event) { sptr\_delegate->TestMenuCommand(event); })(LAYOUT\_TEST\_WRAP, "Test wrap sizers...\\tF7")  
                (menu::end))  
            ("&Help",  
             menu::begin(new wxMenu)  
                (LAYOUT\_ABOUT, "&About", "About layout demo...")  
                (menu::end))  
            ("level-tree",  
             menu::begin(new wxMenu)  
                (wxID\_ANY, "level-1.1",  
                    menu::begin(new wxMenu)  
                            (wxID\_ANY, "level-1.1-level-2.1")  
                            (wxID\_ANY, "level-1.1-level-2.2")  
                            (menu::end))  
                (wxID\_ANY, "level-1.2",  
                    menu::begin(new wxMenu)  
                            (wxID\_ANY, "level-1.2-level-2.1")  
                            (wxID\_ANY, "level-1.2-level-2.2")  
                            (menu::end))  
                (menu::end))  
            (menu::end,  
                \[=\](wxMenuBar\* mb) {  
                    frame->SetMenuBar(mb);  
                });

layout::begin(new wxBoxSizer(wxVERTICAL))  
// 1) top: create wxStaticText with minimum size equal to its default size  
    (new wxStaticText( p, wxID\_ANY, "An explanation (wxALIGN\_RIGHT)." ),  
    wxSizerFlags().Align(wxALIGN\_RIGHT).Border(wxALL & ~wxBOTTOM, ))  
    (new wxStaticText( p, wxID\_ANY, "An explanation (wxALIGN\_LEFT)." ),  
    wxSizerFlags().Align(wxALIGN\_LEFT).Border(wxALL & ~wxBOTTOM, ))  
    (new wxStaticText( p, wxID\_ANY, "An explanation (wxALIGN\_CENTRE\_HORIZONTAL)." ),  
    wxSizerFlags().Align(wxALIGN\_CENTRE\_HORIZONTAL).Border(wxALL & ~wxBOTTOM, ))

// 2) top: create wxTextCtrl with minimum size (100x60)  
    (new wxTextCtrl( p, wxID\_ANY, "My text (wxEXPAND).", wxDefaultPosition, wxSize(,), wxTE\_MULTILINE),  
    wxSizerFlags().Expand().Border(wxALL, ))

// 2.5) Gratuitous test of wxStaticBoxSizers  
    (layout::begin(new wxStaticBoxSizer(new wxStaticBox(p, wxID\_ANY, "A wxStaticBoxSizer"), wxVERTICAL))  
        (new wxStaticText(p, wxID\_ANY, "And some TEXT inside it"), wxSizerFlags().Border(wxALL, ))  
        (layout::end), wxSizerFlags().Expand().Border(wxALL, ))

// 2.7) And a test of wxGridSizer  
    (layout::begin(new wxGridSizer(, , ))  
            (new wxStaticText(p, wxID\_ANY, "Label"),  
            wxSizerFlags().Align(wxALIGN\_RIGHT | wxALIGN\_CENTER\_VERTICAL))  
            (new wxTextCtrl(p, wxID\_ANY, "Grid sizer demo"),  
            wxSizerFlags().Align(wxGROW | wxALIGN\_CENTER\_VERTICAL))  
            (new wxStaticText(p, wxID\_ANY, "Another label"),  
            wxSizerFlags().Align(wxALIGN\_RIGHT | wxALIGN\_CENTER\_VERTICAL))  
            (new wxTextCtrl(p, wxID\_ANY, "More text"),  
            wxSizerFlags().Align(wxGROW | wxALIGN\_CENTER\_VERTICAL))  
            (new wxStaticText(p, wxID\_ANY, "Final label"),  
            wxSizerFlags().Align(wxALIGN\_RIGHT | wxALIGN\_CENTER\_VERTICAL))  
            (new wxTextCtrl(p, wxID\_ANY, "And yet more text"),  
            wxSizerFlags().Align(wxGROW | wxALIGN\_CENTER\_VERTICAL))  
            (layout::end), wxSizerFlags().Proportion().Expand().Border(wxALL, ))

#if wxUSE_STATLINE
// 3) middle: create wxStaticLine with minimum size (3x3)
(new wxStaticLine( p, wxID_ANY, wxDefaultPosition, wxSize(,), wxHORIZONTAL),
wxSizerFlags().Expand())
#endif // wxUSE_STATLINE

// 4) bottom: create two centred wxButtons  
    (layout::begin(new wxBoxSizer( wxHORIZONTAL ))  
        (new wxButton( p, wxID\_ANY, "Two buttons in a box" ),  
        wxSizerFlags().Border(wxALL, ))\[onclick = \[=\](wxCommandEvent& e) { delegate->OnClick(e); } \]  
        (new wxButton( p, wxID\_ANY, "(wxCENTER)" ),  
        wxSizerFlags().Border(wxALL, ))  
        (layout::end), wxSizerFlags().Center())  
    (layout::end,  
        \[=\](wxSizer\* s) {  
            p->SetSizer(s);  
            s->SetSizeHints(frame);  
        });

frame->Show(true);  
return true;  

}

zwx_helper将会在https://github.com/bbqz007/zhelper-wxWidgets/发布。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章