// accessors
// ---------
- // Get the active MDI child window (Windows only)
+ // Get the active MDI child window
wxMDIChildFrame *GetActiveChild() const;
// Get the client window
// Create the client window class (don't Create the window,
// just return a new class)
- virtual wxMDIClientWindow *OnCreateClient(void);
+ virtual wxMDIClientWindow *OnCreateClient();
- // MDI windows menu
- wxMenu* GetWindowMenu() const { return m_windowMenu; }
+ // MDI windows menu functions
+ // --------------------------
+
+ // return the pointer to the current window menu or NULL if we don't have
+ // because of wxFRAME_NO_WINDOW_MENU style
+ wxMenu *GetWindowMenu() const { return m_windowMenu; }
+
+ // use the given menu instead of the default window menu
+ //
+ // menu can be NULL to disable the window menu completely
void SetWindowMenu(wxMenu* menu) ;
+
virtual void DoMenuUpdates(wxMenu* menu = NULL);
// MDI operations
virtual void ActivateNext();
virtual void ActivatePrevious();
+
+ // implementation only from now on
+
+ // MDI helpers
+ // -----------
+
+ // called by wxMDIChildFrame after it was successfully created
+ virtual void AddMDIChild(wxMDIChildFrame *child);
+
+ // called by wxMDIChildFrame just before it is destroyed
+ virtual void RemoveMDIChild(wxMDIChildFrame *child);
+
// handlers
// --------
wxMDIClientWindow * m_clientWindow;
wxMDIChildFrame * m_currentChild;
- wxMenu* m_windowMenu;
+
+ // the current window menu or NULL if we are not using it
+ wxMenu *m_windowMenu;
// true if MDI Frame is intercepting commands, not child
bool m_parentFrameActive;
private:
+ // add/remove window menu if we have it (i.e. m_windowMenu != NULL)
+ void AddWindowMenu();
+ void RemoveWindowMenu();
+
+ // return the number of child frames we currently have (maybe 0)
+ int GetChildFramesCount() const;
+
friend class WXDLLIMPEXP_FWD_CORE wxMDIChildFrame;
DECLARE_EVENT_TABLE()
// insert the window menu (subMenu) into menu just before "Help" submenu or at
// the very end if not found
-static void InsertWindowMenu(wxWindow *win, WXHMENU menu, HMENU subMenu);
+static void MDIInsertWindowMenu(wxWindow *win, WXHMENU menu, HMENU subMenu);
// Remove the window menu
-static void RemoveWindowMenu(wxWindow *win, WXHMENU menu);
+static void MDIRemoveWindowMenu(wxWindow *win, WXHMENU menu);
// is this an id of an MDI child?
inline bool IsMdiCommandId(int id)
WXWORD *activate, WXHWND *hwndAct, WXHWND *hwndDeact);
// return the HMENU of the MDI menu
+//
+// this function works correctly even when we don't have a window menu and just
+// returns 0 then
static inline HMENU GetMDIWindowMenu(wxMDIParentFrame *frame)
{
wxMenu *menu = frame->GetWindowMenu();
{
m_clientWindow = NULL;
m_currentChild = NULL;
- m_windowMenu = (wxMenu*) NULL;
+ m_windowMenu = NULL;
m_parentFrameActive = true;
}
// "Window" menu
if ( style & wxFRAME_NO_WINDOW_MENU )
{
- m_windowMenu = (wxMenu *)NULL;
+ m_windowMenu = NULL;
}
else // normal case: we have the window menu, so construct it
{
DestroyChildren();
- if (m_windowMenu)
- {
- delete m_windowMenu;
- m_windowMenu = (wxMenu*) NULL;
- }
+ delete m_windowMenu;
// the MDI frame menubar is not automatically deleted by Windows unlike for
// the normal frames
if ( m_hMenu )
- {
::DestroyMenu((HMENU)m_hMenu);
- m_hMenu = (WXHMENU)NULL;
- }
if ( m_clientWindow )
{
}
}
+// ----------------------------------------------------------------------------
+// wxMDIParentFrame child management
+// ----------------------------------------------------------------------------
+
+int wxMDIParentFrame::GetChildFramesCount() const
+{
+ int count = 0;
+ for ( wxWindowList::const_iterator i = GetChildren().begin();
+ i != GetChildren().end();
+ ++i )
+ {
+ if ( wxDynamicCast(*i, wxMDIChildFrame) )
+ count++;
+ }
+
+ return count;
+}
+
+void wxMDIParentFrame::AddMDIChild(wxMDIChildFrame * WXUNUSED(child))
+{
+ if ( GetChildFramesCount() == 1 )
+ {
+ // first MDI child added, we need to insert the window menu now if we
+ // have it
+ AddWindowMenu();
+ }
+}
+
+void wxMDIParentFrame::RemoveMDIChild(wxMDIChildFrame * WXUNUSED(child))
+{
+ if ( GetChildFramesCount() == 1 )
+ {
+ // last MDI child is being removed, remove the now unnecessary window
+ // menu too
+ RemoveWindowMenu();
+ }
+}
+
+// ----------------------------------------------------------------------------
+// wxMDIParentFrame window menu handling
+// ----------------------------------------------------------------------------
+
+void wxMDIParentFrame::AddWindowMenu()
+{
+ if ( m_windowMenu )
+ MDIInsertWindowMenu(GetClientWindow(), m_hMenu, GetMDIWindowMenu(this));
+}
+
+void wxMDIParentFrame::RemoveWindowMenu()
+{
+ if ( m_windowMenu )
+ MDIRemoveWindowMenu(GetClientWindow(), m_hMenu);
+}
+
#if wxUSE_MENUS_NATIVE
void wxMDIParentFrame::InternalSetMenuBar()
{
m_parentFrameActive = true;
- InsertWindowMenu(GetClientWindow(), m_hMenu, GetMDIWindowMenu(this));
+ if ( GetActiveChild() )
+ {
+ AddWindowMenu();
+ }
+ else // we don't have any MDI children yet
+ {
+ // wait until we do to add the window menu but do set the main menu for
+ // now (this is done by AddWindowMenu() as a side effect)
+ MDISetMenu(GetClientWindow(), (HMENU)m_hMenu, NULL);
+ }
}
#endif // wxUSE_MENUS_NATIVE
{
if (m_windowMenu)
{
- if (GetMenuBar())
- {
- // Remove old window menu
- RemoveWindowMenu(GetClientWindow(), m_hMenu);
- }
+ RemoveWindowMenu();
delete m_windowMenu;
- m_windowMenu = (wxMenu*) NULL;
+ m_windowMenu = NULL;
}
if (menu)
{
m_windowMenu = menu;
- if (GetMenuBar())
- {
- InsertWindowMenu(GetClientWindow(), m_hMenu,
- GetHmenuOf(m_windowMenu));
- }
+
+ AddWindowMenu();
}
}
WM_MDIGETACTIVE, 0, 0L);
if ( hWnd == 0 )
return NULL;
- else
- return (wxMDIChildFrame *)wxFindWinFromHandle((WXHWND) hWnd);
+
+ return (wxMDIChildFrame *)wxFindWinFromHandle(hWnd);
}
// Create the client window class (don't Create the window, just return a new
SubclassWin(m_hWnd);
+ parent->AddMDIChild(this);
+
return true;
}
if ( !m_hWnd )
return;
+ GetMDIParent()->RemoveMDIChild(this);
+
// will be destroyed by DestroyChildren() but reset them before calling it
// to avoid using dangling pointers if a callback comes in the meanwhile
#if wxUSE_TOOLBAR
DestroyChildren();
- RemoveWindowMenu(NULL, m_hMenu);
+ MDIRemoveWindowMenu(NULL, m_hMenu);
MSWDestroyWindow();
}
{
wxMDIParentFrame *parent = GetMDIParent();
- InsertWindowMenu(parent->GetClientWindow(),
+ MDIInsertWindowMenu(parent->GetClientWindow(),
m_hMenu, GetMDIWindowMenu(parent));
parent->m_parentFrameActive = false;
void wxMDIChildFrame::DetachMenuBar()
{
- RemoveWindowMenu(NULL, m_hMenu);
+ MDIRemoveWindowMenu(NULL, m_hMenu);
wxFrame::DetachMenuBar();
}
SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDIDESTROY,
(WPARAM)oldHandle, 0);
- if (parent->GetActiveChild() == (wxMDIChildFrame*) NULL)
- ResetWindowStyle((void*) NULL);
+ if (parent->GetActiveChild() == NULL)
+ ResetWindowStyle(NULL);
if (m_hMenu)
{
::DrawMenuBar(GetWinHwnd(parent));
}
-static void InsertWindowMenu(wxWindow *win, WXHMENU menu, HMENU subMenu)
+static void MDIInsertWindowMenu(wxWindow *win, WXHMENU menu, HMENU subMenu)
{
// Try to insert Window menu in front of Help, otherwise append it.
HMENU hmenu = (HMENU)menu;
MDISetMenu(win, hmenu, subMenu);
}
-static void RemoveWindowMenu(wxWindow *win, WXHMENU menu)
+static void MDIRemoveWindowMenu(wxWindow *win, WXHMENU menu)
{
HMENU hMenu = (HMENU)menu;