X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e702ff0f08a54622a6b0f1e2ec39537b082c3a8e..9abe166a3073d9e9ceb0110429a45adc6517d76f:/src/msw/frame.cpp diff --git a/src/msw/frame.cpp b/src/msw/frame.cpp index 4cfcc231d6..aded67d34f 100644 --- a/src/msw/frame.cpp +++ b/src/msw/frame.cpp @@ -35,18 +35,15 @@ #include "wx/statusbr.h" #include "wx/toolbar.h" #include "wx/menuitem.h" - -#ifdef LoadAccelerators -#undef LoadAccelerators -#endif +#include "wx/log.h" #if wxUSE_NATIVE_STATUSBAR #include #endif -extern wxList wxModelessWindows; +extern wxWindowList wxModelessWindows; extern wxList WXDLLEXPORT wxPendingDelete; -extern char wxFrameClassName[]; +extern wxChar wxFrameClassName[]; extern wxMenu *wxCurrentPopupMenu; #if !USE_SHARED_LIBRARY @@ -74,7 +71,6 @@ wxFrame::wxFrame() m_frameMenuBar = NULL; m_frameStatusBar = NULL; - m_windowParent = NULL; m_iconized = FALSE; } @@ -90,11 +86,7 @@ bool wxFrame::Create(wxWindow *parent, m_hwndToolTip = 0; #endif - if (!parent) - wxTopLevelWindows.Append(this); - SetName(name); -// m_modalShowing = FALSE; m_windowStyle = style; m_frameMenuBar = NULL; m_frameToolBar = NULL ; @@ -119,7 +111,15 @@ bool wxFrame::Create(wxWindow *parent, // we pass NULL as parent to MSWCreate because frames with parents behave // very strangely under Win95 shell - MSWCreate(m_windowId, NULL, wxFrameClassName, this, title, + // Alteration by JACS: keep normal Windows behaviour (float on top of parent) + // with this style. + if ((m_windowStyle & wxFRAME_FLOAT_ON_PARENT) == 0) + parent = NULL; + + if (!parent) + wxTopLevelWindows.Append(this); + + MSWCreate(m_windowId, parent, wxFrameClassName, this, title, x, y, width, height, style); wxModelessWindows.Append(this); @@ -154,20 +154,18 @@ wxFrame::~wxFrame() // For some reason, wxWindows can activate another task altogether // when a frame is destroyed after a modal dialog has been invoked. // Try to bring the parent to the top. + // MT:Only do this if this frame is currently the active window, else weird + // things start to happen + if ( wxGetActiveWindow() == this ) if (GetParent() && GetParent()->GetHWND()) ::BringWindowToTop((HWND) GetParent()->GetHWND()); } -WXHMENU wxFrame::GetWinMenu() const -{ - return m_hMenu; -} - // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc. -void wxFrame::GetClientSize(int *x, int *y) const +void wxFrame::DoGetClientSize(int *x, int *y) const { RECT rect; - ::GetClientRect((HWND) GetHWND(), &rect); + ::GetClientRect(GetHwnd(), &rect); if ( GetStatusBar() ) { @@ -180,15 +178,17 @@ void wxFrame::GetClientSize(int *x, int *y) const rect.bottom -= pt.y; rect.right -= pt.x; - *x = rect.right; - *y = rect.bottom; + if ( x ) + *x = rect.right; + if ( y ) + *y = rect.bottom; } // Set the client size (i.e. leave the calculation of borders etc. // to wxWindows) void wxFrame::DoSetClientSize(int width, int height) { - HWND hWnd = (HWND) GetHWND(); + HWND hWnd = GetHwnd(); RECT rect; ::GetClientRect(hWnd, &rect); @@ -224,18 +224,18 @@ void wxFrame::DoSetClientSize(int width, int height) GetEventHandler()->ProcessEvent(event); } -void wxFrame::GetSize(int *width, int *height) const +void wxFrame::DoGetSize(int *width, int *height) const { RECT rect; - GetWindowRect((HWND) GetHWND(), &rect); + GetWindowRect(GetHwnd(), &rect); *width = rect.right - rect.left; *height = rect.bottom - rect.top; } -void wxFrame::GetPosition(int *x, int *y) const +void wxFrame::DoGetPosition(int *x, int *y) const { RECT rect; - GetWindowRect((HWND) GetHWND(), &rect); + GetWindowRect(GetHwnd(), &rect); POINT point; point.x = rect.left; point.y = rect.top; @@ -244,32 +244,6 @@ void wxFrame::GetPosition(int *x, int *y) const *y = point.y; } -void wxFrame::DoSetSize(int x, int y, int width, int height, int sizeFlags) -{ - int currentX, currentY; - int x1 = x; - int y1 = y; - int w1 = width; - int h1 = height; - - GetPosition(¤tX, ¤tY); - if (x == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) - x1 = currentX; - if (y == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) - y1 = currentY; - - int ww,hh ; - GetSize(&ww,&hh) ; - if (width == -1) w1 = ww ; - if (height==-1) h1 = hh ; - - MoveWindow((HWND) GetHWND(), x1, y1, w1, h1, (BOOL)TRUE); - - wxSizeEvent event(wxSize(width, height), m_windowId); - event.SetEventObject( this ); - GetEventHandler()->ProcessEvent(event); -} - bool wxFrame::Show(bool show) { int cshow; @@ -290,10 +264,10 @@ bool wxFrame::Show(bool show) } } - ShowWindow((HWND) GetHWND(), (BOOL)cshow); + ShowWindow(GetHwnd(), (BOOL)cshow); if (show) { - BringWindowToTop((HWND) GetHWND()); + BringWindowToTop(GetHwnd()); wxActivateEvent event(wxEVT_ACTIVATE, TRUE, m_windowId); event.SetEventObject( this ); @@ -312,7 +286,7 @@ void wxFrame::Iconize(bool iconize) cshow = SW_MINIMIZE; else cshow = SW_RESTORE; - ShowWindow((HWND) GetHWND(), (BOOL)cshow); + ShowWindow(GetHwnd(), (BOOL)cshow); m_iconized = iconize; } @@ -325,31 +299,20 @@ void wxFrame::Maximize(bool maximize) cshow = SW_MAXIMIZE; else cshow = SW_RESTORE; - ShowWindow((HWND) GetHWND(), cshow); + ShowWindow(GetHwnd(), cshow); m_iconized = FALSE; } bool wxFrame::IsIconized() const { - ((wxFrame *)this)->m_iconized = (::IsIconic((HWND) GetHWND()) != 0); + ((wxFrame *)this)->m_iconized = (::IsIconic(GetHwnd()) != 0); return m_iconized; } // Is it maximized? bool wxFrame::IsMaximized() const { - return (::IsZoomed((HWND) GetHWND()) != 0) ; -} - -void wxFrame::SetTitle(const wxString& title) -{ - SetWindowText((HWND) GetHWND(), (const char *)title); -} - -wxString wxFrame::GetTitle() const -{ - GetWindowText((HWND) GetHWND(), wxBuffer, 1000); - return wxString(wxBuffer); + return (::IsZoomed(GetHwnd()) != 0) ; } void wxFrame::SetIcon(const wxIcon& icon) @@ -357,11 +320,12 @@ void wxFrame::SetIcon(const wxIcon& icon) m_icon = icon; #if defined(__WIN95__) if ( m_icon.Ok() ) - SendMessage((HWND) GetHWND(), WM_SETICON, + SendMessage(GetHwnd(), WM_SETICON, (WPARAM)TRUE, (LPARAM)(HICON) m_icon.GetHICON()); #endif } +#if wxUSE_STATUSBAR wxStatusBar *wxFrame::OnCreateStatusBar(int number, long style, wxWindowID id, const wxString& name) { @@ -399,7 +363,7 @@ wxStatusBar* wxFrame::CreateStatusBar(int number, long style, wxWindowID id, { // VZ: calling CreateStatusBar twice is an error - why anyone would do it? wxCHECK_MSG( m_frameStatusBar == NULL, FALSE, - "recreating status bar in wxFrame" ); + wxT("recreating status bar in wxFrame") ); m_frameStatusBar = OnCreateStatusBar(number, style, id, name); @@ -414,14 +378,14 @@ wxStatusBar* wxFrame::CreateStatusBar(int number, long style, wxWindowID id, void wxFrame::SetStatusText(const wxString& text, int number) { - wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set text for" ); + wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set text for") ); m_frameStatusBar->SetStatusText(text, number); } void wxFrame::SetStatusWidths(int n, const int widths_field[]) { - wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set widths for" ); + wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set widths for") ); m_frameStatusBar->SetStatusWidths(n, widths_field); PositionStatusBar(); @@ -446,16 +410,26 @@ void wxFrame::PositionStatusBar() m_frameStatusBar->SetSize(0, h, w, sh); } } +#endif // wxUSE_STATUSBAR + +void wxFrame::DetachMenuBar() +{ + if (m_frameMenuBar) + { + m_frameMenuBar->Detach(); + m_frameMenuBar = NULL; + } +} void wxFrame::SetMenuBar(wxMenuBar *menu_bar) { if (!menu_bar) { - m_frameMenuBar = NULL; + DetachMenuBar(); return; } - wxCHECK_RET( !menu_bar->GetFrame(), "this menubar is already attached" ); + wxCHECK_RET( !menu_bar->GetFrame(), wxT("this menubar is already attached") ); if (m_frameMenuBar) delete m_frameMenuBar; @@ -465,64 +439,18 @@ void wxFrame::SetMenuBar(wxMenuBar *menu_bar) if ( !m_hMenu ) return; - if ( !::SetMenu((HWND)GetHWND(), (HMENU)m_hMenu) ) - { - wxLogLastError("SetMenu"); - } + InternalSetMenuBar(); m_frameMenuBar = menu_bar; menu_bar->Attach(this); } -#if 0 -bool wxFrame::LoadAccelerators(const wxString& table) -{ - m_acceleratorTable = (WXHANDLE) -#ifdef __WIN32__ -#ifdef UNICODE - ::LoadAcceleratorsW(wxGetInstance(), (const char *)table); -#else - ::LoadAcceleratorsA(wxGetInstance(), (const char *)table); -#endif -#else - ::LoadAccelerators(wxGetInstance(), (const char *)table); -#endif - - // The above is necessary because LoadAccelerators is a macro - // which we have undefed earlier in the file to avoid confusion - // with wxFrame::LoadAccelerators. Ugh! - - return (m_acceleratorTable != (WXHANDLE) NULL); -} -#endif - -void wxFrame::Fit() +void wxFrame::InternalSetMenuBar() { - // Work out max. size - wxNode *node = GetChildren().First(); - int max_width = 0; - int max_height = 0; - while (node) - { - // Find a child that's a subwindow, but not a dialog box. - wxWindow *win = (wxWindow *)node->Data(); - - if (!win->IsKindOf(CLASSINFO(wxFrame)) && - !win->IsKindOf(CLASSINFO(wxDialog))) + if ( !::SetMenu(GetHwnd(), (HMENU)m_hMenu) ) { - int width, height; - int x, y; - win->GetSize(&width, &height); - win->GetPosition(&x, &y); - - if ((x + width) > max_width) - max_width = x + width; - if ((y + height) > max_height) - max_height = y + height; + wxLogLastError("SetMenu"); } - node = node->Next(); - } - SetClientSize(max_width, max_height); } // Responds to colour changes, and passes event on to children. @@ -547,7 +475,7 @@ void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event) * */ -void wxFrame::MSWCreate(int id, wxWindow *parent, const char *wclass, wxWindow *wx_win, const char *title, +bool wxFrame::MSWCreate(int id, wxWindow *parent, const wxChar *wclass, wxWindow *wx_win, const wxChar *title, int x, int y, int width, int height, long style) { @@ -606,244 +534,98 @@ void wxFrame::MSWCreate(int id, wxWindow *parent, const char *wclass, wxWindow * extendedStyle |= WS_EX_TOPMOST; m_iconized = FALSE; - wxWindow::MSWCreate(id, parent, wclass, wx_win, title, x, y, width, height, - msflags, NULL, extendedStyle); + if ( !wxWindow::MSWCreate(id, parent, wclass, wx_win, title, x, y, width, height, + msflags, NULL, extendedStyle) ) + return FALSE; + // Seems to be necessary if we use WS_POPUP // style instead of WS_OVERLAPPED if (width > -1 && height > -1) - ::PostMessage((HWND) GetHWND(), WM_SIZE, SIZE_RESTORED, MAKELPARAM(width, height)); -} - -bool wxFrame::MSWOnPaint() -{ - RECT rect; - if (GetUpdateRect((HWND) GetHWND(), &rect, FALSE)) - { - if (m_iconized) - { - HICON the_icon; - if (m_icon.Ok()) - the_icon = (HICON) m_icon.GetHICON(); - else - the_icon = (HICON) m_defaultIcon; - - PAINTSTRUCT ps; - // Hold a pointer to the dc so long as the OnPaint() message - // is being processed - HDC cdc = BeginPaint((HWND) GetHWND(), &ps); - - // Erase background before painting or we get white background - this->MSWDefWindowProc(WM_ICONERASEBKGND,(WORD)(LONG) ps.hdc,0L); - - if (the_icon) - { - RECT rect; - ::GetClientRect((HWND) GetHWND(), &rect); - int icon_width = 32; - int icon_height = 32; - int icon_x = (int)((rect.right - icon_width)/2); - int icon_y = (int)((rect.bottom - icon_height)/2); - DrawIcon(cdc, icon_x, icon_y, the_icon); - } + ::PostMessage(GetHwnd(), WM_SIZE, SIZE_RESTORED, MAKELPARAM(width, height)); - EndPaint((HWND) GetHWND(), &ps); - } - else - { - wxPaintEvent event(m_windowId); - event.m_eventObject = this; - if (!GetEventHandler()->ProcessEvent(event)) - Default(); - } - return 0; - } - return 1; -} - -WXHICON wxFrame::MSWOnQueryDragIcon() -{ - if (m_icon.Ok() && (m_icon.GetHICON() != 0)) - return m_icon.GetHICON(); - else - return m_defaultIcon; -} - -void wxFrame::MSWOnSize(int x, int y, WXUINT id) -{ - switch (id) - { - case SIZENORMAL: - // only do it it if we were iconized before, otherwise resizing the - // parent frame has a curious side effect of bringing it under it's - // children - if ( !m_iconized ) - break; - - // restore all child frames too - IconizeChildFrames(FALSE); - - // fall through - - case SIZEFULLSCREEN: - m_iconized = FALSE; - break; - - case SIZEICONIC: - // iconize all child frames too - IconizeChildFrames(TRUE); - - m_iconized = TRUE; - break; - } - - if (!m_iconized) - { - // forward WM_SIZE to status bar control -#if wxUSE_NATIVE_STATUSBAR - if (m_frameStatusBar && m_frameStatusBar->IsKindOf(CLASSINFO(wxStatusBar95))) - { - wxSizeEvent event(wxSize(x, y), m_frameStatusBar->GetId()); - event.SetEventObject( m_frameStatusBar ); - - ((wxStatusBar95 *)m_frameStatusBar)->OnSize(event); - } -#endif - - PositionStatusBar(); - PositionToolBar(); - - wxSizeEvent event(wxSize(x, y), m_windowId); - event.SetEventObject( this ); - if (!GetEventHandler()->ProcessEvent(event)) - Default(); - } -} - -bool wxFrame::MSWOnClose() -{ - return Close(); + return TRUE; } -bool wxFrame::MSWOnCommand(WXWORD id, WXWORD cmd, WXHWND control) +// Default resizing behaviour - if only ONE subwindow, resize to client +// rectangle size +void wxFrame::OnSize(wxSizeEvent& event) { - if (cmd == 0 || cmd == 1 ) // Can be either a menu command or an accelerator. - { - // In case it's e.g. a toolbar. - wxWindow *win = wxFindWinFromHandle(control); - if (win) - return win->MSWCommand(cmd, id); - - if (wxCurrentPopupMenu) + // if we're using constraints - do use them +#if wxUSE_CONSTRAINTS + if ( GetAutoLayout() ) { - wxMenu *popupMenu = wxCurrentPopupMenu; - wxCurrentPopupMenu = NULL; - if (popupMenu->MSWCommand(cmd, id)) - return TRUE; + Layout(); + return; } +#endif - if (GetMenuBar() && GetMenuBar()->FindItemForId(id)) + // do we have _exactly_ one child? + wxWindow *child = NULL; + for ( wxWindowList::Node *node = GetChildren().GetFirst(); + node; + node = node->GetNext() ) { - ProcessCommand(id); - return TRUE; + wxWindow *win = node->GetData(); + if ( !win->IsTopLevel() +#if wxUSE_STATUSBAR + && (win != GetStatusBar()) +#endif // wxUSE_STATUSBAR +#if wxUSE_TOOLBAR + && (win != GetToolBar()) +#endif // wxUSE_TOOLBAR + ) + { + if ( child ) + return; // it's our second subwindow - nothing to do + child = win; + } } - else - return FALSE; - } - else - return wxWindow::MSWOnCommand(id, cmd, control); -} - -void wxFrame::MSWOnMenuHighlight(WXWORD nItem, WXWORD nFlags, WXHMENU hSysMenu) -{ - if (nFlags == 0xFFFF && hSysMenu == 0) - { - wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, -1); - event.SetEventObject( this ); - GetEventHandler()->ProcessEvent(event); - } - else if ((nFlags != MF_SEPARATOR) && (nItem != 0) && (nItem != 65535)) - { - wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, nItem); - event.SetEventObject( this ); - GetEventHandler()->ProcessEvent(event); - } -} - -bool wxFrame::MSWProcessMessage(WXMSG* pMsg) -{ - return FALSE; -} - -bool wxFrame::MSWTranslateMessage(WXMSG* pMsg) -{ - if (m_acceleratorTable.Ok() && - ::TranslateAccelerator((HWND) GetHWND(), (HACCEL) m_acceleratorTable.GetHACCEL(), (MSG *)pMsg)) - return TRUE; - return FALSE; -} + if ( child ) { + // we have exactly one child - set it's size to fill the whole frame + int clientW, clientH; + GetClientSize(&clientW, &clientH); -// Default resizing behaviour - if only ONE subwindow, -// resize to client rectangle size -void wxFrame::OnSize(wxSizeEvent& event) -{ - // if we're using constraints - do use them - #if wxUSE_CONSTRAINTS - if ( GetAutoLayout() ) { - Layout(); - return; - } - #endif + int x = 0; + int y = 0; - // do we have _exactly_ one child? - wxWindow *child = NULL; - for ( wxNode *node = GetChildren().First(); node; node = node->Next() ) - { - wxWindow *win = (wxWindow *)node->Data(); - if ( !win->IsKindOf(CLASSINFO(wxFrame)) && - !win->IsKindOf(CLASSINFO(wxDialog)) && - (win != GetStatusBar()) && - (win != GetToolBar()) ) - { - if ( child ) - return; // it's our second subwindow - nothing to do - child = win; + child->SetSize(x, y, clientW, clientH); } - } - - if ( child ) { - // we have exactly one child - set it's size to fill the whole frame - int clientW, clientH; - GetClientSize(&clientW, &clientH); - - int x = 0; - int y = 0; - - child->SetSize(x, y, clientW, clientH); - } } // Default activation behaviour - set the focus for the first child // subwindow found. void wxFrame::OnActivate(wxActivateEvent& event) { - for(wxNode *node = GetChildren().First(); node; node = node->Next()) - { - // Find a child that's a subwindow, but not a dialog box. - wxWindow *child = (wxWindow *)node->Data(); - if (!child->IsKindOf(CLASSINFO(wxFrame)) && - !child->IsKindOf(CLASSINFO(wxDialog))) + for ( wxWindowList::Node *node = GetChildren().GetFirst(); + node; + node = node->GetNext() ) { - child->SetFocus(); - return; + // FIXME all this is totally bogus - we need to do the same as wxPanel, + // but how to do it without duplicating the code? + + // restore focus + wxWindow *child = node->GetData(); + + if ( !child->IsTopLevel() +#if wxUSE_TOOLBAR + && !wxDynamicCast(child, wxToolBar) +#endif // wxUSE_TOOLBAR +#if wxUSE_STATUSBAR + && !wxDynamicCast(child, wxStatusBar) +#endif // wxUSE_STATUSBAR + ) + { + child->SetFocus(); + return; + } } - } } // The default implementation for the close window event. void wxFrame::OnCloseWindow(wxCloseEvent& event) { - this->Destroy(); + Destroy(); } // Destroy the window (delayed, if a managed window) @@ -859,18 +641,21 @@ void wxFrame::OnMenuHighlight(wxMenuEvent& event) { if (GetStatusBar()) { + wxString help; int menuId = event.GetMenuId(); if ( menuId != -1 ) { wxMenuBar *menuBar = GetMenuBar(); if (menuBar && menuBar->FindItem(menuId)) { - // set status text even if the string is empty - this will at - // least remove the string from the item which was previously - // selected - SetStatusText(menuBar->GetHelpString(menuId)); + help = menuBar->GetHelpString(menuId); } } + + // set status text even if the string is empty - this will at + // least remove the string from the item which was previously + // selected + SetStatusText(help); } } @@ -879,49 +664,24 @@ wxMenuBar *wxFrame::GetMenuBar() const return m_frameMenuBar; } -void wxFrame::Centre(int direction) +bool wxFrame::ProcessCommand(int id) { - int display_width, display_height, width, height, x, y; - wxDisplaySize(&display_width, &display_height); + wxMenuBar *bar = GetMenuBar() ; + if ( !bar ) + return FALSE; - GetSize(&width, &height); - GetPosition(&x, &y); + wxMenuItem *item = bar->FindItemForId(id); - if (direction & wxHORIZONTAL) - x = (int)((display_width - width)/2); - if (direction & wxVERTICAL) - y = (int)((display_height - height)/2); - - SetSize(x, y, width, height); -} - -// Call this to simulate a menu command -void wxFrame::Command(int id) -{ - ProcessCommand(id); -} - -void wxFrame::ProcessCommand(int id) -{ - wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id); - commandEvent.SetInt( id ); - commandEvent.SetEventObject( this ); - - wxMenuBar *bar = GetMenuBar() ; - if (!bar) - return; - - wxMenuItem *item = bar->FindItemForId(id) ; - if (item && item->IsCheckable()) - { - bar->Check(id,!bar->Checked(id)) ; - } + if ( item && item->IsCheckable() ) + { + bar->Check(id, !bar->IsChecked(id)) ; + } - // Process events starting with the window with the focus, if any. - wxWindow* focusWin = wxFindFocusDescendant(this); + wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id); + commandEvent.SetInt( id ); + commandEvent.SetEventObject( this ); - wxEvtHandler* evtHandler = focusWin ? focusWin->GetEventHandler() : GetEventHandler(); - evtHandler->ProcessEvent(commandEvent); + return GetEventHandler()->ProcessEvent(commandEvent); } // Checks if there is a toolbar, and returns the first free client position @@ -945,9 +705,9 @@ wxPoint wxFrame::GetClientAreaOrigin() const return pt; } -void wxFrame::ScreenToClient(int *x, int *y) const +void wxFrame::DoScreenToClient(int *x, int *y) const { - wxWindow::ScreenToClient(x, y); + wxWindow::DoScreenToClient(x, y); // We may be faking the client origin. // So a window that's really at (0, 30) may appear @@ -957,7 +717,7 @@ void wxFrame::ScreenToClient(int *x, int *y) const *y -= pt.y; } -void wxFrame::ClientToScreen(int *x, int *y) const +void wxFrame::DoClientToScreen(int *x, int *y) const { // We may be faking the client origin. // So a window that's really at (0, 30) may appear @@ -966,13 +726,14 @@ void wxFrame::ClientToScreen(int *x, int *y) const *x += pt1.x; *y += pt1.y; - wxWindow::ClientToScreen(x, y); + wxWindow::DoClientToScreen(x, y); } +#if wxUSE_TOOLBAR wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name) { wxCHECK_MSG( m_frameToolBar == NULL, FALSE, - "recreating toolbar in wxFrame" ); + wxT("recreating toolbar in wxFrame") ); wxToolBar* toolBar = OnCreateToolBar(style, id, name); if (toolBar) @@ -995,7 +756,7 @@ wxToolBar* wxFrame::OnCreateToolBar(long style, wxWindowID id, const wxString& n void wxFrame::PositionToolBar() { RECT rect; - ::GetClientRect((HWND) GetHWND(), &rect); + ::GetClientRect(GetHwnd(), &rect); if ( GetStatusBar() ) { @@ -1021,15 +782,283 @@ void wxFrame::PositionToolBar() } } } +#endif // wxUSE_TOOLBAR -// propagate our state change to all child frames +// propagate our state change to all child frames: this allows us to emulate X +// Windows behaviour where child frames float independently of the parent one +// on the desktop, but are iconized/restored with it void wxFrame::IconizeChildFrames(bool bIconize) { - for ( wxNode *node = GetChildren().First(); node; node = node->Next() ) { - wxWindow *win = (wxWindow *)node->Data(); - if ( win->IsKindOf(CLASSINFO(wxFrame)) ) { - ((wxFrame *)win)->Iconize(bIconize); + for ( wxWindowList::Node *node = GetChildren().GetFirst(); + node; + node = node->GetNext() ) + { + wxWindow *win = node->GetData(); + + if ( win->IsKindOf(CLASSINFO(wxFrame)) ) + { + ((wxFrame *)win)->Iconize(bIconize); + } } - } +} + + +// make the window modal (all other windows unresponsive) +void wxFrame::MakeModal(bool modal) +{ + if (modal) { + wxEnableTopLevelWindows(FALSE); + Enable(TRUE); // keep this window enabled + } + else { + wxEnableTopLevelWindows(TRUE); + } +} + + +// =========================================================================== +// message processing +// =========================================================================== + +// --------------------------------------------------------------------------- +// preprocessing +// --------------------------------------------------------------------------- + +bool wxFrame::MSWTranslateMessage(WXMSG* pMsg) +{ + if ( wxWindow::MSWTranslateMessage(pMsg) ) + return TRUE; + + // try the menu bar accels + wxMenuBar *menuBar = GetMenuBar(); + if ( !menuBar ) + return FALSE; + + const wxAcceleratorTable& acceleratorTable = menuBar->GetAccelTable(); + return acceleratorTable.Translate(this, pMsg); +} + +// --------------------------------------------------------------------------- +// our private (non virtual) message handlers +// --------------------------------------------------------------------------- + +bool wxFrame::HandlePaint() +{ + RECT rect; + if ( GetUpdateRect(GetHwnd(), &rect, FALSE) ) + { + if ( m_iconized ) + { + HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon) + : (HICON)m_defaultIcon; + + // Hold a pointer to the dc so long as the OnPaint() message + // is being processed + PAINTSTRUCT ps; + HDC hdc = ::BeginPaint(GetHwnd(), &ps); + + // Erase background before painting or we get white background + MSWDefWindowProc(WM_ICONERASEBKGND, (WORD)(LONG)ps.hdc, 0L); + + if ( hIcon ) + { + RECT rect; + ::GetClientRect(GetHwnd(), &rect); + + // FIXME: why hardcoded? + static const int icon_width = 32; + static const int icon_height = 32; + + int icon_x = (int)((rect.right - icon_width)/2); + int icon_y = (int)((rect.bottom - icon_height)/2); + + ::DrawIcon(hdc, icon_x, icon_y, hIcon); + } + + ::EndPaint(GetHwnd(), &ps); + + return TRUE; + } + else + { + return wxWindow::HandlePaint(); + } + } + else + { + // nothing to paint - processed + return TRUE; + } +} + +bool wxFrame::HandleSize(int x, int y, WXUINT id) +{ + bool processed = FALSE; + + switch ( id ) + { + case SIZENORMAL: + // only do it it if we were iconized before, otherwise resizing the + // parent frame has a curious side effect of bringing it under it's + // children + if ( !m_iconized ) + break; + + // restore all child frames too + IconizeChildFrames(FALSE); + + // fall through + + case SIZEFULLSCREEN: + m_iconized = FALSE; + break; + + case SIZEICONIC: + // iconize all child frames too + IconizeChildFrames(TRUE); + + m_iconized = TRUE; + break; + } + + if ( !m_iconized ) + { + // forward WM_SIZE to status bar control +#if wxUSE_NATIVE_STATUSBAR + if (m_frameStatusBar && m_frameStatusBar->IsKindOf(CLASSINFO(wxStatusBar95))) + { + wxSizeEvent event(wxSize(x, y), m_frameStatusBar->GetId()); + event.SetEventObject( m_frameStatusBar ); + + ((wxStatusBar95 *)m_frameStatusBar)->OnSize(event); + } +#endif // wxUSE_NATIVE_STATUSBAR + + PositionStatusBar(); + PositionToolBar(); + + wxSizeEvent event(wxSize(x, y), m_windowId); + event.SetEventObject( this ); + processed = GetEventHandler()->ProcessEvent(event); + } + + return processed; +} + +bool wxFrame::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control) +{ + if ( control ) + { + // In case it's e.g. a toolbar. + wxWindow *win = wxFindWinFromHandle(control); + if ( win ) + return win->MSWCommand(cmd, id); + } + + // handle here commands from menus and accelerators + if ( cmd == 0 || cmd == 1 ) + { + if ( wxCurrentPopupMenu ) + { + wxMenu *popupMenu = wxCurrentPopupMenu; + wxCurrentPopupMenu = NULL; + + return popupMenu->MSWCommand(cmd, id); + } + + if ( ProcessCommand(id) ) + { + return TRUE; + } + } + + return FALSE; +} + +bool wxFrame::HandleMenuSelect(WXWORD nItem, WXWORD flags, WXHMENU hMenu) +{ + int item; + if ( flags == 0xFFFF && hMenu == 0 ) + { + // menu was removed from screen + item = -1; + } + else if ( !(flags & MF_POPUP) && !(flags & MF_SEPARATOR) ) + { + item = nItem; + } + else + { + // don't give hints for separators (doesn't make sense) nor for the + // items opening popup menus (they don't have them anyhow) + return FALSE; + } + + wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, item); + event.SetEventObject( this ); + + return GetEventHandler()->ProcessEvent(event); +} + +// --------------------------------------------------------------------------- +// the window proc for wxFrame +// --------------------------------------------------------------------------- + +long wxFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) +{ + long rc = 0; + bool processed = FALSE; + + switch ( message ) + { + case WM_CLOSE: + // if we can't close, tell the system that we processed the + // message - otherwise it would close us + processed = !Close(); + break; + + 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_MENUSELECT: + { + WXWORD item, flags; + WXHMENU hmenu; + UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu); + + processed = HandleMenuSelect(item, flags, hmenu); + } + break; + + case WM_PAINT: + processed = HandlePaint(); + break; + + case WM_QUERYDRAGICON: + { + HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon) + : (HICON)(m_defaultIcon); + rc = (long)hIcon; + processed = rc != 0; + } + break; + + case WM_SIZE: + processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam); + break; + } + + if ( !processed ) + rc = wxWindow::MSWWindowProc(message, wParam, lParam); + + return rc; }