Использование возможностей библиотеки 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
Возможно просто пофиксили баг с утечкой памяти для незадоченных окон и теперь этот кусок кода уже не нужен.