Customize Consent Preferences

We use cookies to help you navigate efficiently and perform certain functions. You will find detailed information about all cookies under each consent category below.

The cookies that are categorized as "Necessary" are stored on your browser as they are essential for enabling the basic functionalities of the site. ... 

Always Active

Necessary cookies are required to enable the basic features of this site, such as providing secure log-in or adjusting your consent preferences. These cookies do not store any personally identifiable data.

No cookies to display.

Functional cookies help perform certain functionalities like sharing the content of the website on social media platforms, collecting feedback, and other third-party features.

No cookies to display.

Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics such as the number of visitors, bounce rate, traffic source, etc.

No cookies to display.

Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.

No cookies to display.

Advertisement cookies are used to provide visitors with customized advertisements based on the pages you visited previously and to analyze the effectiveness of the ad campaigns.

No cookies to display.

Skip to content Skip to footer

Сделайте мне красиво – Часть II – wxAUI в Multi-View приложений

Использование возможностей библиотеки wxAUI для создания Multi-View приложений

Ну вот, «Ножки дошли до ручки» (c) <один-очень-хороший-человек>, вернее, ручки дошли до новых возможностей библиотеки wxAUI. И, сдается мне, что эти новые возможности будут востребованы в моих последующих проектах, ибо удобство и эстетичность GUI, созданного с их помощью, лично меня приводит в восторг.

Создадим базу для нашего приложения. Разница между приложением, использующим возможности библиотеки wxAUI для создания нескольких представлений (views), заключается лишь в том, что класс главной формы наследуется не от wxFrame, а от wxAuiMDIParentFrame. В этом случае на форме автоматически будет создан wxAuiNotebook, который будет служить контейнером для дочерних окон и доступ к которому можно получить через метод GetNotebook()
Для создания статических окон (которые будут отображаться вне зависимости от активного дочернего окна), будем использовать wxAuiManager, как и в обычном приложении.
Хотелось бы добавить вот что… Пусть вас не смущают названия типа AUIDocView*.h, на самом деле архитектура Document/View в данном примере не используется и на данный момент библиотека wxAUI не предоставляет такой возможности, но… я, в данный момент, серьезно подумываю о ее реализации и, если окажется, что в официальном RoadMap’е wxAUI планов по созданию данного функционала нет, то можно будет попробовать его реализовать вручную, благо там привязка к GUI минимальна.
Итак, начнем:

AUIDocViewMainFrame.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#ifndef _AUI_DOCVIEW_MAINFRAME_H
#define _AUI_DOCVIEW_MAINFRAME_H
 
#include <wx/wx.h>
#include <wx/textctrl.h>
#include <wx/aui/aui.h>
#include <wx/aui/tabmdi.h>
 
#define AUIDocViewMainFrameTitle wxT("AUI DocView Test")
 
enum
{
    ID_LOG_TEXTCTRL = 10001,
    ID_TOGGLE_LOGWINDOW
};
 
class AUIDocViewMainFrame : public wxAuiMDIParentFrame
{
    DECLARE_DYNAMIC_CLASS(AUIDocViewMainFrame);
    wxTextCtrl * m_LOGTextCtrl;
    wxAuiManager m_FrameManager;
    void CreateControls();
    static wxMenuBar * CreateMainMenuBar();
public:
    AUIDocViewMainFrame();
    AUIDocViewMainFrame(wxWindow * parent, wxWindowID id = wxID_ANY,
        const wxString & title = AUIDocViewMainFrameTitle);
    ~AUIDocViewMainFrame();
    bool Create(wxWindow * parent, wxWindowID id = wxID_ANY,
        const wxString & title = AUIDocViewMainFrameTitle);
 
    wxTextCtrl * GetLOGTextCtrl();
 
    bool GetPaneVisibility(wxString pane_name);
    void TogglePaneVisibility(wxString pane_name);
 
    DECLARE_EVENT_TABLE()
    void OnExit(wxCommandEvent & event);
    void OnAbout(wxCommandEvent & event);
void OnToggleLogWindow(wxCommandEvent & event);
    void OnToggleLogWindowUpdateUI(wxUpdateUIEvent & event);
};
 
#endif

AUIDocViewMainFrame.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include "AUIDocViewMainFrame.h"
#include <wx/aboutdlg.h>
 
IMPLEMENT_DYNAMIC_CLASS(AUIDocViewMainFrame, wxAuiMDIParentFrame);
 
BEGIN_EVENT_TABLE(AUIDocViewMainFrame , wxAuiMDIParentFrame)
EVT_MENU(wxID_EXIT, AUIDocViewMainFrame::OnExit)
EVT_MENU(wxID_ABOUT, AUIDocViewMainFrame::OnAbout)
EVT_MENU(ID_TOGGLE_LOGWINDOW, AUIDocViewMainFrame::OnToggleLogWindow)
EVT_UPDATE_UI(ID_TOGGLE_LOGWINDOW, AUIDocViewMainFrame::OnToggleLogWindowUpdateUI)
END_EVENT_TABLE()
 
AUIDocViewMainFrame::AUIDocViewMainFrame ()
{
}
 
AUIDocViewMainFrame::AUIDocViewMainFrame (wxWindow * parent, wxWindowID id,const wxString & title)
{
    Create(parent, id, title);
}
 
AUIDocViewMainFrame::~AUIDocViewMainFrame()
{
    m_FrameManager.UnInit();
}
 
bool AUIDocViewMainFrame::Create(wxWindow * parent, wxWindowID id,const wxString & title)
{
    bool res = wxAuiMDIParentFrame::Create(parent, id, title, wxDefaultPosition,
        wxSize(600,500), wxDEFAULT_FRAME_STYLE|wxFRAME_NO_WINDOW_MENU);
    if(res)
    {
        m_HeaderStyle = HS_DEFAULT;
        CreateControls();
    }
    return res;
}
 
wxMenuBar * AUIDocViewMainFrame::CreateMainMenuBar()
{
    wxMenuBar * menuBar = new wxMenuBar;
 
    wxMenu * fileMenu = new wxMenu;
    fileMenu->Append(wxID_EXIT, _("Exit\tAlt+F4"));
    menuBar->Append(fileMenu, _("File"));
 
    wxMenu * viewMenu = new wxMenu;
    viewMenu->AppendCheckItem(ID_TOGGLE_LOGWINDOW, _("Toggle Help Window"));
    menuBar->Append(viewMenu, _("View"));
 
    wxMenu * helpMenu = new wxMenu;
    helpMenu->Append(wxID_ABOUT, _("About..."));
    menuBar->Append(helpMenu, _("Help"));
 
    return menuBar;
}
 
void AUIDocViewMainFrame::CreateControls()
{
    SetMenuBar(AUIDocViewMainFrame::CreateMainMenuBar());
    CreateStatusBar(2);
    m_LOGTextCtrl = new wxTextCtrl(this, ID_LOG_TEXTCTRL, wxEmptyString,
        wxDefaultPosition, wxSize(250, 100),
        wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER);
 
    GetNotebook()->SetWindowStyleFlag(wxAUI_NB_TOP|
        wxAUI_NB_TAB_MOVE |
        wxAUI_NB_SCROLL_BUTTONS |
        wxNO_BORDER);
 
    m_FrameManager.SetManagedWindow(this);
    m_FrameManager.AddPane(GetNotebook(), wxAuiPaneInfo().
        Name(wxT("CenterPane")).CenterPane());
    m_FrameManager.AddPane(m_LOGTextCtrl, wxAuiPaneInfo().Bottom().
        Name(wxT("Help")).Caption(_("Help Window")));
    m_FrameManager.Update();
}
 
void AUIDocViewMainFrame::OnExit(wxCommandEvent & event)
{
    Close();
}
 
void AUIDocViewMainFrame::OnAbout(wxCommandEvent & event)
{
    wxAboutDialogInfo info;
    info.SetName(wxT("MultiView Test"));
    info.SetVersion(wxT("v0.1"));
    info.SetWebSite(wxT("https://wxwidgets.info"));
    info.AddDeveloper(wxT("Volodymir (T-Rex) Tryapichko"));
    wxAboutBox(info);
}
 
wxTextCtrl * AUIDocViewMainFrame::GetLOGTextCtrl()
{
    return m_LOGTextCtrl;
}
 
void AUIDocViewMainFrame::OnToggleLogWindow(wxCommandEvent & event)
{
    TogglePaneVisibility(wxT("Help"));
}
 
void AUIDocViewMainFrame::OnToggleLogWindowUpdateUI(wxUpdateUIEvent & event)
{
    event.Check(GetPaneVisibility(wxT("Help")));
}
 
bool AUIDocViewMainFrame::GetPaneVisibility(wxString pane_name)
{
    wxAuiPaneInfoArray& all_panes = m_FrameManager.GetAllPanes();
    size_t i, count;
    for (i = 0, count = all_panes.GetCount(); i < count; ++i)
    {
        if(all_panes.Item(i).name == pane_name)
        {
                return all_panes.Item(i).IsShown();
        }
    }
    return false;
}
 
void AUIDocViewMainFrame::TogglePaneVisibility(wxString pane_name)
{
    wxAuiPaneInfoArray& all_panes = m_FrameManager.GetAllPanes();
    size_t i, count;
    for (i = 0, count = all_panes.GetCount(); i < count; ++i)
    {
        if(all_panes.Item(i).name == pane_name)
        {
            all_panes.Item(i).Show(!all_panes.Item(i).IsShown());
            m_FrameManager.Update();
            break;
        }
    }
}
&#91;/sourcecode&#93;
 
<b>AUIDocViewApp.h</b>
[sourcecode language="cpp"]
#ifndef _AUI_DOCVIEW_APP_H
#define _AUI_DOCVIEW_APP_H
 
#include <wx/wx.h>
 
class AUIDocViewApp : public wxApp
{
public:
    virtual bool OnInit();
};
 
DECLARE_APP(AUIDocViewApp);
 
#endif

AUIDocViewApp.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "AUIDocViewApp.h"
#include "AUIDocViewMainFrame.h"
#include <wx/image.h>
 
IMPLEMENT_APP(AUIDocViewApp)
 
bool AUIDocViewApp::OnInit()
{
    srand(time(NULL));
 
    wxImage::AddHandler(new wxXPMHandler);
    wxImage::AddHandler(new wxPNGHandler);
 
    AUIDocViewMainFrame * frame = new AUIDocViewMainFrame(NULL);
    SetTopWindow(frame);
    frame->Centre();
    frame->Show();
    return true;
}

Сделайте мне красиво - Часть II - wxAUI в Multi-View приложении

Как видно, мы создали окно, содержащее строку меню, строку состояния и плавающую панель «Help Window». Плавающая панель может бать спрятана или отображена с помощью пункта меню «Toggle Help Window»
Теперь можно приступить к созданию дочерних окон.

AUIDocViewChildFrame.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#ifndef _AUI_DOCVIEW_CHILDFRAME_H
#define _AUI_DOCVIEW_CHILDFRAME_H
 
#include <wx/wx.h>
#include <wx/toolbar.h>
#include <wx/aui/tabmdi.h>
 
class AUIDocViewChildFrame : public wxAuiMDIChildFrame
{
    bool m_HasToolBar;
    void CreateControls();
    wxToolBar * m_ToolBar;
    wxMenuBar * CreateMenuBar();
public:
    AUIDocViewChildFrame();
    AUIDocViewChildFrame(wxAuiMDIParentFrame * parent, wxWindowID id = wxID_ANY,
        const wxString & title = wxEmptyString, bool has_toolbar = true);
    bool Create(wxAuiMDIParentFrame * parent, wxWindowID id = wxID_ANY,
        const wxString & title = wxEmptyString, bool has_toolbar = true);
 
    virtual wxToolBar* CreateToolBar(long style,
                                     wxWindowID winid,
                                     const wxString& WXUNUSED(name));
    virtual wxToolBar *GetToolBar() const;
private:
    void OnToolButton(wxCommandEvent & event);
    void OnToggleToolbar(wxCommandEvent & event);
    void OnActivated(wxActivateEvent & event);
};
 
#endif

AUIDocViewChildFrame.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include "AUIDocViewChildFrame.h"
#include "AUIDocViewMainFrame.h"
 
#include "news_sticky.xpm"
#include "news_question.xpm"
 
enum
{
    ID_CHILD_TOGGLE_TOOLBAR = 11001,
    //--- BUTTONS ---
    ID_CHILD_BUTTON_ID_START = 12000
};
 
AUIDocViewChildFrame::AUIDocViewChildFrame()
{
}
 
AUIDocViewChildFrame::AUIDocViewChildFrame(wxAuiMDIParentFrame * parent,
wxWindowID id, const wxString & title, bool has_toolbar)
{
    m_ToolBar = NULL;
    Create(parent, id, title, has_toolbar);
}
 
bool AUIDocViewChildFrame::Create(wxAuiMDIParentFrame * parent, wxWindowID id,
    const wxString & title, bool has_toolbar)
{
    bool res = wxAuiMDIChildFrame::Create(parent, id, title);
    if(res)
    {
        m_HasToolBar = has_toolbar;
        CreateControls();
    }
    return res;
}
 
void AUIDocViewChildFrame::CreateControls()
{
    SetSizer(new wxBoxSizer(wxVERTICAL));
    Connect(wxID_ANY, wxEVT_ACTIVATE,
        wxActivateEventHandler(AUIDocViewChildFrame::OnActivated));
    wxToolBar * toolBar = CreateToolBar(wxTB_FLAT|wxTB_NODIVIDER,
        wxID_ANY, GetTitle());
    if(toolBar)
    {
        GetSizer()->Add(toolBar, 0, wxGROW);
        Connect(ID_CHILD_TOGGLE_TOOLBAR,
                wxEVT_COMMAND_MENU_SELECTED,
                wxCommandEventHandler(AUIDocViewChildFrame::OnToggleToolbar));
    }
    SetMenuBar(CreateMenuBar());
    SetBackgroundColour(wxColour(100+rand()%156,
        100+rand()%156, 100+rand()%156));
}
 
wxMenuBar * AUIDocViewChildFrame::CreateMenuBar()
{
    wxMenuBar * menuBar = new wxMenuBar;
 
    wxMenu * fileMenu = new wxMenu;
    fileMenu->Append(wxID_EXIT, _("Exit\tAlt+F4"));
    menuBar->Append(fileMenu, _("File"));
 
    wxMenu * viewMenu = new wxMenu;
    viewMenu->AppendCheckItem(ID_TOGGLE_LOGWINDOW, _("Toggle Help Window"));
    if(m_HasToolBar)
    {
        viewMenu->Append(ID_CHILD_TOGGLE_TOOLBAR, _("Toggle toolbar"));
    }
    menuBar->Append(viewMenu, _("View"));
 
    wxMenu * helpMenu = new wxMenu;
    helpMenu->Append(wxID_ABOUT, _("About..."));
    menuBar->Append(helpMenu, _("Help"));
 
    return menuBar;
}
 
void AUIDocViewChildFrame::OnToggleToolbar(wxCommandEvent & event)
{
    if(m_ToolBar)
    {
        if(m_ToolBar->IsShown())
        {
            GetSizer()->Detach(m_ToolBar);
            m_ToolBar->Hide();
        }
        else
        {
            m_ToolBar->Show();
            GetSizer()->Insert(0, m_ToolBar, 0, wxGROW);
        }
    }
}
 
wxToolBar * AUIDocViewChildFrame::CreateToolBar(long style,
wxWindowID winid, const wxString& WXUNUSED(name))
{
    if(!m_ToolBar && m_HasToolBar)
    {
        m_ToolBar = new wxToolBar(this, winid, wxDefaultPosition,
            wxDefaultSize, style);
        wxBitmap bmp;
        for(int i = 0; i < 1+rand()%10; i++)
        {
            if(rand()%2)
            {
                bmp = wxBitmap(news_sticky_xpm);
            } else bmp = wxBitmap(news_question_xpm);
            wxWindowID id = ID_CHILD_BUTTON_ID_START+i;
            m_ToolBar->AddTool(id, bmp, wxString::Format(wxT("Tool %i"), i));
            Connect(id, wxEVT_COMMAND_MENU_SELECTED,
                    wxCommandEventHandler(AUIDocViewChildFrame::OnToolButton));
        }
        m_ToolBar->Realize();
    }
    return m_ToolBar;
}
 
wxToolBar * AUIDocViewChildFrame::GetToolBar() const
{
    return m_ToolBar;
}
 
void AUIDocViewChildFrame::OnToolButton(wxCommandEvent & event)
{
    wxMessageBox(wxString::Format(_("Button %u pressed"),
        event.GetId()-ID_CHILD_BUTTON_ID_START+1));
}
 
void AUIDocViewChildFrame::OnActivated(wxActivateEvent & event)
{
    AUIDocViewMainFrame * frame = wxDynamicCast(GetMDIParentFrame(),
        AUIDocViewMainFrame);
    if(frame)
    {
        frame->GetLOGTextCtrl()->SetValue(wxString::Format(
            _("Some help text about '%s'"), GetTitle().GetData()));
    }
}

AUIDocViewMainFrame.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void AUIDocViewMainFrame::CreateControls()
{
    ...
    for(int i = 0; i < 5; i++)
    {
        AUIDocViewChildFrame * frame = new AUIDocViewChildFrame(this, wxID_ANY,
            wxString::Format(wxT("View %i"), i+1), (rand()%2)?true:false);
        wxUnusedVar(frame);
    }
    GetNotebook()->SetWindowStyleFlag(wxAUI_NB_TOP|
        wxAUI_NB_TAB_MOVE |
        wxAUI_NB_SCROLL_BUTTONS |
        wxNO_BORDER);
    GetNotebook()->SetSelection(0);
...
}

Итак, мы создали класс дочернего окна, которое может иметь (или не иметь) панель инструментов (в зависимости от параметров, передаваемых конструктору). Кроме того, каждое дочернее окно может иметь свою строку меню (см. AUIDocViewChildFrame::CreateMenuBar()) . Если дочернее окно содержит панель инструментов, то в строке меню отображается пункт «Toggle toolbar».
При активизации дочернего окна, в панели «HelpWindow» отображается соответствующий текст. Доступ к главной форме из дочернего окна можно получить, используя метод wxAuiMDIChildFrame::GetMDIParentFrame().
Вот так будет выглядеть наше приложение после внесения всех изменений.

Сделайте мне красиво - Часть II - wxAUI в Multi-View приложении

А вот как наше приложение будет выглядеть в Liunx

Сделайте мне красиво - Часть II - wxAUI в Multi-View приложении

Но это еще не все. Существует интересная возможность смены интерфейса закладок в wxAuiNotebook. Для этого используются классы, производные от wxAuiTabArt (о них я расскажу как-нибудь позже). В нашем приложении мы будем использовать классы wxAuiDefaultTabArt и wxAuiSimpleTabArt, которые доступны в стандартной поставке wxAUI.
К сожалению, класс wxAuiTabArt не является потомком wxObject и для него недоступен RTTI, что не дает возможности определить, какой скин установлен в данный момент. Поэтому для определения активного скина заведем дополнительный enum HeaderStyle.
Ну что же, пора вносить новые изменения в исходный код:

AUIDocViewMainFrame.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#ifndef _AUI_DOCVIEW_MAINFRAME_H
#define _AUI_DOCVIEW_MAINFRAME_H
...
 
enum HeaderStyle
{
    HS_DEFAULT,
    HS_SIMPLE
};
 
enum
{
    ID_LOG_TEXTCTRL = 10001,
    ID_HEADER_DEFAULT_STYLE,
    ID_HEADER_SIMPLE_STYLE,
    ID_TOGGLE_LOGWINDOW
};
...
class AUIDocViewMainFrame : public wxAuiMDIParentFrame
{
    DECLARE_DYNAMIC_CLASS(AUIDocViewMainFrame);
    HeaderStyle m_HeaderStyle;
    ...
public:
    ...
    HeaderStyle GetHeaderStyle();
    ...
    DECLARE_EVENT_TABLE()
    ...
    void OnSwitchHeaderStyle(wxCommandEvent & event);
    void OnSwitchHeaderStyleUpdateUI(wxUpdateUIEvent & event);
    ...
};
 
#endif

AUIDocViewMainFrame.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include "AUIDocViewMainFrame.h"
#include "AUIDocViewChildFrame.h"
#include <wx/aboutdlg.h>
 
IMPLEMENT_DYNAMIC_CLASS(AUIDocViewMainFrame, wxAuiMDIParentFrame);
 
BEGIN_EVENT_TABLE(AUIDocViewMainFrame , wxAuiMDIParentFrame)
...
EVT_MENU(ID_HEADER_DEFAULT_STYLE, AUIDocViewMainFrame::OnSwitchHeaderStyle)
EVT_MENU(ID_HEADER_SIMPLE_STYLE, AUIDocViewMainFrame::OnSwitchHeaderStyle)
...
EVT_UPDATE_UI(ID_HEADER_DEFAULT_STYLE, AUIDocViewMainFrame::OnSwitchHeaderStyleUpdateUI)
EVT_UPDATE_UI(ID_HEADER_SIMPLE_STYLE, AUIDocViewMainFrame::OnSwitchHeaderStyleUpdateUI)
...
END_EVENT_TABLE()
...
wxMenuBar * AUIDocViewMainFrame::CreateMainMenuBar()
{
    ...
    wxMenu * viewMenu = new wxMenu;
    wxMenu * headerMenu = new wxMenu;
    headerMenu->AppendRadioItem(ID_HEADER_DEFAULT_STYLE, _("Default"));
    headerMenu->AppendRadioItem(ID_HEADER_SIMPLE_STYLE, _("Simple"));
    viewMenu->Append(wxID_ANY, _("Header"), headerMenu);
    ...
}
 
...
void AUIDocViewMainFrame::OnSwitchHeaderStyle(wxCommandEvent & event)
{
    wxAuiTabArt * art(NULL);
    switch(event.GetId())
    {
    default:
    case ID_HEADER_DEFAULT_STYLE:
        art = new wxAuiDefaultTabArt;
        m_HeaderStyle = HS_DEFAULT;
        break;
    case ID_HEADER_SIMPLE_STYLE:
        art = new wxAuiSimpleTabArt;
        m_HeaderStyle = HS_SIMPLE;
        break;
    }
    if(art)
    {
        GetNotebook()->SetArtProvider(art);
    }
}
 
HeaderStyle AUIDocViewMainFrame::GetHeaderStyle()
{
    return m_HeaderStyle;
}
 
void AUIDocViewMainFrame::OnSwitchHeaderStyleUpdateUI(wxUpdateUIEvent & event)
{
    switch(event.GetId())
    {
    case ID_HEADER_DEFAULT_STYLE:
        event.Check(GetHeaderStyle() == HS_DEFAULT);
        break;
    case ID_HEADER_SIMPLE_STYLE:
        event.Check(GetHeaderStyle() == HS_SIMPLE);
        break;
    default:
        event.Skip();
    }
}
...

В принципе, внесенные изменениядовольно просты. Мы добавили переменную-индикатор текущего скина, меню «Header» с двумя пунктами, которые позволяют сменить активный скин, а также обработчики события wxUpdateUIEvent, необходимые для того, чтобы маркер активного скина корректно отображался в меню.
После всего сделанного, мы должны получить вот приблизительно такой результат.

Сделайте мне красиво - Часть II - wxAUI в Multi-View приложении

Но и это еще не всё. Интересной особенностью является также возможность использования плавающих панелей внутри каждого дочернего окна. В этом случае докинг будет осуществляться только внутри дочернего окна.

Для демонстрации этих возможностей изменим немного класс дочернего окна и создадим производный от него класс, который будет частично наследовать уже существующий функционал, а также будет предоставлять возможность размещения плавающих панелей.

AUIDocViewChildFrame.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#ifndef _AUI_DOCVIEW_CHILDFRAME_H
#define _AUI_DOCVIEW_CHILDFRAME_H
 
#include <wx/wx.h>
#include <wx/toolbar.h>
#include <wx/treectrl.h>
#include <wx/aui/tabmdi.h>
 
class AUIDocViewChildFrame : public wxAuiMDIChildFrame
{
protected:
    wxToolBar * m_ToolBar;
    bool m_HasToolBar;
    virtual wxMenuBar * CreateMenuBar();
    virtual void CreateControls();
public:
    AUIDocViewChildFrame();
    AUIDocViewChildFrame(wxAuiMDIParentFrame * parent, wxWindowID id = wxID_ANY,
        const wxString & title = wxEmptyString, bool has_toolbar = true);
    bool Create(wxAuiMDIParentFrame * parent, wxWindowID id = wxID_ANY,
        const wxString & title = wxEmptyString, bool has_toolbar = true);
 
    virtual wxToolBar* CreateToolBar(long style,
                                     wxWindowID winid,
                                     const wxString& WXUNUSED(name));
    virtual wxToolBar *GetToolBar() const;
    DECLARE_EVENT_TABLE()
    void OnActivated(wxActivateEvent & event);
    void OnToolButton(wxCommandEvent & event);
    virtual void OnToggleToolbar(wxCommandEvent & event);
    virtual void OnToggleToolbarUpdateUI(wxUpdateUIEvent & event);
};
 
class AUIManagedChildFrame : public AUIDocViewChildFrame
{
    wxAuiManager m_FrameManager;
    wxTreeCtrl * m_TreeCtrl;
    virtual wxMenuBar * CreateMenuBar();
    virtual void CreateControls();
public:
    ~AUIManagedChildFrame();
 
    bool GetPaneVisibility(wxString pane_name);
    void TogglePaneVisibility(wxString pane_name);
    DECLARE_EVENT_TABLE()
    void OnToggleTreeCtrl(wxCommandEvent & event);
    void OnToggleTreeCtrlUpdateUI(wxUpdateUIEvent & event);
    virtual void OnToggleToolbar(wxCommandEvent & event);
    virtual void OnToggleToolbarUpdateUI(wxUpdateUIEvent & event);
};
 
#endif

AUIDocViewChildFrame.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
#include "AUIDocViewChildFrame.h"
#include "AUIDocViewMainFrame.h"
 
#include "news_sticky.xpm"
#include "news_question.xpm"
 
enum
{
    ID_CHILD_TOGGLE_TOOLBAR = 11001,
    ID_CHILD_TOGGLE_TREECTRL,
    //--- BUTTONS ---
    ID_CHILD_BUTTON_ID_START = 12000
};
 
BEGIN_EVENT_TABLE(AUIDocViewChildFrame, wxAuiMDIChildFrame)
EVT_ACTIVATE(AUIDocViewChildFrame::OnActivated)
END_EVENT_TABLE()
 
AUIDocViewChildFrame::AUIDocViewChildFrame()
{
}
 
bool AUIDocViewChildFrame::Create(wxAuiMDIParentFrame * parent, wxWindowID id,
    const wxString & title, bool has_toolbar)
{
    bool res = wxAuiMDIChildFrame::Create(parent, id, title);
    if(res)
    {
        m_ToolBar = NULL;
        m_HasToolBar = has_toolbar;
        CreateControls();
    }
    return res;
}
 
void AUIDocViewChildFrame::CreateControls()
{
    SetSizer(new wxBoxSizer(wxVERTICAL));
    m_ToolBar = CreateToolBar(wxTB_FLAT|wxTB_NODIVIDER, wxID_ANY, GetTitle());
    if(m_ToolBar)
    {
        GetSizer()->Add(m_ToolBar, 0, wxGROW);
        Connect(ID_CHILD_TOGGLE_TOOLBAR,
                wxEVT_COMMAND_MENU_SELECTED,
                wxCommandEventHandler(AUIDocViewChildFrame::OnToggleToolbar));
        Connect(ID_CHILD_TOGGLE_TOOLBAR,
                wxEVT_UPDATE_UI,
                wxUpdateUIEventHandler(AUIDocViewChildFrame::OnToggleToolbarUpdateUI));
    }
    SetMenuBar(CreateMenuBar());
    SetBackgroundColour(wxColour(100+rand()%156, 100+rand()%156, 100+rand()%156));
}
 
wxMenuBar * AUIDocViewChildFrame::CreateMenuBar()
{
    wxMenuBar * menuBar = new wxMenuBar;
 
    wxMenu * fileMenu = new wxMenu;
    fileMenu->Append(wxID_EXIT, _("Exit\tAlt+F4"));
    menuBar->Append(fileMenu, _("File"));
 
    wxMenu * viewMenu = new wxMenu;
    wxMenu * headerMenu = new wxMenu;
    headerMenu->AppendRadioItem(ID_HEADER_DEFAULT_STYLE, _("Default"));
    headerMenu->AppendRadioItem(ID_HEADER_SIMPLE_STYLE, _("Simple"));
    viewMenu->Append(wxID_ANY, _("Header"), headerMenu);
    viewMenu->AppendCheckItem(ID_TOGGLE_LOGWINDOW, _("Toggle Help Window"));
    if(m_HasToolBar)
    {
        viewMenu->AppendCheckItem(ID_CHILD_TOGGLE_TOOLBAR, _("Toggle toolbar"));
    }
    menuBar->Append(viewMenu, _("View"));
 
    wxMenu * helpMenu = new wxMenu;
    helpMenu->Append(wxID_ABOUT, _("About..."));
    menuBar->Append(helpMenu, _("Help"));
 
    return menuBar;
}
 
void AUIDocViewChildFrame::OnToggleToolbar(wxCommandEvent & event)
{
    if(m_ToolBar)
    {
        if(m_ToolBar->IsShown())
        {
            GetSizer()->Detach(m_ToolBar);
            m_ToolBar->Hide();
        }
        else
        {
            m_ToolBar->Show();
            GetSizer()->Insert(0, m_ToolBar, 0, wxGROW);
        }
    }
}
 
void AUIDocViewChildFrame::OnToggleToolbarUpdateUI(wxUpdateUIEvent & event)
{
    if(m_ToolBar)
    {
        event.Check(m_ToolBar->IsShown());
    }
    else event.Skip();
}
 
wxToolBar * AUIDocViewChildFrame::CreateToolBar(long style,
wxWindowID winid, const wxString& WXUNUSED(name))
{
    if(!m_ToolBar && m_HasToolBar)
    {
        m_ToolBar = new wxToolBar(this, winid, wxDefaultPosition, wxDefaultSize, style);
        wxBitmap bmp;
        for(int i = 0; i < 1+rand()%10; i++)
        {
            if(rand()%2)
            {
                bmp = wxBitmap(news_sticky_xpm);
            } else bmp = wxBitmap(news_question_xpm);
            wxWindowID id = ID_CHILD_BUTTON_ID_START+i;
            m_ToolBar->AddTool(id, bmp, wxString::Format(wxT("Tool %i"), i));
            Connect(id, wxEVT_COMMAND_MENU_SELECTED,
                    wxCommandEventHandler(AUIDocViewChildFrame::OnToolButton));
        }
        m_ToolBar->Realize();
    }
    return m_ToolBar;
}
 
wxToolBar * AUIDocViewChildFrame::GetToolBar() const
{
    return m_ToolBar;
}
 
void AUIDocViewChildFrame::OnToolButton(wxCommandEvent & event)
{
    wxMessageBox(wxString::Format(_("Button %u pressed"),
        event.GetId()-ID_CHILD_BUTTON_ID_START+1));
}
 
void AUIDocViewChildFrame::OnActivated(wxActivateEvent & event)
{
    AUIDocViewMainFrame * frame = wxDynamicCast(GetMDIParentFrame(), AUIDocViewMainFrame);
    if(frame)
    {
        frame->GetLOGTextCtrl()->SetValue(wxString::Format(
            _("Some help text about '%s'"), GetTitle().GetData()));
    }
}
 
BEGIN_EVENT_TABLE(AUIManagedChildFrame, AUIDocViewChildFrame)
EVT_MENU(ID_CHILD_TOGGLE_TREECTRL, AUIManagedChildFrame::OnToggleTreeCtrl)
EVT_UPDATE_UI(ID_CHILD_TOGGLE_TREECTRL, AUIManagedChildFrame::OnToggleTreeCtrlUpdateUI)
END_EVENT_TABLE()
 
AUIManagedChildFrame::~AUIManagedChildFrame()
{
    m_FrameManager.UnInit();
}
 
void AUIManagedChildFrame::CreateControls()
{
    AUIDocViewChildFrame::CreateControls();
    m_FrameManager.SetManagedWindow(this);
    wxPanel * panel = new wxPanel(this, wxID_ANY);
    panel->SetBackgroundColour(
        wxColour(100+rand()%156, 100+rand()%156, 100+rand()%156));
    m_FrameManager.AddPane(panel,
        wxAuiPaneInfo().Name(wxT("CenterPane")).CenterPane());
 
    SetMenuBar(CreateMenuBar());
 
    wxToolBar * toolBar = CreateToolBar(wxTB_FLAT|wxTB_NODIVIDER, wxID_ANY, GetTitle());
    if(toolBar)
    {
        m_FrameManager.AddPane(toolBar, wxAuiPaneInfo().Name(wxT("ToolBar")).
            ToolbarPane().Top());
        Connect(ID_CHILD_TOGGLE_TOOLBAR,
                wxEVT_COMMAND_MENU_SELECTED,
                wxCommandEventHandler(AUIManagedChildFrame::OnToggleToolbar));
        Connect(ID_CHILD_TOGGLE_TOOLBAR,
                wxEVT_UPDATE_UI,
                wxUpdateUIEventHandler(AUIManagedChildFrame::OnToggleToolbarUpdateUI));
    }
 
    m_TreeCtrl = new wxTreeCtrl(this, wxID_ANY, wxDefaultPosition,
        wxSize(150, 300));
    wxTreeItemId root = m_TreeCtrl->AddRoot(_("Root"));
    m_TreeCtrl->AppendItem(root, _("Node 1"));
    m_TreeCtrl->AppendItem(root, _("Node 2"));
    m_TreeCtrl->AppendItem(root, _("Node 3"));
    m_TreeCtrl->Expand(root);
    m_FrameManager.AddPane(m_TreeCtrl, wxAuiPaneInfo().Name(wxT("Tree")).Left());
    m_FrameManager.Update();
}
 
void AUIManagedChildFrame::OnToggleToolbar(wxCommandEvent & event)
{
    TogglePaneVisibility(wxT("ToolBar"));
}
 
void AUIManagedChildFrame::OnToggleToolbarUpdateUI(wxUpdateUIEvent & event)
{
    event.Check(GetPaneVisibility(wxT("ToolBar")));
}
 
void AUIManagedChildFrame::OnToggleTreeCtrl(wxCommandEvent & event)
{
    TogglePaneVisibility(wxT("Tree"));
}
 
void AUIManagedChildFrame::OnToggleTreeCtrlUpdateUI(wxUpdateUIEvent & event)
{
    event.Check(GetPaneVisibility(wxT("Tree")));
}
 
bool AUIManagedChildFrame::GetPaneVisibility(wxString pane_name)
{
    wxAuiPaneInfoArray& all_panes = m_FrameManager.GetAllPanes();
    size_t i, count;
    for (i = 0, count = all_panes.GetCount(); i < count; ++i)
    {
        if(all_panes.Item(i).name == pane_name)
        {
                return all_panes.Item(i).IsShown();
        }
    }
    return false;
}
 
void AUIManagedChildFrame::TogglePaneVisibility(wxString pane_name)
{
    wxAuiPaneInfoArray& all_panes = m_FrameManager.GetAllPanes();
    size_t i, count;
    for (i = 0, count = all_panes.GetCount(); i < count; ++i)
    {
        if(all_panes.Item(i).name == pane_name)
        {
            all_panes.Item(i).Show(!all_panes.Item(i).IsShown());
            m_FrameManager.Update();
            break;
        }
    }
}
 
wxMenuBar * AUIManagedChildFrame::CreateMenuBar()
{
    wxMenuBar * menuBar = new wxMenuBar;
 
    wxMenu * fileMenu = new wxMenu;
    fileMenu->Append(wxID_EXIT, _("Exit\tAlt+F4"));
    menuBar->Append(fileMenu, _("File"));
 
    wxMenu * viewMenu = new wxMenu;
    wxMenu * headerMenu = new wxMenu;
    headerMenu->AppendRadioItem(ID_HEADER_DEFAULT_STYLE, _("Default"));
    headerMenu->AppendRadioItem(ID_HEADER_SIMPLE_STYLE, _("Simple"));
    viewMenu->Append(wxID_ANY, _("Header"), headerMenu);
    viewMenu->AppendCheckItem(ID_TOGGLE_LOGWINDOW, _("Toggle Help Window"));
    viewMenu->AppendCheckItem(ID_CHILD_TOGGLE_TREECTRL, _("Toggle tree"));
    if(m_HasToolBar)
    {
        viewMenu->AppendCheckItem(ID_CHILD_TOGGLE_TOOLBAR, _("Toggle toolbar"));
    }
    menuBar->Append(viewMenu, _("View"));
 
    wxMenu * helpMenu = new wxMenu;
    helpMenu->Append(wxID_ABOUT, _("About..."));
    menuBar->Append(helpMenu, _("Help"));
 
    return menuBar;
}

AUIDocViewMainFrame.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void AUIDocViewMainFrame::CreateControls()
{
    SetMenuBar(AUIDocViewMainFrame::CreateMainMenuBar());
    ...
 
    AUIDocViewChildFrame * f1 = new AUIDocViewChildFrame;
    f1->Create(this, wxID_ANY, wxT("View 1"), true);
 
    AUIManagedChildFrame * f2 = new AUIManagedChildFrame;
    f2->Create(this, wxID_ANY, wxT("View 2"), true);
    ...
 
    GetNotebook()->SetWindowStyleFlag(wxAUI_NB_TOP|
        wxAUI_NB_TAB_MOVE |
        wxAUI_NB_SCROLL_BUTTONS |
        wxNO_BORDER);
    GetNotebook()->SetSelection(0);
...
}

Теперь у нас должно получиться что-то типа этого:

Сделайте мне красиво - Часть II - wxAUI в Multi-View приложении

А вот как наше приложение будет выглядеть в Linux:
Сделайте мне красиво - Часть II - wxAUI в Multi-View приложении

Исходный код примеров:
Пример 1 (VS 2005)
Пример 2 (VS 2005 – Windows|Eclipse – Linux)

2 Comments

  • Vanya
    Posted March 3, 2010 at 15:24

    Привет, я воспользовался вашим примером ( на 2.9.0 и 2.8.3) и в обоих случаях при закрытии программы получаю ошибку про то что “Нарушение прав доступа при чтении…” и выскакивает файл framemanager.cpp с указанием на строку :
    …..
    else
    {
    if (p.window->IsShown() != p.IsShown())
    >> p.window->Show(p.IsShown());
    }
    ….

    Не подскажите в чем подвох?

  • T-Rex
    Posted March 4, 2010 at 16:42

    Возможно просто пофиксили баг с утечкой памяти для незадоченных окон и теперь этот кусок кода уже не нужен.

Leave a comment

0.0/5