1 /////////////////////////////////////////////////////////////////////////////
4 // Author: David Webster
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
21 #include "wx/dialog.h"
22 #include "wx/settings.h"
23 #include "wx/dcclient.h"
26 #include "wx/os2/private.h"
29 #include "wx/statusbr.h"
30 #endif // wxUSE_STATUSBAR
33 #include "wx/toolbar.h"
34 #endif // wxUSE_TOOLBAR
36 #include "wx/menuitem.h"
39 // ----------------------------------------------------------------------------
41 // ----------------------------------------------------------------------------
43 extern wxWindowList wxModelessWindows
;
44 extern wxList WXDLLEXPORT wxPendingDelete
;
45 extern wxChar wxFrameClassName
[];
46 extern wxMenu
*wxCurrentPopupMenu
;
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 BEGIN_EVENT_TABLE(wxFrame
, wxFrameBase
)
53 EVT_ACTIVATE(wxFrame::OnActivate
)
54 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged
)
57 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxWindow
)
59 // ============================================================================
61 // ============================================================================
63 // ----------------------------------------------------------------------------
64 // static class members
65 // ----------------------------------------------------------------------------
67 #if wxUSE_NATIVE_STATUSBAR
68 bool wxFrame::m_useNativeStatusBar
= TRUE
;
70 bool wxFrame::m_useNativeStatusBar
= FALSE
;
73 // ----------------------------------------------------------------------------
74 // creation/destruction
75 // ----------------------------------------------------------------------------
86 bool wxFrame::Create(wxWindow
*parent
,
88 const wxString
& title
,
95 m_windowStyle
= style
;
96 m_frameMenuBar
= NULL
;
97 m_frameToolBar
= NULL
;
98 m_frameStatusBar
= NULL
;
100 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
));
105 m_windowId
= (int)NewControlId();
107 if (parent
) parent
->AddChild(this);
116 // we pass NULL as parent to MSWCreate because frames with parents behave
117 // very strangely under Win95 shell
118 // Alteration by JACS: keep normal Windows behaviour (float on top of parent)
120 if ((m_windowStyle
& wxFRAME_FLOAT_ON_PARENT
) == 0)
124 wxTopLevelWindows
.Append(this);
126 OS2Create(m_windowId
, parent
, wxFrameClassName
, this, title
,
127 x
, y
, width
, height
, style
);
129 wxModelessWindows
.Append(this);
135 m_isBeingDeleted
= TRUE
;
136 wxTopLevelWindows
.DeleteObject(this);
142 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
144 wxTheApp->SetTopWindow(NULL);
146 if (wxTheApp->GetExitOnFrameDelete())
152 wxModelessWindows.DeleteObject(this);
154 // For some reason, wxWindows can activate another task altogether
155 // when a frame is destroyed after a modal dialog has been invoked.
156 // Try to bring the parent to the top.
157 // MT:Only do this if this frame is currently the active window, else weird
158 // things start to happen
159 if ( wxGetActiveWindow() == this )
160 if (GetParent() && GetParent()->GetHWND())
161 ::BringWindowToTop((HWND) GetParent()->GetHWND());
165 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
166 void wxFrame::DoGetClientSize(int *x
, int *y
) const
171 ::GetClientRect(GetHwnd(), &rect);
174 if ( GetStatusBar() )
176 int statusX, statusY;
177 GetStatusBar()->GetClientSize(&statusX, &statusY);
178 rect.bottom -= statusY;
180 #endif // wxUSE_STATUSBAR
182 wxPoint pt(GetClientAreaOrigin());
193 // Set the client size (i.e. leave the calculation of borders etc.
195 void wxFrame::DoSetClientSize(int width
, int height
)
197 HWND hWnd
= GetHwnd();
202 ::GetClientRect(hWnd, &rect);
205 GetWindowRect(hWnd, &rect2);
207 // Find the difference between the entire window (title bar and all)
208 // and the client area; add this to the new client size to move the
210 int actual_width = rect2.right - rect2.left - rect.right + width;
211 int actual_height = rect2.bottom - rect2.top - rect.bottom + height;
214 if ( GetStatusBar() )
216 int statusX, statusY;
217 GetStatusBar()->GetClientSize(&statusX, &statusY);
218 actual_height += statusY;
220 #endif // wxUSE_STATUSBAR
222 wxPoint pt(GetClientAreaOrigin());
223 actual_width += pt.y;
224 actual_height += pt.x;
227 point.x = rect2.left;
230 MoveWindow(hWnd, point.x, point.y, actual_width, actual_height, (BOOL)TRUE);
232 wxSizeEvent event(wxSize(width, height), m_windowId);
233 event.SetEventObject( this );
234 GetEventHandler()->ProcessEvent(event);
238 void wxFrame::DoGetSize(int *width
, int *height
) const
243 GetWindowRect(GetHwnd(), &rect);
244 *width = rect.right - rect.left;
245 *height = rect.bottom - rect.top;
249 void wxFrame::DoGetPosition(int *x
, int *y
) const
254 GetWindowRect(GetHwnd(), &rect);
264 // ----------------------------------------------------------------------------
265 // variations around ::ShowWindow()
266 // ----------------------------------------------------------------------------
268 void wxFrame::DoShowWindow(int nShowCmd
)
272 ::ShowWindow(GetHwnd(), nShowCmd);
274 m_iconized = nShowCmd == SW_MINIMIZE;
278 bool wxFrame::Show(bool show
)
282 DoShowWindow(show ? SW_SHOW : SW_HIDE);
286 ::BringWindowToTop(GetHwnd());
288 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, m_windowId);
289 event.SetEventObject( this );
290 GetEventHandler()->ProcessEvent(event);
294 // Try to highlight the correct window (the parent)
297 HWND hWndParent = GetHwndOf(GetParent());
299 ::BringWindowToTop(hWndParent);
306 void wxFrame::Iconize(bool iconize
)
308 // DoShowWindow(iconize ? SW_MINIMIZE : SW_RESTORE);
311 void wxFrame::Maximize(bool maximize
)
313 // DoShowWindow(maximize ? SW_MAXIMIZE : SW_RESTORE);
316 void wxFrame::Restore()
318 // DoShowWindow(SW_RESTORE);
321 bool wxFrame::IsIconized() const
325 ((wxFrame *)this)->m_iconized = (::IsIconic(GetHwnd()) != 0);
332 bool wxFrame::IsMaximized() const
336 return (::IsZoomed(GetHwnd()) != 0);
341 void wxFrame::SetIcon(const wxIcon
& icon
)
343 wxFrameBase::SetIcon(icon
);
349 SendMessage(GetHwnd(), WM_SETICON,
350 (WPARAM)TRUE, (LPARAM)(HICON) m_icon.GetHICON());
356 wxStatusBar
*wxFrame::OnCreateStatusBar(int number
,
359 const wxString
& name
)
361 wxStatusBar
*statusBar
= NULL
;
363 statusBar
= wxFrameBase::OnCreateStatusBar(number
, style
, id
, name
);
368 void wxFrame::PositionStatusBar()
372 // native status bar positions itself
373 if ( m_frameStatusBar )
376 GetClientSize(&w, &h);
378 m_frameStatusBar->GetSize(&sw, &sh);
380 // Since we wish the status bar to be directly under the client area,
381 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
382 m_frameStatusBar->SetSize(0, h, w, sh);
386 #endif // wxUSE_STATUSBAR
388 void wxFrame::DetachMenuBar()
392 m_frameMenuBar
->Detach();
393 m_frameMenuBar
= NULL
;
397 void wxFrame::SetMenuBar(wxMenuBar
*menu_bar
)
405 wxCHECK_RET( !menu_bar
->GetFrame(), wxT("this menubar is already attached") );
408 delete m_frameMenuBar
;
410 m_hMenu
= menu_bar
->Create();
415 InternalSetMenuBar();
417 m_frameMenuBar
= menu_bar
;
418 menu_bar
->Attach(this);
421 void wxFrame::InternalSetMenuBar()
425 if ( !::SetMenu(GetHwnd(), (HMENU)m_hMenu) )
427 wxLogLastError("SetMenu");
432 // Responds to colour changes, and passes event on to children.
433 void wxFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
)
437 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
440 if ( m_frameStatusBar )
442 wxSysColourChangedEvent event2;
443 event2.SetEventObject( m_frameStatusBar );
444 m_frameStatusBar->GetEventHandler()->ProcessEvent(event2);
447 // Propagate the event to the non-top-level children
448 wxWindow::OnSysColourChanged(event);
457 bool wxFrame::OS2Create(int id
, wxWindow
*parent
, const wxChar
*wclass
, wxWindow
*wx_win
, const wxChar
*title
,
458 int x
, int y
, int width
, int height
, long style
)
461 m_defaultIcon
= (WXHICON
) (wxSTD_FRAME_ICON
? wxSTD_FRAME_ICON
: wxDEFAULT_FRAME_ICON
);
463 // If child windows aren't properly drawn initially, WS_CLIPCHILDREN
464 // could be the culprit. But without it, you can get a lot of flicker.
469 if ((style & wxCAPTION) == wxCAPTION)
470 msflags = WS_OVERLAPPED;
474 if (style & wxMINIMIZE_BOX)
475 msflags |= WS_MINIMIZEBOX;
476 if (style & wxMAXIMIZE_BOX)
477 msflags |= WS_MAXIMIZEBOX;
478 if (style & wxTHICK_FRAME)
479 msflags |= WS_THICKFRAME;
480 if (style & wxSYSTEM_MENU)
481 msflags |= WS_SYSMENU;
482 if ((style & wxMINIMIZE) || (style & wxICONIZE))
483 msflags |= WS_MINIMIZE;
484 if (style & wxMAXIMIZE)
485 msflags |= WS_MAXIMIZE;
486 if (style & wxCAPTION)
487 msflags |= WS_CAPTION;
488 if (style & wxCLIP_CHILDREN)
489 msflags |= WS_CLIPCHILDREN;
491 // Keep this in wxFrame because it saves recoding this function
494 if (style & wxTINY_CAPTION_VERT)
495 msflags |= IBS_VERTCAPTION;
496 if (style & wxTINY_CAPTION_HORIZ)
497 msflags |= IBS_HORZCAPTION;
499 if (style & wxTINY_CAPTION_VERT)
500 msflags |= WS_CAPTION;
501 if (style & wxTINY_CAPTION_HORIZ)
502 msflags |= WS_CAPTION;
504 if ((style & wxTHICK_FRAME) == 0)
505 msflags |= WS_BORDER;
507 WXDWORD extendedStyle = MakeExtendedStyle(style);
509 #if !defined(__WIN16__) && !defined(__SC__)
510 if (style & wxFRAME_TOOL_WINDOW)
511 extendedStyle |= WS_EX_TOOLWINDOW;
514 if (style & wxSTAY_ON_TOP)
515 extendedStyle |= WS_EX_TOPMOST;
518 if ( !wxWindow::MSWCreate(id, parent, wclass, wx_win, title, x, y, width, height,
519 msflags, NULL, extendedStyle) )
522 // Seems to be necessary if we use WS_POPUP
523 // style instead of WS_OVERLAPPED
524 if (width > -1 && height > -1)
525 ::PostMessage(GetHwnd(), WM_SIZE, SIZE_RESTORED, MAKELPARAM(width, height));
530 // Default activation behaviour - set the focus for the first child
532 void wxFrame::OnActivate(wxActivateEvent
& event
)
534 for ( wxWindowList::Node
*node
= GetChildren().GetFirst();
536 node
= node
->GetNext() )
538 // FIXME all this is totally bogus - we need to do the same as wxPanel,
539 // but how to do it without duplicating the code?
542 wxWindow
*child
= node
->GetData();
544 if ( !child
->IsTopLevel()
546 && !wxDynamicCast(child
, wxToolBar
)
547 #endif // wxUSE_TOOLBAR
549 && !wxDynamicCast(child
, wxStatusBar
)
550 #endif // wxUSE_STATUSBAR
559 // ----------------------------------------------------------------------------
560 // wxFrame size management: we exclude the areas taken by menu/status/toolbars
561 // from the client area, so the client area is what's really available for the
563 // ----------------------------------------------------------------------------
565 // Checks if there is a toolbar, and returns the first free client position
566 wxPoint
wxFrame::GetClientAreaOrigin() const
572 GetToolBar()->GetSize(& w
, & h
);
574 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL
)
586 void wxFrame::DoScreenToClient(int *x
, int *y
) const
588 wxWindow::DoScreenToClient(x
, y
);
590 // We may be faking the client origin.
591 // So a window that's really at (0, 30) may appear
592 // (to wxWin apps) to be at (0, 0).
593 wxPoint
pt(GetClientAreaOrigin());
598 void wxFrame::DoClientToScreen(int *x
, int *y
) const
600 // We may be faking the client origin.
601 // So a window that's really at (0, 30) may appear
602 // (to wxWin apps) to be at (0, 0).
603 wxPoint
pt1(GetClientAreaOrigin());
607 wxWindow::DoClientToScreen(x
, y
);
610 // ----------------------------------------------------------------------------
611 // tool/status bar stuff
612 // ----------------------------------------------------------------------------
616 wxToolBar
* wxFrame::CreateToolBar(long style
, wxWindowID id
, const wxString
& name
)
618 if ( wxFrameBase::CreateToolBar(style
, id
, name
) )
623 return m_frameToolBar
;
626 void wxFrame::PositionToolBar()
631 ::GetClientRect(GetHwnd(), &rect);
634 if ( GetStatusBar() )
636 int statusX, statusY;
637 GetStatusBar()->GetClientSize(&statusX, &statusY);
638 rect.bottom -= statusY;
640 #endif // wxUSE_STATUSBAR
645 GetToolBar()->GetSize(&tw, &th);
647 if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL )
656 // Use the 'real' MSW position here
657 GetToolBar()->SetSize(0, 0, tw, th, wxSIZE_NO_ADJUSTMENTS);
661 #endif // wxUSE_TOOLBAR
663 // ----------------------------------------------------------------------------
664 // frame state (iconized/maximized/...)
665 // ----------------------------------------------------------------------------
667 // propagate our state change to all child frames: this allows us to emulate X
668 // Windows behaviour where child frames float independently of the parent one
669 // on the desktop, but are iconized/restored with it
670 void wxFrame::IconizeChildFrames(bool bIconize
)
672 for ( wxWindowList::Node
*node
= GetChildren().GetFirst();
674 node
= node
->GetNext() )
676 wxWindow
*win
= node
->GetData();
678 if ( win
->IsKindOf(CLASSINFO(wxFrame
)) )
680 ((wxFrame
*)win
)->Iconize(bIconize
);
685 // ===========================================================================
686 // message processing
687 // ===========================================================================
689 // ---------------------------------------------------------------------------
691 // ---------------------------------------------------------------------------
693 bool wxFrame::OS2TranslateMessage(WXMSG
* pMsg
)
697 if ( wxWindow::OS2TranslateMessage(pMsg) )
700 // try the menu bar accels
701 wxMenuBar
*menuBar
= GetMenuBar();
705 const wxAcceleratorTable
& acceleratorTable
= menuBar
->GetAccelTable();
706 return acceleratorTable
.Translate(this, pMsg
);
709 // ---------------------------------------------------------------------------
710 // our private (non virtual) message handlers
711 // ---------------------------------------------------------------------------
713 bool wxFrame::HandlePaint()
718 if ( GetUpdateRect(GetHwnd(), &rect, FALSE) )
722 HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon)
723 : (HICON)m_defaultIcon;
725 // Hold a pointer to the dc so long as the OnPaint() message
726 // is being processed
728 HDC hdc = ::BeginPaint(GetHwnd(), &ps);
730 // Erase background before painting or we get white background
731 MSWDefWindowProc(WM_ICONERASEBKGND, (WORD)(LONG)ps.hdc, 0L);
736 ::GetClientRect(GetHwnd(), &rect);
738 // FIXME: why hardcoded?
739 static const int icon_width = 32;
740 static const int icon_height = 32;
742 int icon_x = (int)((rect.right - icon_width)/2);
743 int icon_y = (int)((rect.bottom - icon_height)/2);
745 ::DrawIcon(hdc, icon_x, icon_y, hIcon);
748 ::EndPaint(GetHwnd(), &ps);
754 return wxWindow::HandlePaint();
759 // nothing to paint - processed
766 bool wxFrame::HandleSize(int x
, int y
, WXUINT id
)
768 bool processed
= FALSE
;
775 // only do it it if we were iconized before, otherwise resizing the
776 // parent frame has a curious side effect of bringing it under it's
781 // restore all child frames too
782 IconizeChildFrames(FALSE);
791 // iconize all child frames too
792 IconizeChildFrames(TRUE);
800 // forward WM_SIZE to status bar control
801 #if wxUSE_NATIVE_STATUSBAR
802 if (m_frameStatusBar && m_frameStatusBar->IsKindOf(CLASSINFO(wxStatusBar95)))
804 wxSizeEvent event(wxSize(x, y), m_frameStatusBar->GetId());
805 event.SetEventObject( m_frameStatusBar );
807 ((wxStatusBar95 *)m_frameStatusBar)->OnSize(event);
809 #endif // wxUSE_NATIVE_STATUSBAR
814 wxSizeEvent event(wxSize(x, y), m_windowId);
815 event.SetEventObject( this );
816 processed = GetEventHandler()->ProcessEvent(event);
822 bool wxFrame::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
828 // In case it's e.g. a toolbar.
829 wxWindow *win = wxFindWinFromHandle(control);
831 return win->MSWCommand(cmd, id);
834 // handle here commands from menus and accelerators
835 if ( cmd == 0 || cmd == 1 )
837 if ( wxCurrentPopupMenu )
839 wxMenu *popupMenu = wxCurrentPopupMenu;
840 wxCurrentPopupMenu = NULL;
842 return popupMenu->MSWCommand(cmd, id);
845 if ( ProcessCommand(id) )
854 bool wxFrame::HandleMenuSelect(WXWORD nItem
, WXWORD flags
, WXHMENU hMenu
)
857 if ( flags
== 0xFFFF && hMenu
== 0 )
859 // menu was removed from screen
864 else if ( !(flags & MF_POPUP) && !(flags & MF_SEPARATOR) )
870 // don't give hints for separators (doesn't make sense) nor for the
871 // items opening popup menus (they don't have them anyhow)
875 wxMenuEvent
event(wxEVT_MENU_HIGHLIGHT
, item
);
876 event
.SetEventObject( this );
878 return GetEventHandler()->ProcessEvent(event
);
881 // ---------------------------------------------------------------------------
882 // the window proc for wxFrame
883 // ---------------------------------------------------------------------------
885 MRESULT
wxFrame::OS2WindowProc(HWND hwnd
, WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
888 bool processed
= FALSE
;
895 // if we can't close, tell the system that we processed the
896 // message - otherwise it would close us
897 processed = !Close();
904 UnpackCommand((WXWPARAM)wParam, (WXLPARAM)lParam,
907 processed = HandleCommand(id, cmd, (WXHWND)hwnd);
915 UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu);
917 processed = HandleMenuSelect(item, flags, hmenu);
922 processed = HandlePaint();
925 case WM_QUERYDRAGICON:
927 HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon)
928 : (HICON)(m_defaultIcon);
935 processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam);
940 rc = wxWindow::MSWWindowProc(message, wParam, lParam);