extern wxMenu *wxCurrentPopupMenu;
-extern const wxChar *wxMDIFrameClassName; // from app.cpp
-extern const wxChar *wxMDIChildFrameClassName;
-extern const wxChar *wxMDIChildFrameClassNameNoRedraw;
extern void wxRemoveHandleAssociation(wxWindow *win);
// ---------------------------------------------------------------------------
// 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();
wxMDIParentFrame::wxMDIParentFrame()
{
- m_clientWindow = NULL;
- m_currentChild = NULL;
- m_windowMenu = (wxMenu*) NULL;
m_parentFrameActive = true;
}
long style,
const wxString& name)
{
- m_clientWindow = NULL;
- m_currentChild = NULL;
-
// this style can be used to prevent a window from having the standard MDI
// "Window" menu
- if ( style & wxFRAME_NO_WINDOW_MENU )
- {
- m_windowMenu = (wxMenu *)NULL;
- }
- else // normal case: we have the window menu, so construct it
+ if ( !(style & wxFRAME_NO_WINDOW_MENU) )
{
+ // normal case: we have the window menu, so construct it
m_windowMenu = new wxMenu;
m_windowMenu->Append(IDM_WINDOWCASCADE, _("&Cascade"));
msflags &= ~WS_VSCROLL;
msflags &= ~WS_HSCROLL;
- if ( !wxWindow::MSWCreate(wxMDIFrameClassName,
+ if ( !wxWindow::MSWCreate(wxApp::GetRegisteredClassName(_T("wxMDIFrame")),
title.wx_str(),
pos, size,
msflags,
DestroyChildren();
- if (m_windowMenu)
- {
- delete m_windowMenu;
- m_windowMenu = (wxMenu*) NULL;
- }
-
// 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
void wxMDIParentFrame::SetWindowMenu(wxMenu* menu)
{
- if (m_windowMenu)
- {
- if (GetMenuBar())
- {
- // Remove old window menu
- RemoveWindowMenu(GetClientWindow(), m_hMenu);
- }
+ // notice that Remove/AddWindowMenu() are safe to call even when
+ // m_windowMenu is NULL
+ RemoveWindowMenu();
- delete m_windowMenu;
- m_windowMenu = (wxMenu*) NULL;
- }
+ delete m_windowMenu;
- if (menu)
- {
- m_windowMenu = menu;
- if (GetMenuBar())
- {
- InsertWindowMenu(GetClientWindow(), m_hMenu,
- GetHmenuOf(m_windowMenu));
- }
- }
+ m_windowMenu = menu;
+
+ AddWindowMenu();
}
void wxMDIParentFrame::DoMenuUpdates(wxMenu* menu)
{
event.Skip();
- if ( !event.Iconized() )
- {
+ if ( !event.IsIconized() )
UpdateClientSize();
- }
}
// Returns the active MDI child window
WM_MDIGETACTIVE, 0, 0L);
if ( hWnd == 0 )
return NULL;
- else
- return (wxMDIChildFrame *)wxFindWinFromHandle((WXHWND) hWnd);
-}
-// Create the client window class (don't Create the window, just return a new
-// class)
-wxMDIClientWindow *wxMDIParentFrame::OnCreateClient()
-{
- return new wxMDIClientWindow;
+ return (wxMDIChildFrame *)wxFindWinFromHandle(hWnd);
}
// Responds to colour changes, and passes event on to children.
return processed;
}
-bool wxMDIParentFrame::HandleCommand(WXWORD id, WXWORD cmd, WXHWND hwnd)
+bool wxMDIParentFrame::HandleCommand(WXWORD id_, WXWORD cmd, WXHWND hwnd)
{
+ // sign extend to int from short before comparing with the other int ids
+ int id = (signed short)id_;
+
// In case it's e.g. a toolbar.
if ( hwnd )
{
long style,
const wxString& name)
{
+ m_mdiParent = parent;
+
SetName(name);
if ( id != wxID_ANY )
MDICREATESTRUCT mcs;
- mcs.szClass = style & wxFULL_REPAINT_ON_RESIZE
- ? wxMDIChildFrameClassName
- : wxMDIChildFrameClassNameNoRedraw;
+ wxString className =
+ wxApp::GetRegisteredClassName(_T("wxMDIChildFrame"), COLOR_WINDOW);
+ if ( !(style & wxFULL_REPAINT_ON_RESIZE) )
+ className += wxApp::GetNoRedrawClassSuffix();
+
+ mcs.szClass = className.wx_str();
mcs.szTitle = title.wx_str();
mcs.hOwner = wxGetInstance();
if (x != wxDefaultCoord)
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();
}
// we need to refresh the MDI frame window menu to include (or exclude if
// we've been hidden) this frame
- wxMDIParentFrame *parent = GetMDIParent();
+ wxMDIParentFrame * const parent = GetMDIParent();
MDISetMenu(parent->GetClientWindow(), NULL, NULL);
return true;
// If there's an MDI parent, must subtract the parent's top left corner
// since MoveWindow moves relative to the parent
- wxMDIParentFrame *mdiParent = GetMDIParent();
- ::ScreenToClient((HWND) mdiParent->GetClientWindow()->GetHWND(), &point);
+ wxMDIParentFrame * const mdiParent = GetMDIParent();
+ ::ScreenToClient(GetHwndOf(mdiParent->GetClientWindow()), &point);
MoveWindow(hWnd, point.x, point.y, actual_width, actual_height, (BOOL)true);
// Since we now have the absolute screen coords,
// if there's a parent we must subtract its top left corner
- wxMDIParentFrame *mdiParent = GetMDIParent();
- ::ScreenToClient((HWND) mdiParent->GetClientWindow()->GetHWND(), &point);
+ wxMDIParentFrame * const mdiParent = GetMDIParent();
+ ::ScreenToClient(GetHwndOf(mdiParent->GetClientWindow()), &point);
if (x)
*x = point.x;
void wxMDIChildFrame::InternalSetMenuBar()
{
- wxMDIParentFrame *parent = GetMDIParent();
+ wxMDIParentFrame * const 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();
}
void wxMDIChildFrame::Maximize(bool maximize)
{
- wxMDIParentFrame *parent = GetMDIParent();
+ wxMDIParentFrame * const parent = GetMDIParent();
if ( parent && parent->GetClientWindow() )
{
::SendMessage(GetWinHwnd(parent->GetClientWindow()),
void wxMDIChildFrame::Restore()
{
- wxMDIParentFrame *parent = GetMDIParent();
+ wxMDIParentFrame * const parent = GetMDIParent();
if ( parent && parent->GetClientWindow() )
{
::SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDIRESTORE,
void wxMDIChildFrame::Activate()
{
- wxMDIParentFrame *parent = GetMDIParent();
+ wxMDIParentFrame * const parent = GetMDIParent();
if ( parent && parent->GetClientWindow() )
{
::SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDIACTIVATE,
return rc;
}
-bool wxMDIChildFrame::HandleCommand(WXWORD id, WXWORD cmd, WXHWND hwnd)
+bool wxMDIChildFrame::HandleCommand(WXWORD id_, WXWORD cmd, WXHWND hwnd)
{
+ // sign extend to int from short before comparing with the other int ids
+ int id = (signed short)id_;
+
// In case it's e.g. a toolbar.
if ( hwnd )
{
WXHWND hwndAct,
WXHWND hwndDeact)
{
- wxMDIParentFrame *parent = GetMDIParent();
+ wxMDIParentFrame * const parent = GetMDIParent();
HMENU menuToSet = 0;
void wxMDIChildFrame::MSWDestroyWindow()
{
- wxMDIParentFrame *parent = GetMDIParent();
+ wxMDIParentFrame * const parent = GetMDIParent();
// Must make sure this handle is invalidated (set to NULL) since all sorts
// of things could happen after the child client is destroyed, but before
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)
{
bool wxMDIChildFrame::ResetWindowStyle(void *vrect)
{
RECT *rect = (RECT *)vrect;
- wxMDIParentFrame* pFrameWnd = GetMDIParent();
+ wxMDIParentFrame * const pFrameWnd = GetMDIParent();
wxMDIChildFrame* pChild = pFrameWnd->GetActiveChild();
if (!pChild || (pChild == this))
::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;