]> git.saurik.com Git - wxWidgets.git/commitdiff
refactor WM_COMMAND messages handling in MDI frames to avoid duplicating code unneces...
authorVadim Zeitlin <vadim@wxwidgets.org>
Tue, 27 Jan 2009 16:47:41 +0000 (16:47 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Tue, 27 Jan 2009 16:47:41 +0000 (16:47 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58462 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/doxygen/mainpages/const_stdevtid.h
include/wx/defs.h
include/wx/msw/frame.h
include/wx/msw/mdi.h
interface/wx/mdi.h
samples/mdi/mdi.cpp
samples/mdi/mdi.h
src/msw/frame.cpp
src/msw/mdi.cpp

index f43140ed2d496b8735273d738e53374d8c36b1d4..37923c9d40650eb316c0f969786ac3bf3d8649ed 100644 (file)
@@ -144,6 +144,16 @@ wxID_MAXIMIZE_FRAME,
 wxID_ICONIZE_FRAME,
 wxID_RESTORE_FRAME,
 
+// MDI window menu ids
+wxID_MDI_WINDOW_FIRST = 5230,
+wxID_MDI_WINDOW_CASCADE = wxID_MDI_WINDOW_FIRST,
+wxID_MDI_WINDOW_TILE_HORZ,
+wxID_MDI_WINDOW_TILE_VERT,
+wxID_MDI_WINDOW_ARRANGE_ICONS,
+wxID_MDI_WINDOW_PREV,
+wxID_MDI_WINDOW_NEXT,
+wxID_MDI_WINDOW_LAST = wxID_MDI_WINDOW_NEXT,
+
 // IDs used by generic file dialog (13 consecutive starting from this value)
 wxID_FILEDLGG = 5900,
 
index e179b9ff8b9f4e3d9c6e86bf0a71c3b4d4d2764c..df2cedf59cdd9fc936817e300b60e4ff99ba5bbe 100644 (file)
@@ -2002,6 +2002,16 @@ enum
     wxID_ICONIZE_FRAME,
     wxID_RESTORE_FRAME,
 
+    /* MDI window menu ids */
+    wxID_MDI_WINDOW_FIRST = 5230,
+    wxID_MDI_WINDOW_CASCADE = wxID_MDI_WINDOW_FIRST,
+    wxID_MDI_WINDOW_TILE_HORZ,
+    wxID_MDI_WINDOW_TILE_VERT,
+    wxID_MDI_WINDOW_ARRANGE_ICONS,
+    wxID_MDI_WINDOW_PREV,
+    wxID_MDI_WINDOW_NEXT,
+    wxID_MDI_WINDOW_LAST = wxID_MDI_WINDOW_NEXT,
+
     /*  IDs used by generic file dialog (13 consecutive starting from this value) */
     wxID_FILEDLGG = 5900,
 
index 348853262afa6d1e77e50492601fe583cb4ce8bd..e43cc2247e3ad6e5679b4c6da4bf298de5a92bd1 100644 (file)
@@ -107,6 +107,9 @@ public:
     // get the currently active menu: this is the same as the frame menu for
     // normal frames but is overridden by wxMDIParentFrame
     virtual WXHMENU MSWGetActiveMenu() const { return m_hMenu; }
+
+    // find the item in our menu bar: this is again a hook for MDI frames
+    virtual wxMenuItem *MSWFindMenuBarItem(WXWORD id);
 #endif // wxUSE_MENUS
 
 protected:
index 9c2389e9a6f482ffc59871f79a414fdeb6fce540..127cc968ba617792656e6d979943f3db88bbe225 100644 (file)
@@ -15,6 +15,8 @@
 
 #include "wx/frame.h"
 
+class WXDLLIMPEXP_FWD_CORE wxAcceleratorTable;
+
 // ---------------------------------------------------------------------------
 // wxMDIParentFrame
 // ---------------------------------------------------------------------------
@@ -22,7 +24,7 @@
 class WXDLLIMPEXP_CORE wxMDIParentFrame : public wxMDIParentFrameBase
 {
 public:
-    wxMDIParentFrame();
+    wxMDIParentFrame() { }
     wxMDIParentFrame(wxWindow *parent,
                      wxWindowID id,
                      const wxString& title,
@@ -103,6 +105,7 @@ public:
 #if wxUSE_MENUS
     // override wxFrameBase function to also look in the active child menu bar
     virtual const wxMenuItem *FindItemInMenuBar(int menuId) const;
+    virtual wxMenuItem *MSWFindMenuBarItem(WXWORD id);
 #endif // wxUSE_MENUS
 
 protected:
@@ -115,12 +118,13 @@ protected:
     // set the size of the MDI client window to match the frame size
     void UpdateClientSize();
 
-
-    // true if MDI Frame is intercepting commands, not child
-    bool m_parentFrameActive;
-
 private:
 #if wxUSE_MENUS
+    // "Window" menu commands event handlers
+    void OnMDICommand(wxCommandEvent& event);
+    void OnMDIChild(wxCommandEvent& event);
+
+
     // add/remove window menu if we have it (i.e. m_windowMenu != NULL)
     void AddWindowMenu();
     void RemoveWindowMenu();
@@ -128,6 +132,10 @@ private:
     // update the window menu (if we have it) to enable or disable the commands
     // which only make sense when we have more than one child
     void UpdateWindowMenu(bool enable);
+
+#if wxUSE_ACCEL
+    wxAcceleratorTable *m_accelWindowMenu;
+#endif // wxUSE_ACCEL
 #endif // wxUSE_MENUS
 
     // return the number of child frames we currently have (maybe 0)
@@ -187,7 +195,6 @@ public:
     // Handlers
     bool HandleMDIActivate(long bActivate, WXHWND, WXHWND);
     bool HandleWindowPosChanging(void *lpPos);
-    bool HandleCommand(WXWORD id, WXWORD cmd, WXHWND control);
     bool HandleGetMinMaxInfo(void *mmInfo);
 
     virtual WXLRESULT MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam);
index 83627cd2c3f1a40977c53838fe7c76bcb127a3c5..052f612ff374dbd256c43e37498c8b34fa8112ce 100644 (file)
@@ -310,6 +310,17 @@ public:
         window style but this function also allows to do it by passing @NULL
         pointer as @a menu.
 
+        The menu may include the items with the following standard identifiers
+        (but may use arbitrary text and help strings and bitmaps for them):
+            - @c wxID_MDI_WINDOW_CASCADE
+            - @c wxID_MDI_WINDOW_TILE_HORZ
+            - @c wxID_MDI_WINDOW_TILE_VERT
+            - @c wxID_MDI_WINDOW_ARRANGE_ICONS
+            - @c wxID_MDI_WINDOW_PREV
+            - @c wxID_MDI_WINDOW_NEXT
+        All of which are handled by wxMDIParentFrame itself. If any other
+        commands are used in the menu, the derived frame should handle them.
+
         This function is currently not available under OS X.
 
         @param menu
index 3c8e263f8970d7162101cda3299c2c665d9d9661..e4b581a2c42a6882c79b13dc8c047d1c57c0b65b 100644 (file)
@@ -69,6 +69,8 @@ BEGIN_EVENT_TABLE(MyFrame, wxMDIParentFrame)
     EVT_MENU(MDI_FULLSCREEN, MyFrame::OnFullScreen)
     EVT_MENU(wxID_EXIT, MyFrame::OnQuit)
 
+    EVT_MENU(wxID_CLOSE_ALL, MyFrame::OnCloseAll)
+
     EVT_CLOSE(MyFrame::OnClose)
 END_EVENT_TABLE()
 
@@ -150,12 +152,33 @@ MyFrame::MyFrame()
     // Associate the menu bar with the frame
     SetMenuBar(menu_bar);
 
-#if 0
-    // Experimental: change the window menu
-    wxMenu* windowMenu = new wxMenu;
-    windowMenu->Append(5000, "My menu item!");
-    frame->SetWindowMenu(windowMenu);
-#endif
+
+    // This shows that the standard window menu may be customized:
+    wxMenu * const windowMenu = GetWindowMenu();
+    if ( windowMenu )
+    {
+        // we can change the labels of standard items (which also means we can
+        // set up accelerators for them as they're part of the label)
+        windowMenu->SetLabel(wxID_MDI_WINDOW_TILE_HORZ,
+                             "&Tile horizontally\tCtrl-Shift-H");
+        windowMenu->SetLabel(wxID_MDI_WINDOW_TILE_VERT,
+                             "&Tile vertically\tCtrl-Shift-V");
+
+        // we can also change the help string
+        windowMenu->SetHelpString(wxID_MDI_WINDOW_CASCADE,
+                                  "Arrange windows in cascade");
+
+        // we can remove some items
+        windowMenu->Delete(wxID_MDI_WINDOW_ARRANGE_ICONS);
+
+        // and we can add completely custom commands -- but then we must handle
+        // them ourselves, see OnCloseAll()
+        windowMenu->AppendSeparator();
+        windowMenu->Append(wxID_CLOSE_ALL, "&Close all windows\tCtrl-Shift-C",
+                           "Close all open windows");
+
+        SetWindowMenu(windowMenu);
+    }
 #endif // wxUSE_MENUS
 
 #if wxUSE_STATUSBAR
@@ -236,6 +259,17 @@ void MyFrame::OnFullScreen(wxCommandEvent& event)
     ShowFullScreen(event.IsChecked());
 }
 
+void MyFrame::OnCloseAll(wxCommandEvent& WXUNUSED(event))
+{
+    for ( wxWindowList::const_iterator i = GetChildren().begin();
+          i != GetChildren().end();
+          ++i )
+    {
+        if ( wxDynamicCast(*i, wxMDIChildFrame) )
+            (*i)->Close();
+    }
+}
+
 void MyFrame::OnSize(wxSizeEvent& event)
 {
     int w, h;
index 48f18dbf58a6446b3cacb2f5f60603e56c81a11a..550ee6720ea6d449a507a4cda175b8570932933c 100644 (file)
@@ -53,6 +53,8 @@ private:
     void OnNewWindow(wxCommandEvent& event);
     void OnFullScreen(wxCommandEvent& event);
     void OnQuit(wxCommandEvent& event);
+    void OnCloseAll(wxCommandEvent& event);
+
     void OnClose(wxCloseEvent& event);
 
     wxTextCtrl *m_textWindow;
index 15c9e2bb59bf6f010d7cfa5c7379608abe1923e0..774e99e27bb09a991b96fd25e388a3a28616f363 100644 (file)
@@ -890,8 +890,9 @@ bool wxFrame::HandleSize(int WXUNUSED(x), int WXUNUSED(y), WXUINT id)
     return false;
 }
 
-bool wxFrame::HandleCommand(WXWORD id_, WXWORD cmd, WXHWND control)
+bool wxFrame::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control)
 {
+#if wxUSE_MENUS
     // we only need to handle the menu and accelerator commands from the items
     // of our menu bar, base wxWindow class already handles the rest
     if ( !control && (cmd == 0 /* menu */ || cmd == 1 /* accel */) )
@@ -900,25 +901,24 @@ bool wxFrame::HandleCommand(WXWORD id_, WXWORD cmd, WXHWND control)
         if ( !wxCurrentPopupMenu )
 #endif // wxUSE_MENUS_NATIVE
         {
-            wxMenuBar * const mbar = GetMenuBar();
-            if ( mbar )
-            {
-                // sign extend to int from short before comparing with the
-                // other int ids
-                const int id = (signed short)id_;
-
-                wxMenuItem * const mitem = mbar->FindItem(id);
-                if ( mitem )
-                    return ProcessCommand(mitem);
-            }
+            wxMenuItem * const mitem = MSWFindMenuBarItem(id);
+            if ( mitem )
+                return ProcessCommand(mitem);
         }
     }
+#endif // wxUSE_MENUS
 
-    return wxFrameBase::HandleCommand(id_, cmd, control);;
+    return wxFrameBase::HandleCommand(id, cmd, control);;
 }
 
 #if wxUSE_MENUS
 
+wxMenuItem *wxFrame::MSWFindMenuBarItem(WXWORD id)
+{
+    wxMenuBar * const mbar = GetMenuBar();
+    return mbar ? mbar->FindItem((signed short)id) : NULL;
+}
+
 bool wxFrame::HandleMenuSelect(WXWORD nItem, WXWORD flags, WXHMENU hMenu)
 {
     int item;
index 6f579ee9a75c0fdd3547e58dbbe31c87df076dcd..2d6109b3db36ed209e034581874dfb6c8ca587f9 100644 (file)
@@ -59,13 +59,6 @@ extern void wxRemoveHandleAssociation(wxWindow *win);
 // constants
 // ---------------------------------------------------------------------------
 
-static const int IDM_WINDOWTILEHOR  = 4001;
-static const int IDM_WINDOWCASCADE = 4002;
-static const int IDM_WINDOWICONS = 4003;
-static const int IDM_WINDOWNEXT = 4004;
-static const int IDM_WINDOWTILEVERT = 4005;
-static const int IDM_WINDOWPREV = 4006;
-
 // This range gives a maximum of 500 MDI children. Should be enough :-)
 static const int wxFIRST_MDI_CHILD = 4100;
 static const int wxLAST_MDI_CHILD = 4600;
@@ -85,12 +78,6 @@ static void MDIInsertWindowMenu(wxWindow *win, WXHMENU menu, HMENU subMenu);
 // Remove the window menu
 static void MDIRemoveWindowMenu(wxWindow *win, WXHMENU menu);
 
-// is this an id of an MDI child?
-inline bool IsMdiCommandId(int id)
-{
-    return (id >= wxFIRST_MDI_CHILD) && (id <= wxLAST_MDI_CHILD);
-}
-
 // unpack the parameters of WM_MDIACTIVATE message
 static void UnpackMDIActivate(WXWPARAM wParam, WXLPARAM lParam,
                               WXWORD *activate, WXHWND *hwndAct, WXHWND *hwndDeact);
@@ -121,6 +108,13 @@ BEGIN_EVENT_TABLE(wxMDIParentFrame, wxFrame)
     EVT_SIZE(wxMDIParentFrame::OnSize)
     EVT_ICONIZE(wxMDIParentFrame::OnIconized)
     EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged)
+
+#if wxUSE_MENUS
+    EVT_MENU_RANGE(wxFIRST_MDI_CHILD, wxLAST_MDI_CHILD,
+                   wxMDIParentFrame::OnMDIChild)
+    EVT_MENU_RANGE(wxID_MDI_WINDOW_FIRST, wxID_MDI_WINDOW_LAST,
+                   wxMDIParentFrame::OnMDICommand)
+#endif // wxUSE_MENUS
 END_EVENT_TABLE()
 
 BEGIN_EVENT_TABLE(wxMDIChildFrame, wxFrame)
@@ -136,11 +130,6 @@ END_EVENT_TABLE()
 // the children
 // ===========================================================================
 
-wxMDIParentFrame::wxMDIParentFrame()
-{
-    m_parentFrameActive = true;
-}
-
 bool wxMDIParentFrame::Create(wxWindow *parent,
                               wxWindowID id,
                               const wxString& title,
@@ -156,16 +145,19 @@ bool wxMDIParentFrame::Create(wxWindow *parent,
       // normal case: we have the window menu, so construct it
       m_windowMenu = new wxMenu;
 
-      m_windowMenu->Append(IDM_WINDOWCASCADE, _("&Cascade"));
-      m_windowMenu->Append(IDM_WINDOWTILEHOR, _("Tile &Horizontally"));
-      m_windowMenu->Append(IDM_WINDOWTILEVERT, _("Tile &Vertically"));
+      m_windowMenu->Append(wxID_MDI_WINDOW_CASCADE, _("&Cascade"));
+      m_windowMenu->Append(wxID_MDI_WINDOW_TILE_HORZ, _("Tile &Horizontally"));
+      m_windowMenu->Append(wxID_MDI_WINDOW_TILE_VERT, _("Tile &Vertically"));
       m_windowMenu->AppendSeparator();
-      m_windowMenu->Append(IDM_WINDOWICONS, _("&Arrange Icons"));
-      m_windowMenu->Append(IDM_WINDOWNEXT, _("&Next"));
-      m_windowMenu->Append(IDM_WINDOWPREV, _("&Previous"));
+      m_windowMenu->Append(wxID_MDI_WINDOW_ARRANGE_ICONS, _("&Arrange Icons"));
+      m_windowMenu->Append(wxID_MDI_WINDOW_NEXT, _("&Next"));
+      m_windowMenu->Append(wxID_MDI_WINDOW_PREV, _("&Previous"));
   }
 
-  m_parentFrameActive = true;
+#if wxUSE_MENUS && wxUSE_ACCEL
+  // the default menu doesn't have any accelerators (even if we have it)
+  m_accelWindowMenu = NULL;
+#endif // wxUSE_MENUS && wxUSE_ACCEL
 
   if (!parent)
     wxTopLevelWindows.Append(this);
@@ -213,6 +205,10 @@ wxMDIParentFrame::~wxMDIParentFrame()
     m_frameStatusBar = NULL;
 #endif // wxUSE_STATUSBAR
 
+#if wxUSE_MENUS && wxUSE_ACCEL
+    delete m_accelWindowMenu;
+#endif // wxUSE_MENUS && wxUSE_ACCEL
+
     DestroyChildren();
 
     // the MDI frame menubar is not automatically deleted by Windows unlike for
@@ -238,10 +234,10 @@ wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const
 {
     HWND hWnd = (HWND)::SendMessage(GetWinHwnd(GetClientWindow()),
                                     WM_MDIGETACTIVE, 0, 0L);
-    if ( hWnd == 0 )
+    if ( !hWnd )
         return NULL;
 
-    return (wxMDIChildFrame *)wxFindWinFromHandle(hWnd);
+    return static_cast<wxMDIChildFrame *>(wxFindWinFromHandle(hWnd));
 }
 
 int wxMDIParentFrame::GetChildFramesCount() const
@@ -323,8 +319,8 @@ void wxMDIParentFrame::UpdateWindowMenu(bool enable)
 {
     if ( m_windowMenu )
     {
-        m_windowMenu->Enable(IDM_WINDOWNEXT, enable);
-        m_windowMenu->Enable(IDM_WINDOWPREV, enable);
+        m_windowMenu->Enable(wxID_MDI_WINDOW_NEXT, enable);
+        m_windowMenu->Enable(wxID_MDI_WINDOW_PREV, enable);
     }
 }
 
@@ -332,8 +328,6 @@ void wxMDIParentFrame::UpdateWindowMenu(bool enable)
 
 void wxMDIParentFrame::InternalSetMenuBar()
 {
-    m_parentFrameActive = true;
-
     if ( GetActiveChild() )
     {
         AddWindowMenu();
@@ -350,15 +344,26 @@ void wxMDIParentFrame::InternalSetMenuBar()
 
 void wxMDIParentFrame::SetWindowMenu(wxMenu* menu)
 {
-    // notice that Remove/AddWindowMenu() are safe to call even when
-    // m_windowMenu is NULL
-    RemoveWindowMenu();
+    if ( menu != m_windowMenu )
+    {
+        // notice that Remove/AddWindowMenu() are safe to call even when
+        // m_windowMenu is NULL
+        RemoveWindowMenu();
+
+        delete m_windowMenu;
+
+        m_windowMenu = menu;
 
-    delete m_windowMenu;
+        AddWindowMenu();
+    }
 
-    m_windowMenu = menu;
+#if wxUSE_ACCEL
+    delete m_accelWindowMenu;
+    m_accelWindowMenu = NULL;
 
-    AddWindowMenu();
+    if ( menu && menu->HasAccels() )
+        m_accelWindowMenu = menu->CreateAccelTable();
+#endif // wxUSE_ACCEL
 }
 
 // ----------------------------------------------------------------------------
@@ -396,9 +401,9 @@ void wxMDIParentFrame::DoMenuUpdates(wxMenu* menu)
 const wxMenuItem *wxMDIParentFrame::FindItemInMenuBar(int menuId) const
 {
     const wxMenuItem *item = wxFrame::FindItemInMenuBar(menuId);
-    if ( !item && m_currentChild )
+    if ( !item && GetActiveChild() )
     {
-        item = m_currentChild->FindItemInMenuBar(menuId);
+        item = GetActiveChild()->FindItemInMenuBar(menuId);
     }
 
     return item;
@@ -587,128 +592,107 @@ bool wxMDIParentFrame::HandleActivate(int state, bool minimized, WXHWND activate
 
     // If this window is an MDI parent, we must also send an OnActivate message
     // to the current child.
-    if ( (m_currentChild != NULL) &&
+    if ( GetActiveChild() &&
          ((state == WA_ACTIVE) || (state == WA_CLICKACTIVE)) )
     {
-        wxActivateEvent event(wxEVT_ACTIVATE, true, m_currentChild->GetId());
-        event.SetEventObject( m_currentChild );
-        if ( m_currentChild->HandleWindowEvent(event) )
+        wxActivateEvent event(wxEVT_ACTIVATE, true, GetActiveChild()->GetId());
+        event.SetEventObject( GetActiveChild() );
+        if ( GetActiveChild()->HandleWindowEvent(event) )
             processed = true;
     }
 
     return processed;
 }
 
-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_;
+#if wxUSE_MENUS
 
-    // In case it's e.g. a toolbar.
-    if ( hwnd )
+void wxMDIParentFrame::OnMDIChild(wxCommandEvent& event)
+{
+    wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+    while ( node )
     {
-        wxWindow *win = wxFindWinFromHandle(hwnd);
-        if ( win )
-            return win->MSWCommand(cmd, id);
-    }
+        wxWindow *child = node->GetData();
+        if ( child->GetHWND() )
+        {
+            int childId = wxGetWindowId(child->GetHWND());
+            if ( childId == event.GetId() )
+            {
+                ::SendMessage( GetWinHwnd(GetClientWindow()),
+                        WM_MDIACTIVATE,
+                        (WPARAM)child->GetHWND(), 0);
+                return;
+            }
+        }
 
-    if (wxCurrentPopupMenu)
-    {
-        wxMenu *popupMenu = wxCurrentPopupMenu;
-        wxCurrentPopupMenu = NULL;
-        if (popupMenu->MSWCommand(cmd, id))
-            return true;
+        node = node->GetNext();
     }
 
-    // is it one of standard MDI commands?
+    wxFAIL_MSG( "unknown MDI child selected?" );
+}
+
+void wxMDIParentFrame::OnMDICommand(wxCommandEvent& event)
+{
     WXWPARAM wParam = 0;
     WXLPARAM lParam = 0;
     int msg;
-    switch ( id )
+    switch ( event.GetId() )
     {
-        case IDM_WINDOWCASCADE:
+        case wxID_MDI_WINDOW_CASCADE:
             msg = WM_MDICASCADE;
             wParam = MDITILE_SKIPDISABLED;
             break;
 
-        case IDM_WINDOWTILEHOR:
+        case wxID_MDI_WINDOW_TILE_HORZ:
             wParam |= MDITILE_HORIZONTAL;
             // fall through
 
-        case IDM_WINDOWTILEVERT:
+        case wxID_MDI_WINDOW_TILE_VERT:
             if ( !wParam )
                 wParam = MDITILE_VERTICAL;
             msg = WM_MDITILE;
             wParam |= MDITILE_SKIPDISABLED;
             break;
 
-        case IDM_WINDOWICONS:
+        case wxID_MDI_WINDOW_ARRANGE_ICONS:
             msg = WM_MDIICONARRANGE;
             break;
 
-        case IDM_WINDOWNEXT:
+        case wxID_MDI_WINDOW_NEXT:
             msg = WM_MDINEXT;
             lParam = 0;         // next child
             break;
 
-        case IDM_WINDOWPREV:
+        case wxID_MDI_WINDOW_PREV:
             msg = WM_MDINEXT;
             lParam = 1;         // previous child
             break;
 
         default:
-            msg = 0;
+            wxFAIL_MSG( "unknown MDI command" );
+            return;
     }
 
-    if ( msg )
-    {
-        ::SendMessage(GetWinHwnd(GetClientWindow()), msg, wParam, lParam);
+    ::SendMessage(GetWinHwnd(GetClientWindow()), msg, wParam, lParam);
+}
 
-        return true;
-    }
+wxMenuItem *wxMDIParentFrame::MSWFindMenuBarItem(WXWORD id)
+{
+    wxMenuItem *mitem = wxFrame::MSWFindMenuBarItem(id);
+    if ( !mitem && m_windowMenu )
+        mitem = m_windowMenu->FindItem((signed short)id);
 
-    // FIXME VZ: what does this test do??
-    if (id >= 0xF000)
-    {
-        return false; // Get WndProc to call default proc
-    }
+    return mitem;
+}
 
-    if ( IsMdiCommandId(id) )
-    {
-        wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
-        while ( node )
-        {
-            wxWindow *child = node->GetData();
-            if ( child->GetHWND() )
-            {
-                int childId = wxGetWindowId(child->GetHWND());
-                if ( childId == (signed short)id )
-                {
-                    ::SendMessage( GetWinHwnd(GetClientWindow()),
-                                   WM_MDIACTIVATE,
-                                   (WPARAM)child->GetHWND(), 0);
-                    return true;
-                }
-            }
-            node = node->GetNext();
-        }
-    }
-    else if ( m_parentFrameActive )
-    {
-        return ProcessCommand(id);
-    }
-    else if ( m_currentChild )
-    {
-        return m_currentChild->HandleCommand(id, cmd, hwnd);
-    }
-    else
-    {
-        // this shouldn't happen because it means that our messages are being
-        // lost (they're not sent to the parent frame nor to the children)
-        wxFAIL_MSG(wxT("MDI parent frame is not active, yet there is no active MDI child?"));
-    }
+#endif // wxUSE_MENUS
 
-    return false;
+bool wxMDIParentFrame::HandleCommand(WXWORD id, WXWORD cmd, WXHWND hwnd)
+{
+    wxMDIChildFrame * const child = GetActiveChild();
+    if ( child && child->HandleCommand(id, cmd, hwnd) )
+        return true;
+
+    return wxFrame::HandleCommand(id, cmd, hwnd);
 }
 
 WXLRESULT wxMDIParentFrame::MSWDefWindowProc(WXUINT message,
@@ -729,19 +713,28 @@ bool wxMDIParentFrame::MSWTranslateMessage(WXMSG* msg)
     MSG *pMsg = (MSG *)msg;
 
     // first let the current child get it
-    if ( m_currentChild && m_currentChild->GetHWND() &&
-         m_currentChild->MSWTranslateMessage(msg) )
+    wxMDIChildFrame * const child = GetActiveChild();
+    if ( child && child->MSWTranslateMessage(msg) )
     {
         return true;
     }
 
-    // then try out accel table (will also check the menu accels)
+    // then try out accelerator table (will also check the accelerators for the
+    // normal menu items)
     if ( wxFrame::MSWTranslateMessage(msg) )
     {
         return true;
     }
 
-    // finally, check for MDI specific built in accel keys
+#if wxUSE_MENUS && wxUSE_ACCEL
+    // but it doesn't check for the (custom) accelerators of the window menu
+    // items as it's not part of the menu bar as it's handled by Windows itself
+    // so we need to do this explicitly
+    if ( m_accelWindowMenu->Translate(this, msg) )
+        return true;
+#endif // wxUSE_MENUS && wxUSE_ACCEL
+
+    // finally, check for MDI specific built-in accelerators
     if ( pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN )
     {
         if ( ::TranslateMDISysAccel(GetWinHwnd(GetClientWindow()), pMsg))
@@ -985,8 +978,6 @@ void wxMDIChildFrame::InternalSetMenuBar()
 
     MDIInsertWindowMenu(parent->GetClientWindow(),
                      m_hMenu, GetMDIWindowMenu(parent));
-
-    parent->m_parentFrameActive = false;
 }
 
 void wxMDIChildFrame::DetachMenuBar()
@@ -1049,17 +1040,6 @@ WXLRESULT wxMDIChildFrame::MSWWindowProc(WXUINT message,
 
     switch ( message )
     {
-        case WM_COMMAND:
-            {
-                WORD id, cmd;
-                WXHWND hwnd;
-                UnpackCommand((WXWPARAM)wParam, (WXLPARAM)lParam,
-                              &id, &hwnd, &cmd);
-
-                processed = HandleCommand(id, cmd, (WXHWND)hwnd);
-            }
-            break;
-
         case WM_GETMINMAXINFO:
             processed = HandleGetMinMaxInfo((MINMAXINFO *)lParam);
             break;
@@ -1102,40 +1082,6 @@ WXLRESULT wxMDIChildFrame::MSWWindowProc(WXUINT message,
     return rc;
 }
 
-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 )
-    {
-        wxWindow *win = wxFindWinFromHandle(hwnd);
-        if (win)
-            return win->MSWCommand(cmd, id);
-    }
-
-    if (wxCurrentPopupMenu)
-    {
-        wxMenu *popupMenu = wxCurrentPopupMenu;
-        wxCurrentPopupMenu = NULL;
-        if (popupMenu->MSWCommand(cmd, id))
-            return true;
-    }
-
-    bool processed;
-    if (GetMenuBar() && GetMenuBar()->FindItem(id))
-    {
-        processed = ProcessCommand(id);
-    }
-    else
-    {
-        processed = false;
-    }
-
-    return processed;
-}
-
 bool wxMDIChildFrame::HandleMDIActivate(long WXUNUSED(activate),
                                         WXHWND hwndAct,
                                         WXHWND hwndDeact)
@@ -1149,34 +1095,26 @@ bool wxMDIChildFrame::HandleMDIActivate(long WXUNUSED(activate),
     if ( m_hWnd == hwndAct )
     {
         activated = true;
-        parent->m_currentChild = this;
+        parent->SetActiveChild(this);
 
         WXHMENU hMenuChild = m_hMenu;
         if ( hMenuChild )
-        {
-            parent->m_parentFrameActive = false;
-
             hMenuToSet = hMenuChild;
-        }
     }
     else if ( m_hWnd == hwndDeact )
     {
-        wxASSERT_MSG( parent->m_currentChild == this,
+        wxASSERT_MSG( parent->GetActiveChild() == this,
                       wxT("can't deactivate MDI child which wasn't active!") );
 
         activated = false;
-        parent->m_currentChild = NULL;
+        parent->SetActiveChild(NULL);
 
         WXHMENU hMenuParent = parent->m_hMenu;
 
         // activate the the parent menu only when there is no other child
         // that has been activated
         if ( hMenuParent && !hwndAct )
-        {
-            parent->m_parentFrameActive = true;
-
             hMenuToSet = hMenuParent;
-        }
     }
     else
     {