]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/mdi.cpp
added trivial wxLaunchDefaultApplication() implementation for wxMac; added a test...
[wxWidgets.git] / src / msw / mdi.cpp
index b0ec95a99dc42256e66ed35cd3cf56afd0518841..c854040c0529e03b1b964ca324e65a56cf6575fe 100644 (file)
 
 #if wxUSE_MDI && !defined(__WXUNIVERSAL__)
 
+#include "wx/mdi.h"
+
 #ifndef WX_PRECOMP
-    #include "wx/setup.h"
     #include "wx/frame.h"
     #include "wx/menu.h"
     #include "wx/app.h"
     #include "wx/utils.h"
     #include "wx/dialog.h"
-    #if wxUSE_STATUSBAR
-        #include "wx/statusbr.h"
-    #endif
+    #include "wx/statusbr.h"
     #include "wx/settings.h"
     #include "wx/intl.h"
     #include "wx/log.h"
+    #include "wx/toolbar.h"
 #endif
 
 #include "wx/stockitem.h"
-#include "wx/mdi.h"
 #include "wx/msw/private.h"
 
-#if wxUSE_STATUSBAR && wxUSE_NATIVE_STATUSBAR
-    #include "wx/msw/statbr95.h"
-#endif
-
-#if wxUSE_TOOLBAR
-    #include "wx/toolbar.h"
-#endif // wxUSE_TOOLBAR
-
 #include <string.h>
 
 // ---------------------------------------------------------------------------
@@ -64,11 +55,8 @@ extern wxMenu *wxCurrentPopupMenu;
 extern const wxChar *wxMDIFrameClassName;   // from app.cpp
 extern const wxChar *wxMDIChildFrameClassName;
 extern const wxChar *wxMDIChildFrameClassNameNoRedraw;
-extern void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win);
 extern void wxRemoveHandleAssociation(wxWindow *win);
 
-static HWND invalidHandle = 0;
-
 // ---------------------------------------------------------------------------
 // constants
 // ---------------------------------------------------------------------------
@@ -207,7 +195,7 @@ bool wxMDIParentFrame::Create(wxWindow *parent,
   msflags &= ~WS_HSCROLL;
 
   if ( !wxWindow::MSWCreate(wxMDIFrameClassName,
-                            title,
+                            title.wx_str(),
                             pos, size,
                             msflags,
                             exflags) )
@@ -215,6 +203,8 @@ bool wxMDIParentFrame::Create(wxWindow *parent,
       return false;
   }
 
+  SetOwnBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
+
   // unlike (almost?) all other windows, frames are created hidden
   m_isShown = false;
 
@@ -321,6 +311,17 @@ void wxMDIParentFrame::DoMenuUpdates(wxMenu* menu)
     }
 }
 
+const wxMenuItem *wxMDIParentFrame::FindItemInMenuBar(int menuId) const
+{
+    const wxMenuItem *item = wxFrame::FindItemInMenuBar(menuId);
+    if ( !item && m_currentChild )
+    {
+        item = m_currentChild->FindItemInMenuBar(menuId);
+    }
+
+    return item;
+}
+
 void wxMDIParentFrame::UpdateClientSize()
 {
     if ( GetClientWindow() )
@@ -343,10 +344,8 @@ void wxMDIParentFrame::OnIconized(wxIconizeEvent& event)
 {
     event.Skip();
 
-    if ( !event.Iconized() )
-    {
+    if ( !event.IsIconized() )
         UpdateClientSize();
-    }
 }
 
 // Returns the active MDI child window
@@ -481,24 +480,6 @@ WXLRESULT wxMDIParentFrame::MSWWindowProc(WXUINT message,
             rc = true;
             break;
 
-        case WM_MENUSELECT:
-            {
-                WXWORD item, flags;
-                WXHMENU hmenu;
-                UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu);
-
-                if ( m_parentFrameActive )
-                {
-                    processed = HandleMenuSelect(item, flags, hmenu);
-                }
-                else if (m_currentChild)
-                {
-                    processed = m_currentChild->
-                        HandleMenuSelect(item, flags, hmenu);
-                }
-            }
-            break;
-
         case WM_SIZE:
             // though we don't (usually) resize the MDI client to exactly fit the
             // client area we need to pass this one to DefFrameProc to allow the children to show
@@ -528,15 +509,18 @@ bool wxMDIParentFrame::HandleActivate(int state, bool minimized, WXHWND activate
     {
         wxActivateEvent event(wxEVT_ACTIVATE, true, m_currentChild->GetId());
         event.SetEventObject( m_currentChild );
-        if ( m_currentChild->GetEventHandler()->ProcessEvent(event) )
+        if ( m_currentChild->HandleWindowEvent(event) )
             processed = true;
     }
 
     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 )
     {
@@ -545,6 +529,14 @@ bool wxMDIParentFrame::HandleCommand(WXWORD id, WXWORD cmd, WXHWND hwnd)
             return win->MSWCommand(cmd, id);
     }
 
+    if (wxCurrentPopupMenu)
+    {
+        wxMenu *popupMenu = wxCurrentPopupMenu;
+        wxCurrentPopupMenu = NULL;
+        if (popupMenu->MSWCommand(cmd, id))
+            return true;
+    }
+
     // is it one of standard MDI commands?
     WXWPARAM wParam = 0;
     WXLPARAM lParam = 0;
@@ -606,8 +598,8 @@ bool wxMDIParentFrame::HandleCommand(WXWORD id, WXWORD cmd, WXHWND hwnd)
             wxWindow *child = node->GetData();
             if ( child->GetHWND() )
             {
-                long childId = wxGetWindowId(child->GetHWND());
-                if (childId == (long)id)
+                int childId = wxGetWindowId(child->GetHWND());
+                if ( childId == (signed short)id )
                 {
                     ::SendMessage( GetWinHwnd(GetClientWindow()),
                                    WM_MDIACTIVATE,
@@ -699,7 +691,7 @@ bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
   if ( id != wxID_ANY )
     m_windowId = id;
   else
-    m_windowId = (int)NewControlId();
+    m_windowId = NewControlId();
 
   if ( parent )
   {
@@ -716,7 +708,7 @@ bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
   mcs.szClass = style & wxFULL_REPAINT_ON_RESIZE
                     ? wxMDIChildFrameClassName
                     : wxMDIChildFrameClassNameNoRedraw;
-  mcs.szTitle = title;
+  mcs.szTitle = title.wx_str();
   mcs.hOwner = wxGetInstance();
   if (x != wxDefaultCoord)
       mcs.x = x;
@@ -743,7 +735,7 @@ bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
     msflags |= WS_MINIMIZEBOX;
   if (style & wxMAXIMIZE_BOX)
     msflags |= WS_MAXIMIZEBOX;
-  if (style & wxTHICK_FRAME)
+  if (style & wxRESIZE_BORDER)
     msflags |= WS_THICKFRAME;
   if (style & wxSYSTEM_MENU)
     msflags |= WS_SYSMENU;
@@ -761,15 +753,25 @@ bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
   wxWindowCreationHook hook(this);
 
   m_hWnd = (WXHWND)::SendMessage(GetWinHwnd(parent->GetClientWindow()),
-                                 WM_MDICREATE, 0, (LONG)(LPSTR)&mcs);
+                                 WM_MDICREATE, 0, (LPARAM)&mcs);
 
-  wxAssociateWinWithHandle((HWND) GetHWND(), this);
+  if ( !m_hWnd )
+  {
+      wxLogLastError(_T("WM_MDICREATE"));
+      return false;
+  }
+
+  SubclassWin(m_hWnd);
 
   return true;
 }
 
 wxMDIChildFrame::~wxMDIChildFrame()
 {
+    // if we hadn't been created, there is nothing to destroy
+    if ( !m_hWnd )
+        return;
+
     // 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
@@ -799,6 +801,11 @@ bool wxMDIChildFrame::Show(bool show)
     if ( show )
         ::BringWindowToTop(GetHwnd());
 
+    // we need to refresh the MDI frame window menu to include (or exclude if
+    // we've been hidden) this frame
+    wxMDIParentFrame *parent = GetMDIParent();
+    MDISetMenu(parent->GetClientWindow(), NULL, NULL);
+
     return true;
 }
 
@@ -835,7 +842,7 @@ void wxMDIChildFrame::DoSetClientSize(int width, int height)
 
   // If there's an MDI parent, must subtract the parent's top left corner
   // since MoveWindow moves relative to the parent
-  wxMDIParentFrame *mdiParent = (wxMDIParentFrame *)GetParent();
+  wxMDIParentFrame *mdiParent = GetMDIParent();
   ::ScreenToClient((HWND) mdiParent->GetClientWindow()->GetHWND(), &point);
 
   MoveWindow(hWnd, point.x, point.y, actual_width, actual_height, (BOOL)true);
@@ -843,9 +850,24 @@ void wxMDIChildFrame::DoSetClientSize(int width, int height)
   wxSize size(width, height);
   wxSizeEvent event(size, m_windowId);
   event.SetEventObject( this );
-  GetEventHandler()->ProcessEvent(event);
+  HandleWindowEvent(event);
+}
+
+// Unlike other wxTopLevelWindowBase, the mdi child's "GetPosition" is not the
+//  same as its GetScreenPosition
+void wxMDIChildFrame::DoGetScreenPosition(int *x, int *y) const
+{
+  HWND hWnd = GetHwnd();
+
+  RECT rect;
+  ::GetWindowRect(hWnd, &rect);
+  if (x)
+     *x = rect.left;
+  if (y)
+     *y = rect.top;
 }
 
+
 void wxMDIChildFrame::DoGetPosition(int *x, int *y) const
 {
   RECT rect;
@@ -856,7 +878,7 @@ void wxMDIChildFrame::DoGetPosition(int *x, int *y) const
 
   // Since we now have the absolute screen coords,
   // if there's a parent we must subtract its top left corner
-  wxMDIParentFrame *mdiParent = (wxMDIParentFrame *)GetParent();
+  wxMDIParentFrame *mdiParent = GetMDIParent();
   ::ScreenToClient((HWND) mdiParent->GetClientWindow()->GetHWND(), &point);
 
   if (x)
@@ -867,7 +889,7 @@ void wxMDIChildFrame::DoGetPosition(int *x, int *y) const
 
 void wxMDIChildFrame::InternalSetMenuBar()
 {
-    wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
+    wxMDIParentFrame *parent = GetMDIParent();
 
     InsertWindowMenu(parent->GetClientWindow(),
                      m_hMenu, GetMDIWindowMenu(parent));
@@ -893,7 +915,7 @@ WXHICON wxMDIChildFrame::GetDefaultIcon() const
 
 void wxMDIChildFrame::Maximize(bool maximize)
 {
-    wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
+    wxMDIParentFrame *parent = GetMDIParent();
     if ( parent && parent->GetClientWindow() )
     {
         ::SendMessage(GetWinHwnd(parent->GetClientWindow()),
@@ -904,7 +926,7 @@ void wxMDIChildFrame::Maximize(bool maximize)
 
 void wxMDIChildFrame::Restore()
 {
-    wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
+    wxMDIParentFrame *parent = GetMDIParent();
     if ( parent && parent->GetClientWindow() )
     {
         ::SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDIRESTORE,
@@ -914,7 +936,7 @@ void wxMDIChildFrame::Restore()
 
 void wxMDIChildFrame::Activate()
 {
-    wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
+    wxMDIParentFrame *parent = GetMDIParent();
     if ( parent && parent->GetClientWindow() )
     {
         ::SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDIACTIVATE,
@@ -988,8 +1010,11 @@ WXLRESULT wxMDIChildFrame::MSWWindowProc(WXUINT message,
     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 )
     {
@@ -1023,7 +1048,7 @@ bool wxMDIChildFrame::HandleMDIActivate(long WXUNUSED(activate),
                                         WXHWND hwndAct,
                                         WXHWND hwndDeact)
 {
-    wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
+    wxMDIParentFrame *parent = GetMDIParent();
 
     HMENU menuToSet = 0;
 
@@ -1078,13 +1103,13 @@ bool wxMDIChildFrame::HandleMDIActivate(long WXUNUSED(activate),
 
     ResetWindowStyle((void *)NULL);
 
-    return GetEventHandler()->ProcessEvent(event);
+    return HandleWindowEvent(event);
 }
 
 bool wxMDIChildFrame::HandleWindowPosChanging(void *pos)
 {
     WINDOWPOS *lpPos = (WINDOWPOS *)pos;
-#if defined(__WIN95__)
+
     if (!(lpPos->flags & SWP_NOSIZE))
     {
         RECT rectClient;
@@ -1098,15 +1123,7 @@ bool wxMDIChildFrame::HandleWindowPosChanging(void *pos)
             lpPos->cx = rectClient.right - rectClient.left;
             lpPos->cy = rectClient.bottom - rectClient.top;
         }
-#if wxUSE_TOOLBAR
-        wxMDIParentFrame* pFrameWnd = (wxMDIParentFrame *)GetParent();
-        if (pFrameWnd && pFrameWnd->GetToolBar() && pFrameWnd->GetToolBar()->IsShown())
-        {
-            pFrameWnd->GetToolBar()->Refresh();
-        }
-#endif
     }
-#endif // Win95
 
     return false;
 }
@@ -1124,14 +1141,14 @@ bool wxMDIChildFrame::HandleGetMinMaxInfo(void *mmInfo)
         minHeight = GetMinHeight();
 
     // but allow GetSizeHints() to set the min size
-    if ( minWidth != -1 )
+    if ( minWidth != wxDefaultCoord )
     {
         info->ptMinTrackSize.x = minWidth;
 
         processed = true;
     }
 
-    if ( minHeight != -1 )
+    if ( minHeight != wxDefaultCoord )
     {
         info->ptMinTrackSize.y = minHeight;
 
@@ -1153,7 +1170,9 @@ WXLRESULT wxMDIChildFrame::MSWDefWindowProc(WXUINT message, WXWPARAM wParam, WXL
 
 bool wxMDIChildFrame::MSWTranslateMessage(WXMSG* msg)
 {
-    return wxFrame::MSWTranslateMessage(msg);
+    // we must pass the parent frame to ::TranslateAccelerator(), otherwise it
+    // doesn't do its job correctly for MDI child menus
+    return MSWDoTranslateMessage(GetMDIParent(), msg);
 }
 
 // ---------------------------------------------------------------------------
@@ -1162,9 +1181,7 @@ bool wxMDIChildFrame::MSWTranslateMessage(WXMSG* msg)
 
 void wxMDIChildFrame::MSWDestroyWindow()
 {
-    invalidHandle = GetHwnd();
-
-    wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
+    wxMDIParentFrame *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
@@ -1177,8 +1194,6 @@ void wxMDIChildFrame::MSWDestroyWindow()
     if (parent->GetActiveChild() == (wxMDIChildFrame*) NULL)
         ResetWindowStyle((void*) NULL);
 
-    invalidHandle = 0;
-
     if (m_hMenu)
     {
         ::DestroyMenu((HMENU) m_hMenu);
@@ -1192,10 +1207,10 @@ void wxMDIChildFrame::MSWDestroyWindow()
 // style when a child is maximised (a double border looks silly.)
 bool wxMDIChildFrame::ResetWindowStyle(void *vrect)
 {
-#if defined(__WIN95__)
     RECT *rect = (RECT *)vrect;
-    wxMDIParentFrame* pFrameWnd = (wxMDIParentFrame *)GetParent();
+    wxMDIParentFrame* pFrameWnd = GetMDIParent();
     wxMDIChildFrame* pChild = pFrameWnd->GetActiveChild();
+
     if (!pChild || (pChild == this))
     {
         HWND hwndClient = GetWinHwnd(pFrameWnd->GetClientWindow());
@@ -1227,7 +1242,6 @@ bool wxMDIChildFrame::ResetWindowStyle(void *vrect)
             return true;
         }
     }
-#endif // Win95
 
     return false;
 }
@@ -1256,11 +1270,7 @@ bool wxMDIClientWindow::CreateClient(wxMDIParentFrame *parent, long style)
     if ( style & wxVSCROLL )
         msStyle |= WS_VSCROLL;
 
-#if defined(__WIN95__)
     DWORD exStyle = WS_EX_CLIENTEDGE;
-#else
-    DWORD exStyle = 0;
-#endif
 
     wxWindowCreationHook hook(this);
     m_hWnd = (WXHWND)::CreateWindowEx
@@ -1371,13 +1381,20 @@ void wxMDIChildFrame::OnIdle(wxIdleEvent& event)
 
 static void MDISetMenu(wxWindow *win, HMENU hmenuFrame, HMENU hmenuWindow)
 {
-    ::SendMessage(GetWinHwnd(win), WM_MDISETMENU,
-#ifdef __WIN32__
-                  (WPARAM)hmenuFrame, (LPARAM)hmenuWindow
-#else
-                  0, MAKELPARAM(hmenuFrame, hmenuWindow)
-#endif
-                 );
+    if ( hmenuFrame || hmenuWindow )
+    {
+        if ( !::SendMessage(GetWinHwnd(win),
+                            WM_MDISETMENU,
+                            (WPARAM)hmenuFrame,
+                            (LPARAM)hmenuWindow) )
+        {
+#ifdef __WXDEBUG__
+            DWORD err = ::GetLastError();
+            if ( err )
+                wxLogApiError(_T("SendMessage(WM_MDISETMENU)"), err);
+#endif // __WXDEBUG__
+        }
+    }
 
     // update menu bar of the parent window
     wxWindow *parent = win->GetParent();
@@ -1413,14 +1430,15 @@ static void InsertWindowMenu(wxWindow *win, WXHMENU menu, HMENU subMenu)
             {
                 success = true;
                 ::InsertMenu(hmenu, i, MF_BYPOSITION | MF_POPUP | MF_STRING,
-                             (UINT)subMenu, _("&Window"));
+                             (UINT_PTR)subMenu, _("&Window").wx_str());
                 break;
             }
         }
 
         if ( !success )
         {
-            ::AppendMenu(hmenu, MF_POPUP, (UINT)subMenu, _("&Window"));
+            ::AppendMenu(hmenu, MF_POPUP,
+                         (UINT_PTR)subMenu, _("&Window").wx_str());
         }
     }
 
@@ -1478,4 +1496,3 @@ static void UnpackMDIActivate(WXWPARAM wParam, WXLPARAM lParam,
 }
 
 #endif // wxUSE_MDI && !defined(__WXUNIVERSAL__)
-