Использование возможностей библиотеки wxAUI для создания Multi-View приложений
Ну вот, «Ножки дошли до ручки» (c) <один-очень-хороший-человек>, вернее, ручки дошли до новых возможностей библиотеки wxAUI. И, сдается мне, что эти новые возможности будут востребованы в моих последующих проектах, ибо удобство и эстетичность GUI, созданного с их помощью, лично меня приводит в восторг.
Создадим базу для нашего приложения. Разница между приложением, использующим возможности библиотеки wxAUI для создания нескольких представлений (views), заключается лишь в том, что класс главной формы наследуется не от wxFrame, а от wxAuiMDIParentFrame. В этом случае на форме автоматически будет создан wxAuiNotebook, который будет служить контейнером для дочерних окон и доступ к которому можно получить через метод GetNotebook()
Для создания статических окон (которые будут отображаться вне зависимости от активного дочернего окна), будем использовать wxAuiManager, как и в обычном приложении.
Хотелось бы добавить вот что… Пусть вас не смущают названия типа AUIDocView*.h, на самом деле архитектура Document/View в данном примере не используется и на данный момент библиотека wxAUI не предоставляет такой возможности, но… я, в данный момент, серьезно подумываю о ее реализации и, если окажется, что в официальном RoadMap’е wxAUI планов по созданию данного функционала нет, то можно будет попробовать его реализовать вручную, благо там привязка к GUI минимальна.
Итак, начнем:
AUIDocViewMainFrame.h
#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
#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;
}
}
}
[/sourcecode]
<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
#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;
}

Как видно, мы создали окно, содержащее строку меню, строку состояния и плавающую панель «Help Window». Плавающая панель может бать спрятана или отображена с помощью пункта меню «Toggle Help Window»
Теперь можно приступить к созданию дочерних окон.
AUIDocViewChildFrame.h
#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
#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
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().
Вот так будет выглядеть наше приложение после внесения всех изменений.
А вот как наше приложение будет выглядеть в Liunx
Но это еще не все. Существует интересная возможность смены интерфейса закладок в wxAuiNotebook. Для этого используются классы, производные от wxAuiTabArt (о них я расскажу как-нибудь позже). В нашем приложении мы будем использовать классы wxAuiDefaultTabArt и wxAuiSimpleTabArt, которые доступны в стандартной поставке wxAUI.
К сожалению, класс wxAuiTabArt не является потомком wxObject и для него недоступен RTTI, что не дает возможности определить, какой скин установлен в данный момент. Поэтому для определения активного скина заведем дополнительный enum HeaderStyle.
Ну что же, пора вносить новые изменения в исходный код:
AUIDocViewMainFrame.h
#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
#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, необходимые для того, чтобы маркер активного скина корректно отображался в меню.
После всего сделанного, мы должны получить вот приблизительно такой результат.
Но и это еще не всё. Интересной особенностью является также возможность использования плавающих панелей внутри каждого дочернего окна. В этом случае докинг будет осуществляться только внутри дочернего окна.
Для демонстрации этих возможностей изменим немного класс дочернего окна и создадим производный от него класс, который будет частично наследовать уже существующий функционал, а также будет предоставлять возможность размещения плавающих панелей.
AUIDocViewChildFrame.h
#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
#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
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);
...
}
Теперь у нас должно получиться что-то типа этого:

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

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



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