Использование возможностей библиотеки 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.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
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 ; } |
Как видно, мы создали окно, содержащее строку меню, строку состояния и плавающую панель «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().
Вот так будет выглядеть наше приложение после внесения всех изменений.
А вот как наше приложение будет выглядеть в Liunx
Но это еще не все. Существует интересная возможность смены интерфейса закладок в 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, необходимые для того, чтобы маркер активного скина корректно отображался в меню.
После всего сделанного, мы должны получить вот приблизительно такой результат.
Но и это еще не всё. Интересной особенностью является также возможность использования плавающих панелей внутри каждого дочернего окна. В этом случае докинг будет осуществляться только внутри дочернего окна.
Для демонстрации этих возможностей изменим немного класс дочернего окна и создадим производный от него класс, который будет частично наследовать уже существующий функционал, а также будет предоставлять возможность размещения плавающих панелей.
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); ... } |
Теперь у нас должно получиться что-то типа этого:
А вот как наше приложение будет выглядеть в 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
Возможно просто пофиксили баг с утечкой памяти для незадоченных окон и теперь этот кусок кода уже не нужен.