X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/598ddd96f45745188c96f16757f7ceeaa0c8d70d..e031f1df56a1595c7ebb4027eb89bf1c9f286bdf:/src/msw/mdi.cpp diff --git a/src/msw/mdi.cpp b/src/msw/mdi.cpp index b1d924d27d..5b7dd5e75e 100644 --- a/src/msw/mdi.cpp +++ b/src/msw/mdi.cpp @@ -17,10 +17,6 @@ // headers // --------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "mdi.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -31,7 +27,6 @@ #if wxUSE_MDI && !defined(__WXUNIVERSAL__) #ifndef WX_PRECOMP - #include "wx/setup.h" #include "wx/frame.h" #include "wx/menu.h" #include "wx/app.h" @@ -45,6 +40,7 @@ #include "wx/log.h" #endif +#include "wx/stockitem.h" #include "wx/mdi.h" #include "wx/msw/private.h" @@ -67,16 +63,12 @@ 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 // --------------------------------------------------------------------------- -static const int IDM_WINDOWTILE = 4001; static const int IDM_WINDOWTILEHOR = 4001; static const int IDM_WINDOWCASCADE = 4002; static const int IDM_WINDOWICONS = 4003; @@ -88,10 +80,6 @@ static const int IDM_WINDOWPREV = 4006; static const int wxFIRST_MDI_CHILD = 4100; static const int wxLAST_MDI_CHILD = 4600; -// Status border dimensions -static const int wxTHICK_LINE_BORDER = 3; -static const int wxTHICK_LINE_WIDTH = 1; - // --------------------------------------------------------------------------- // private functions // --------------------------------------------------------------------------- @@ -138,6 +126,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxWindow) BEGIN_EVENT_TABLE(wxMDIParentFrame, wxFrame) EVT_SIZE(wxMDIParentFrame::OnSize) + EVT_ICONIZE(wxMDIParentFrame::OnIconized) EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged) END_EVENT_TABLE() @@ -222,6 +211,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; @@ -300,7 +291,35 @@ void wxMDIParentFrame::SetWindowMenu(wxMenu* menu) } } -void wxMDIParentFrame::OnSize(wxSizeEvent&) +void wxMDIParentFrame::DoMenuUpdates(wxMenu* menu) +{ + wxMDIChildFrame *child = GetActiveChild(); + if ( child ) + { + wxEvtHandler* source = child->GetEventHandler(); + wxMenuBar* bar = child->GetMenuBar(); + + if (menu) + { + menu->UpdateUI(source); + } + else + { + if ( bar != NULL ) + { + int nCount = bar->GetMenuCount(); + for (int n = 0; n < nCount; n++) + bar->GetMenu(n)->UpdateUI(source); + } + } + } + else + { + wxFrameBase::DoMenuUpdates(menu); + } +} + +void wxMDIParentFrame::UpdateClientSize() { if ( GetClientWindow() ) { @@ -311,6 +330,23 @@ void wxMDIParentFrame::OnSize(wxSizeEvent&) } } +void wxMDIParentFrame::OnSize(wxSizeEvent& WXUNUSED(event)) +{ + UpdateClientSize(); + + // do not call event.Skip() here, it somehow messes up MDI client window +} + +void wxMDIParentFrame::OnIconized(wxIconizeEvent& event) +{ + event.Skip(); + + if ( !event.Iconized() ) + { + UpdateClientSize(); + } +} + // Returns the active MDI child window wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const { @@ -356,10 +392,14 @@ void wxMDIParentFrame::Cascade() ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDICASCADE, 0, 0); } -// TODO: add a direction argument (hor/vert) -void wxMDIParentFrame::Tile() +void wxMDIParentFrame::Tile(wxOrientation orient) { - ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDITILE, MDITILE_HORIZONTAL, 0); + wxASSERT_MSG( orient == wxHORIZONTAL || orient == wxVERTICAL, + _T("invalid orientation value") ); + + ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDITILE, + orient == wxHORIZONTAL ? MDITILE_HORIZONTAL + : MDITILE_VERTICAL, 0); } void wxMDIParentFrame::ArrangeIcons() @@ -458,9 +498,8 @@ WXLRESULT wxMDIParentFrame::MSWWindowProc(WXUINT message, break; case WM_SIZE: - // as we don't (usually) resize the MDI client to exactly fit the - // client area (we put it below the toolbar, above statusbar &c), - // we should not pass this one to DefFrameProc + // 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 break; } @@ -504,6 +543,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; @@ -642,6 +689,7 @@ bool wxMDIParentFrame::MSWTranslateMessage(WXMSG* msg) void wxMDIChildFrame::Init() { m_needsResize = true; + m_needsInitialShow = true; } bool wxMDIChildFrame::Create(wxMDIParentFrame *parent, @@ -653,7 +701,6 @@ bool wxMDIChildFrame::Create(wxMDIParentFrame *parent, const wxString& name) { SetName(name); - wxWindowBase::Show(true); // MDI child frame starts off shown if ( id != wxID_ANY ) m_windowId = id; @@ -697,12 +744,12 @@ bool wxMDIChildFrame::Create(wxMDIParentFrame *parent, else mcs.cy = CW_USEDEFAULT; - DWORD msflags = WS_OVERLAPPED | WS_CLIPCHILDREN | WS_VISIBLE ; + DWORD msflags = WS_OVERLAPPED | WS_CLIPCHILDREN; if (style & wxMINIMIZE_BOX) 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; @@ -722,7 +769,13 @@ bool wxMDIChildFrame::Create(wxMDIParentFrame *parent, m_hWnd = (WXHWND)::SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDICREATE, 0, (LONG)(LPSTR)&mcs); - wxAssociateWinWithHandle((HWND) GetHWND(), this); + if ( !m_hWnd ) + { + wxLogLastError(_T("WM_MDICREATE")); + return false; + } + + SubclassWin(m_hWnd); return true; } @@ -745,6 +798,27 @@ wxMDIChildFrame::~wxMDIChildFrame() MSWDestroyWindow(); } +bool wxMDIChildFrame::Show(bool show) +{ + m_needsInitialShow = false; + + if (!wxFrame::Show(show)) + return false; + + // KH: Without this call, new MDI children do not become active. + // This was added here after the same BringWindowToTop call was + // removed from wxTopLevelWindow::Show (November 2005) + 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 = (wxMDIParentFrame *)GetParent(); + MDISetMenu(parent->GetClientWindow(), NULL, NULL); + + return true; +} + // Set the client size (i.e. leave the calculation of borders etc. // to wxWidgets) void wxMDIChildFrame::DoSetClientSize(int width, int height) @@ -783,7 +857,8 @@ void wxMDIChildFrame::DoSetClientSize(int width, int height) MoveWindow(hWnd, point.x, point.y, actual_width, actual_height, (BOOL)true); - wxSizeEvent event(wxSize(width, height), m_windowId); + wxSize size(width, height); + wxSizeEvent event(size, m_windowId); event.SetEventObject( this ); GetEventHandler()->ProcessEvent(event); } @@ -801,8 +876,10 @@ void wxMDIChildFrame::DoGetPosition(int *x, int *y) const wxMDIParentFrame *mdiParent = (wxMDIParentFrame *)GetParent(); ::ScreenToClient((HWND) mdiParent->GetClientWindow()->GetHWND(), &point); - *x = point.x; - *y = point.y; + if (x) + *x = point.x; + if (y) + *y = point.y; } void wxMDIChildFrame::InternalSetMenuBar() @@ -815,6 +892,12 @@ void wxMDIChildFrame::InternalSetMenuBar() parent->m_parentFrameActive = false; } +void wxMDIChildFrame::DetachMenuBar() +{ + RemoveWindowMenu(NULL, m_hMenu); + wxFrame::DetachMenuBar(); +} + WXHICON wxMDIChildFrame::GetDefaultIcon() const { // we don't have any standard icons (any more) @@ -1018,7 +1101,7 @@ bool wxMDIChildFrame::HandleMDIActivate(long WXUNUSED(activate), bool wxMDIChildFrame::HandleWindowPosChanging(void *pos) { WINDOWPOS *lpPos = (WINDOWPOS *)pos; -#if defined(__WIN95__) + if (!(lpPos->flags & SWP_NOSIZE)) { RECT rectClient; @@ -1032,15 +1115,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; } @@ -1058,14 +1133,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; @@ -1087,7 +1162,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((wxMDIChildFrame *)GetParent(), msg); } // --------------------------------------------------------------------------- @@ -1096,8 +1173,6 @@ bool wxMDIChildFrame::MSWTranslateMessage(WXMSG* msg) void wxMDIChildFrame::MSWDestroyWindow() { - invalidHandle = GetHwnd(); - wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent(); // Must make sure this handle is invalidated (set to NULL) since all sorts @@ -1111,8 +1186,6 @@ void wxMDIChildFrame::MSWDestroyWindow() if (parent->GetActiveChild() == (wxMDIChildFrame*) NULL) ResetWindowStyle((void*) NULL); - invalidHandle = 0; - if (m_hMenu) { ::DestroyMenu((HMENU) m_hMenu); @@ -1126,10 +1199,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(); wxMDIChildFrame* pChild = pFrameWnd->GetActiveChild(); + if (!pChild || (pChild == this)) { HWND hwndClient = GetWinHwnd(pFrameWnd->GetClientWindow()); @@ -1161,7 +1234,6 @@ bool wxMDIChildFrame::ResetWindowStyle(void *vrect) return true; } } -#endif // Win95 return false; } @@ -1190,11 +1262,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 @@ -1244,11 +1312,11 @@ void wxMDIClientWindow::DoSetSize(int x, int y, int width, int height, int sizeF // (see OGL studio sample). So check if the position is changed and if so, // redraw the MDI child frames. - wxPoint oldPos = GetPosition(); + const wxPoint oldPos = GetPosition(); - wxWindow::DoSetSize(x, y, width, height, sizeFlags); + wxWindow::DoSetSize(x, y, width, height, sizeFlags | wxSIZE_FORCE); - wxPoint newPos = GetPosition(); + const wxPoint newPos = GetPosition(); if ((newPos.x != oldPos.x) || (newPos.y != oldPos.y)) { @@ -1275,6 +1343,16 @@ void wxMDIClientWindow::DoSetSize(int x, int y, int width, int height, int sizeF void wxMDIChildFrame::OnIdle(wxIdleEvent& event) { + // wxMSW prior to 2.5.3 created MDI child frames as visible, which resulted + // in flicker e.g. when the frame contained controls with non-trivial + // layout. Since 2.5.3, the frame is created hidden as all other top level + // windows. In order to maintain backward compatibility, the frame is shown + // in OnIdle, unless Show(false) was called by the programmer before. + if ( m_needsInitialShow ) + { + Show(true); + } + // MDI child frames get their WM_SIZE when they're constructed but at this // moment they don't have any children yet so all child windows will be // positioned incorrectly when they are added later - to fix this, we @@ -1295,13 +1373,16 @@ 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) ) + { + wxLogLastError(_T("SendMessage(WM_MDISETMENU)")); + } + } // update menu bar of the parent window wxWindow *parent = win->GetParent(); @@ -1332,7 +1413,8 @@ static void InsertWindowMenu(wxWindow *win, WXHMENU menu, HMENU subMenu) continue; } - if ( wxStripMenuCodes(wxString(buf)).IsSameAs(_("Help")) ) + wxString strBuf(buf); + if ( wxStripMenuCodes(strBuf) == wxGetStockLabel(wxID_HELP,false) ) { success = true; ::InsertMenu(hmenu, i, MF_BYPOSITION | MF_POPUP | MF_STRING, @@ -1401,4 +1483,3 @@ static void UnpackMDIActivate(WXWPARAM wParam, WXLPARAM lParam, } #endif // wxUSE_MDI && !defined(__WXUNIVERSAL__) -