]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/frame.cpp
Fixed crash-on-exit bug due to status bar being deleted twice (MDI apps);
[wxWidgets.git] / src / msw / frame.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: msw/frame.cpp
3// Purpose: wxFrame
4// Author: Julian Smart
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
21 #pragma implementation "frame.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28 #pragma hdrstop
29#endif
30
31#ifndef WX_PRECOMP
32 #include "wx/setup.h"
33 #include "wx/frame.h"
34 #include "wx/menu.h"
35 #include "wx/app.h"
36 #include "wx/utils.h"
37 #include "wx/dialog.h"
38 #include "wx/settings.h"
39 #include "wx/dcclient.h"
40 #include "wx/mdi.h"
41#endif // WX_PRECOMP
42
43#include "wx/msw/private.h"
44
45#if wxUSE_STATUSBAR
46 #include "wx/statusbr.h"
47 #include "wx/generic/statusbr.h"
48#endif // wxUSE_STATUSBAR
49
50#if wxUSE_TOOLBAR
51 #include "wx/toolbar.h"
52#endif // wxUSE_TOOLBAR
53
54#include "wx/menuitem.h"
55#include "wx/log.h"
56
57// ----------------------------------------------------------------------------
58// globals
59// ----------------------------------------------------------------------------
60
61extern wxWindowList wxModelessWindows;
62extern wxList WXDLLEXPORT wxPendingDelete;
63extern const wxChar *wxFrameClassName;
64extern wxMenu *wxCurrentPopupMenu;
65
66// ----------------------------------------------------------------------------
67// event tables
68// ----------------------------------------------------------------------------
69
70BEGIN_EVENT_TABLE(wxFrame, wxFrameBase)
71 EVT_ACTIVATE(wxFrame::OnActivate)
72 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
73END_EVENT_TABLE()
74
75IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxWindow)
76
77// ============================================================================
78// implementation
79// ============================================================================
80
81// ----------------------------------------------------------------------------
82// static class members
83// ----------------------------------------------------------------------------
84
85#if wxUSE_NATIVE_STATUSBAR
86 bool wxFrame::m_useNativeStatusBar = TRUE;
87#else
88 bool wxFrame::m_useNativeStatusBar = FALSE;
89#endif
90
91// ----------------------------------------------------------------------------
92// creation/destruction
93// ----------------------------------------------------------------------------
94
95void wxFrame::Init()
96{
97 m_iconized = FALSE;
98
99#if wxUSE_TOOLTIPS
100 m_hwndToolTip = 0;
101#endif
102
103 // Data to save/restore when calling ShowFullScreen
104 m_fsStyle = 0;
105 m_fsOldWindowStyle = 0;
106 m_fsStatusBarFields = 0;
107 m_fsStatusBarHeight = 0;
108 m_fsToolBarHeight = 0;
109// m_fsMenu = 0;
110 m_fsIsMaximized = FALSE;
111 m_fsIsShowing = FALSE;
112}
113
114bool wxFrame::Create(wxWindow *parent,
115 wxWindowID id,
116 const wxString& title,
117 const wxPoint& pos,
118 const wxSize& size,
119 long style,
120 const wxString& name)
121{
122 SetName(name);
123 m_windowStyle = style;
124 m_frameMenuBar = NULL;
125 m_frameToolBar = NULL;
126 m_frameStatusBar = NULL;
127
128 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
129
130 if ( id > -1 )
131 m_windowId = id;
132 else
133 m_windowId = (int)NewControlId();
134
135 if (parent) parent->AddChild(this);
136
137 int x = pos.x;
138 int y = pos.y;
139 int width = size.x;
140 int height = size.y;
141
142 m_iconized = FALSE;
143
144 // we pass NULL as parent to MSWCreate because frames with parents behave
145 // very strangely under Win95 shell
146 // Alteration by JACS: keep normal Windows behaviour (float on top of parent)
147 // with this style.
148 if ((m_windowStyle & wxFRAME_FLOAT_ON_PARENT) == 0)
149 parent = NULL;
150
151 if (!parent)
152 wxTopLevelWindows.Append(this);
153
154 MSWCreate(m_windowId, parent, wxFrameClassName, this, title,
155 x, y, width, height, style);
156
157 wxModelessWindows.Append(this);
158 return TRUE;
159}
160
161wxFrame::~wxFrame()
162{
163 m_isBeingDeleted = TRUE;
164 wxTopLevelWindows.DeleteObject(this);
165
166 DeleteAllBars();
167
168 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
169 {
170 wxTheApp->SetTopWindow(NULL);
171
172 if (wxTheApp->GetExitOnFrameDelete())
173 {
174 PostQuitMessage(0);
175 }
176 }
177
178 wxModelessWindows.DeleteObject(this);
179
180 // For some reason, wxWindows can activate another task altogether
181 // when a frame is destroyed after a modal dialog has been invoked.
182 // Try to bring the parent to the top.
183 // MT:Only do this if this frame is currently the active window, else weird
184 // things start to happen
185 if ( wxGetActiveWindow() == this )
186 if (GetParent() && GetParent()->GetHWND())
187 ::BringWindowToTop((HWND) GetParent()->GetHWND());
188}
189
190// Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
191void wxFrame::DoGetClientSize(int *x, int *y) const
192{
193 RECT rect;
194 ::GetClientRect(GetHwnd(), &rect);
195
196#if wxUSE_STATUSBAR
197 if ( GetStatusBar() && GetStatusBar()->IsShown() )
198 {
199 int statusX, statusY;
200 GetStatusBar()->GetClientSize(&statusX, &statusY);
201 rect.bottom -= statusY;
202 }
203#endif // wxUSE_STATUSBAR
204
205 wxPoint pt(GetClientAreaOrigin());
206 rect.bottom -= pt.y;
207 rect.right -= pt.x;
208
209 if ( x )
210 *x = rect.right;
211 if ( y )
212 *y = rect.bottom;
213}
214
215// Set the client size (i.e. leave the calculation of borders etc.
216// to wxWindows)
217void wxFrame::DoSetClientSize(int width, int height)
218{
219 HWND hWnd = GetHwnd();
220
221 RECT rect;
222 ::GetClientRect(hWnd, &rect);
223
224 RECT rect2;
225 GetWindowRect(hWnd, &rect2);
226
227 // Find the difference between the entire window (title bar and all)
228 // and the client area; add this to the new client size to move the
229 // window
230 int actual_width = rect2.right - rect2.left - rect.right + width;
231 int actual_height = rect2.bottom - rect2.top - rect.bottom + height;
232
233#if wxUSE_STATUSBAR
234 if ( GetStatusBar() && GetStatusBar()->IsShown())
235 {
236 int statusX, statusY;
237 GetStatusBar()->GetClientSize(&statusX, &statusY);
238 actual_height += statusY;
239 }
240#endif // wxUSE_STATUSBAR
241
242 wxPoint pt(GetClientAreaOrigin());
243 actual_width += pt.y;
244 actual_height += pt.x;
245
246 POINT point;
247 point.x = rect2.left;
248 point.y = rect2.top;
249
250 MoveWindow(hWnd, point.x, point.y, actual_width, actual_height, (BOOL)TRUE);
251
252 wxSizeEvent event(wxSize(width, height), m_windowId);
253 event.SetEventObject( this );
254 GetEventHandler()->ProcessEvent(event);
255}
256
257void wxFrame::DoGetSize(int *width, int *height) const
258{
259 RECT rect;
260 GetWindowRect(GetHwnd(), &rect);
261 *width = rect.right - rect.left;
262 *height = rect.bottom - rect.top;
263}
264
265void wxFrame::DoGetPosition(int *x, int *y) const
266{
267 RECT rect;
268 GetWindowRect(GetHwnd(), &rect);
269 POINT point;
270 point.x = rect.left;
271 point.y = rect.top;
272
273 *x = point.x;
274 *y = point.y;
275}
276
277// ----------------------------------------------------------------------------
278// variations around ::ShowWindow()
279// ----------------------------------------------------------------------------
280
281void wxFrame::DoShowWindow(int nShowCmd)
282{
283 ::ShowWindow(GetHwnd(), nShowCmd);
284
285 m_iconized = nShowCmd == SW_MINIMIZE;
286}
287
288bool wxFrame::Show(bool show)
289{
290 DoShowWindow(show ? SW_SHOW : SW_HIDE);
291
292 if ( show )
293 {
294 ::BringWindowToTop(GetHwnd());
295
296 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, m_windowId);
297 event.SetEventObject( this );
298 GetEventHandler()->ProcessEvent(event);
299 }
300 else
301 {
302 // Try to highlight the correct window (the parent)
303 if ( GetParent() )
304 {
305 HWND hWndParent = GetHwndOf(GetParent());
306 if (hWndParent)
307 ::BringWindowToTop(hWndParent);
308 }
309 }
310
311 return TRUE;
312}
313
314void wxFrame::Iconize(bool iconize)
315{
316 DoShowWindow(iconize ? SW_MINIMIZE : SW_RESTORE);
317}
318
319void wxFrame::Maximize(bool maximize)
320{
321 DoShowWindow(maximize ? SW_MAXIMIZE : SW_RESTORE);
322}
323
324void wxFrame::Restore()
325{
326 DoShowWindow(SW_RESTORE);
327}
328
329bool wxFrame::IsIconized() const
330{
331 ((wxFrame *)this)->m_iconized = (::IsIconic(GetHwnd()) != 0);
332 return m_iconized;
333}
334
335// Is it maximized?
336bool wxFrame::IsMaximized() const
337{
338 return (::IsZoomed(GetHwnd()) != 0);
339}
340
341void wxFrame::SetIcon(const wxIcon& icon)
342{
343 wxFrameBase::SetIcon(icon);
344
345#if defined(__WIN95__)
346 if ( m_icon.Ok() )
347 {
348 SendMessage(GetHwnd(), WM_SETICON,
349 (WPARAM)TRUE, (LPARAM)(HICON) m_icon.GetHICON());
350 }
351#endif // __WIN95__
352}
353
354#if wxUSE_STATUSBAR
355wxStatusBar *wxFrame::OnCreateStatusBar(int number,
356 long style,
357 wxWindowID id,
358 const wxString& name)
359{
360 wxStatusBar *statusBar = NULL;
361
362#if wxUSE_NATIVE_STATUSBAR
363 if ( UsesNativeStatusBar() )
364 {
365 statusBar = (wxStatusBar *)new wxStatusBar95(this, id, style);
366
367 statusBar->SetFieldsCount(number);
368 }
369 else
370#endif
371 {
372 statusBar = (wxStatusBar *)new wxStatusBarGeneric(this, id, style, name);
373
374 // Set the height according to the font and the border size
375 wxClientDC dc(statusBar);
376 dc.SetFont(statusBar->GetFont());
377
378 wxCoord y;
379 dc.GetTextExtent(_T("X"), NULL, &y );
380
381 int height = (int)( (11*y)/10 + 2*statusBar->GetBorderY());
382
383 statusBar->SetSize(-1, -1, -1, height);
384
385 statusBar->SetFieldsCount(number);
386 }
387
388 return statusBar;
389}
390
391void wxFrame::PositionStatusBar()
392{
393 if ( !m_frameStatusBar )
394 return;
395
396 int w, h;
397 GetClientSize(&w, &h);
398 int sw, sh;
399 m_frameStatusBar->GetSize(&sw, &sh);
400
401 // Since we wish the status bar to be directly under the client area,
402 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
403 m_frameStatusBar->SetSize(0, h, w, sh);
404}
405#endif // wxUSE_STATUSBAR
406
407void wxFrame::DetachMenuBar()
408{
409 if (m_frameMenuBar)
410 {
411 m_frameMenuBar->Detach();
412 m_frameMenuBar = NULL;
413 }
414}
415
416void wxFrame::SetMenuBar(wxMenuBar *menu_bar)
417{
418 if (!menu_bar)
419 {
420 DetachMenuBar();
421 return;
422 }
423
424 m_frameMenuBar = NULL;
425
426 // Can set a menubar several times.
427 // TODO: how to prevent a memory leak if you have a currently-unattached
428 // menubar? wxWindows assumes that the frame will delete the menu (otherwise
429 // there are problems for MDI).
430 if (menu_bar->GetHMenu())
431 {
432 m_hMenu = menu_bar->GetHMenu();
433 }
434 else
435 {
436 menu_bar->Detach();
437
438 m_hMenu = menu_bar->Create();
439
440 if ( !m_hMenu )
441 return;
442 }
443
444 InternalSetMenuBar();
445
446 m_frameMenuBar = menu_bar;
447 menu_bar->Attach(this);
448
449#if 0 // Old code that assumes only one call of SetMenuBar per frame.
450 if (!menu_bar)
451 {
452 DetachMenuBar();
453 return;
454 }
455
456 wxCHECK_RET( !menu_bar->GetFrame(), wxT("this menubar is already attached") );
457
458 if (m_frameMenuBar)
459 delete m_frameMenuBar;
460
461 m_hMenu = menu_bar->Create();
462
463 if ( !m_hMenu )
464 return;
465
466 InternalSetMenuBar();
467
468 m_frameMenuBar = menu_bar;
469 menu_bar->Attach(this);
470#endif
471}
472
473void wxFrame::InternalSetMenuBar()
474{
475 if ( !::SetMenu(GetHwnd(), (HMENU)m_hMenu) )
476 {
477 wxLogLastError("SetMenu");
478 }
479}
480
481// Responds to colour changes, and passes event on to children.
482void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
483{
484 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
485 Refresh();
486
487 if ( m_frameStatusBar )
488 {
489 wxSysColourChangedEvent event2;
490 event2.SetEventObject( m_frameStatusBar );
491 m_frameStatusBar->GetEventHandler()->ProcessEvent(event2);
492 }
493
494 // Propagate the event to the non-top-level children
495 wxWindow::OnSysColourChanged(event);
496}
497
498// Pass TRUE to show full screen, FALSE to restore.
499bool wxFrame::ShowFullScreen(bool show, long style)
500{
501 if (show)
502 {
503 if (IsFullScreen())
504 return FALSE;
505
506 m_fsIsShowing = TRUE;
507 m_fsStyle = style;
508
509 wxToolBar *theToolBar = GetToolBar();
510 wxStatusBar *theStatusBar = GetStatusBar();
511
512 int dummyWidth;
513
514 if (theToolBar)
515 theToolBar->GetSize(&dummyWidth, &m_fsToolBarHeight);
516 if (theStatusBar)
517 theStatusBar->GetSize(&dummyWidth, &m_fsStatusBarHeight);
518
519 // zap the toolbar, menubar, and statusbar
520
521 if ((style & wxFULLSCREEN_NOTOOLBAR) && theToolBar)
522 {
523 theToolBar->SetSize(-1,0);
524 theToolBar->Show(FALSE);
525 }
526
527 if (style & wxFULLSCREEN_NOMENUBAR)
528 SetMenu((HWND)GetHWND(), (HMENU) NULL);
529
530 // Save the number of fields in the statusbar
531 if ((style & wxFULLSCREEN_NOSTATUSBAR) && theStatusBar)
532 {
533 m_fsStatusBarFields = theStatusBar->GetFieldsCount();
534 SetStatusBar((wxStatusBar*) NULL);
535 delete theStatusBar;
536 }
537 else
538 m_fsStatusBarFields = 0;
539
540 // zap the frame borders
541
542 // save the 'normal' window style
543 m_fsOldWindowStyle = GetWindowLong((HWND)GetHWND(), GWL_STYLE);
544
545 // save the old position, width & height, maximize state
546 m_fsOldSize = GetRect();
547 m_fsIsMaximized = IsMaximized();
548
549 // decide which window style flags to turn off
550 LONG newStyle = m_fsOldWindowStyle;
551 LONG offFlags = 0;
552
553 if (style & wxFULLSCREEN_NOBORDER)
554 offFlags |= WS_BORDER;
555 if (style & wxFULLSCREEN_NOCAPTION)
556 offFlags |= (WS_CAPTION | WS_SYSMENU);
557
558 newStyle &= (~offFlags);
559
560 // change our window style to be compatible with full-screen mode
561 SetWindowLong((HWND)GetHWND(), GWL_STYLE, newStyle);
562
563 // resize to the size of the desktop
564 int width, height;
565
566 RECT rect;
567 ::GetWindowRect(GetDesktopWindow(), &rect);
568 width = rect.right - rect.left;
569 height = rect.bottom - rect.top;
570
571 SetSize(width, height);
572
573 // now flush the window style cache and actually go full-screen
574 SetWindowPos((HWND)GetHWND(), HWND_TOP, 0, 0, width, height, SWP_FRAMECHANGED);
575
576 wxSizeEvent event(wxSize(width, height), GetId());
577 GetEventHandler()->ProcessEvent(event);
578
579 return TRUE;
580 }
581 else
582 {
583 if (!IsFullScreen())
584 return FALSE;
585
586 m_fsIsShowing = FALSE;
587
588 wxToolBar *theToolBar = GetToolBar();
589
590 // restore the toolbar, menubar, and statusbar
591 if (theToolBar && (m_fsStyle & wxFULLSCREEN_NOTOOLBAR))
592 {
593 theToolBar->SetSize(-1, m_fsToolBarHeight);
594 theToolBar->Show(TRUE);
595 }
596
597 if ((m_fsStyle & wxFULLSCREEN_NOSTATUSBAR) && (m_fsStatusBarFields > 0))
598 {
599 CreateStatusBar(m_fsStatusBarFields);
600 PositionStatusBar();
601 }
602
603 if ((m_fsStyle & wxFULLSCREEN_NOMENUBAR) && (m_hMenu != 0))
604 SetMenu((HWND)GetHWND(), (HMENU)m_hMenu);
605
606 Maximize(m_fsIsMaximized);
607 SetWindowLong((HWND)GetHWND(),GWL_STYLE, m_fsOldWindowStyle);
608 SetWindowPos((HWND)GetHWND(),HWND_TOP,m_fsOldSize.x, m_fsOldSize.y,
609 m_fsOldSize.width, m_fsOldSize.height, SWP_FRAMECHANGED);
610
611 return TRUE;
612 }
613}
614
615/*
616 * Frame window
617 *
618 */
619
620bool wxFrame::MSWCreate(int id, wxWindow *parent, const wxChar *wclass, wxWindow *wx_win, const wxChar *title,
621 int x, int y, int width, int height, long style)
622
623{
624 m_defaultIcon = (WXHICON) (wxSTD_FRAME_ICON ? wxSTD_FRAME_ICON : wxDEFAULT_FRAME_ICON);
625
626 // If child windows aren't properly drawn initially, WS_CLIPCHILDREN
627 // could be the culprit. But without it, you can get a lot of flicker.
628
629 DWORD msflags = 0;
630 if ((style & wxCAPTION) == wxCAPTION)
631 msflags = WS_OVERLAPPED;
632 else
633 msflags = WS_POPUP;
634
635 if (style & wxMINIMIZE_BOX)
636 msflags |= WS_MINIMIZEBOX;
637 if (style & wxMAXIMIZE_BOX)
638 msflags |= WS_MAXIMIZEBOX;
639 if (style & wxTHICK_FRAME)
640 msflags |= WS_THICKFRAME;
641 if (style & wxSYSTEM_MENU)
642 msflags |= WS_SYSMENU;
643 if ((style & wxMINIMIZE) || (style & wxICONIZE))
644 msflags |= WS_MINIMIZE;
645 if (style & wxMAXIMIZE)
646 msflags |= WS_MAXIMIZE;
647 if (style & wxCAPTION)
648 msflags |= WS_CAPTION;
649 if (style & wxCLIP_CHILDREN)
650 msflags |= WS_CLIPCHILDREN;
651
652 // Keep this in wxFrame because it saves recoding this function
653 // in wxTinyFrame
654#if wxUSE_ITSY_BITSY && !defined(__WIN32__)
655 if (style & wxTINY_CAPTION_VERT)
656 msflags |= IBS_VERTCAPTION;
657 if (style & wxTINY_CAPTION_HORIZ)
658 msflags |= IBS_HORZCAPTION;
659#else
660 if (style & wxTINY_CAPTION_VERT)
661 msflags |= WS_CAPTION;
662 if (style & wxTINY_CAPTION_HORIZ)
663 msflags |= WS_CAPTION;
664#endif
665 if ((style & wxTHICK_FRAME) == 0)
666 msflags |= WS_BORDER;
667
668 WXDWORD extendedStyle = MakeExtendedStyle(style);
669
670#if !defined(__WIN16__) && !defined(__SC__)
671 if (style & wxFRAME_TOOL_WINDOW)
672 extendedStyle |= WS_EX_TOOLWINDOW;
673#endif
674
675 if (style & wxSTAY_ON_TOP)
676 extendedStyle |= WS_EX_TOPMOST;
677
678 m_iconized = FALSE;
679 if ( !wxWindow::MSWCreate(id, parent, wclass, wx_win, title, x, y, width, height,
680 msflags, NULL, extendedStyle) )
681 return FALSE;
682
683 // Seems to be necessary if we use WS_POPUP
684 // style instead of WS_OVERLAPPED
685 if (width > -1 && height > -1)
686 ::PostMessage(GetHwnd(), WM_SIZE, SIZE_RESTORED, MAKELPARAM(width, height));
687
688 return TRUE;
689}
690
691// Default activation behaviour - set the focus for the first child
692// subwindow found.
693void wxFrame::OnActivate(wxActivateEvent& event)
694{
695 if ( !event.GetActive() )
696 {
697 event.Skip();
698
699 return;
700 }
701
702 wxLogTrace(_T("focus"), _T("wxFrame %08x activated."), m_hWnd);
703
704 for ( wxWindowList::Node *node = GetChildren().GetFirst();
705 node;
706 node = node->GetNext() )
707 {
708 // FIXME all this is totally bogus - we need to do the same as wxPanel,
709 // but how to do it without duplicating the code?
710
711 // restore focus
712 wxWindow *child = node->GetData();
713
714 if ( !child->IsTopLevel()
715#if wxUSE_TOOLBAR
716 && !wxDynamicCast(child, wxToolBar)
717#endif // wxUSE_TOOLBAR
718#if wxUSE_STATUSBAR
719 && !wxDynamicCast(child, wxStatusBar)
720#endif // wxUSE_STATUSBAR
721 )
722 {
723 child->SetFocus();
724 break;
725 }
726 }
727}
728
729// ----------------------------------------------------------------------------
730// tool/status bar stuff
731// ----------------------------------------------------------------------------
732
733#if wxUSE_TOOLBAR
734
735wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
736{
737 if ( wxFrameBase::CreateToolBar(style, id, name) )
738 {
739 PositionToolBar();
740 }
741
742 return m_frameToolBar;
743}
744
745void wxFrame::PositionToolBar()
746{
747 RECT rect;
748 ::GetClientRect(GetHwnd(), &rect);
749
750#if wxUSE_STATUSBAR
751 if ( GetStatusBar() )
752 {
753 int statusX, statusY;
754 GetStatusBar()->GetClientSize(&statusX, &statusY);
755 rect.bottom -= statusY;
756 }
757#endif // wxUSE_STATUSBAR
758
759 if ( GetToolBar() && GetToolBar()->IsShown() )
760 {
761 int tw, th;
762 GetToolBar()->GetSize(&tw, &th);
763
764 if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL )
765 {
766 th = rect.bottom;
767 }
768 else
769 {
770 tw = rect.right;
771 }
772
773 // Use the 'real' MSW position here
774 GetToolBar()->SetSize(0, 0, tw, th, wxSIZE_NO_ADJUSTMENTS);
775 }
776}
777#endif // wxUSE_TOOLBAR
778
779// ----------------------------------------------------------------------------
780// frame state (iconized/maximized/...)
781// ----------------------------------------------------------------------------
782
783// propagate our state change to all child frames: this allows us to emulate X
784// Windows behaviour where child frames float independently of the parent one
785// on the desktop, but are iconized/restored with it
786void wxFrame::IconizeChildFrames(bool bIconize)
787{
788 for ( wxWindowList::Node *node = GetChildren().GetFirst();
789 node;
790 node = node->GetNext() )
791 {
792 wxWindow *win = node->GetData();
793
794 // the child MDI frames are a special case and should not be touched by
795 // the parent frame - instead, they are managed by the user
796 wxFrame *frame = wxDynamicCast(win, wxFrame);
797 if ( frame && !wxDynamicCast(frame, wxMDIChildFrame) )
798 {
799 frame->Iconize(bIconize);
800 }
801 }
802}
803
804// ===========================================================================
805// message processing
806// ===========================================================================
807
808// ---------------------------------------------------------------------------
809// preprocessing
810// ---------------------------------------------------------------------------
811
812bool wxFrame::MSWTranslateMessage(WXMSG* pMsg)
813{
814 if ( wxWindow::MSWTranslateMessage(pMsg) )
815 return TRUE;
816
817 // try the menu bar accels
818 wxMenuBar *menuBar = GetMenuBar();
819 if ( !menuBar )
820 return FALSE;
821
822 const wxAcceleratorTable& acceleratorTable = menuBar->GetAccelTable();
823 return acceleratorTable.Translate(this, pMsg);
824}
825
826// ---------------------------------------------------------------------------
827// our private (non virtual) message handlers
828// ---------------------------------------------------------------------------
829
830bool wxFrame::HandlePaint()
831{
832 RECT rect;
833 if ( GetUpdateRect(GetHwnd(), &rect, FALSE) )
834 {
835 if ( m_iconized )
836 {
837 HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon)
838 : (HICON)m_defaultIcon;
839
840 // Hold a pointer to the dc so long as the OnPaint() message
841 // is being processed
842 PAINTSTRUCT ps;
843 HDC hdc = ::BeginPaint(GetHwnd(), &ps);
844
845 // Erase background before painting or we get white background
846 MSWDefWindowProc(WM_ICONERASEBKGND, (WORD)(LONG)ps.hdc, 0L);
847
848 if ( hIcon )
849 {
850 RECT rect;
851 ::GetClientRect(GetHwnd(), &rect);
852
853 // FIXME: why hardcoded?
854 static const int icon_width = 32;
855 static const int icon_height = 32;
856
857 int icon_x = (int)((rect.right - icon_width)/2);
858 int icon_y = (int)((rect.bottom - icon_height)/2);
859
860 ::DrawIcon(hdc, icon_x, icon_y, hIcon);
861 }
862
863 ::EndPaint(GetHwnd(), &ps);
864
865 return TRUE;
866 }
867 else
868 {
869 return wxWindow::HandlePaint();
870 }
871 }
872 else
873 {
874 // nothing to paint - processed
875 return TRUE;
876 }
877}
878
879bool wxFrame::HandleSize(int x, int y, WXUINT id)
880{
881 bool processed = FALSE;
882
883 switch ( id )
884 {
885 case SIZENORMAL:
886 // only do it it if we were iconized before, otherwise resizing the
887 // parent frame has a curious side effect of bringing it under it's
888 // children
889 if ( !m_iconized )
890 break;
891
892 // restore all child frames too
893 IconizeChildFrames(FALSE);
894
895 // fall through
896
897 case SIZEFULLSCREEN:
898 m_iconized = FALSE;
899 break;
900
901 case SIZEICONIC:
902 // iconize all child frames too
903 IconizeChildFrames(TRUE);
904
905 m_iconized = TRUE;
906 break;
907 }
908
909 if ( !m_iconized )
910 {
911 PositionStatusBar();
912 PositionToolBar();
913
914 wxSizeEvent event(wxSize(x, y), m_windowId);
915 event.SetEventObject( this );
916 processed = GetEventHandler()->ProcessEvent(event);
917 }
918
919 return processed;
920}
921
922bool wxFrame::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control)
923{
924 if ( control )
925 {
926 // In case it's e.g. a toolbar.
927 wxWindow *win = wxFindWinFromHandle(control);
928 if ( win )
929 return win->MSWCommand(cmd, id);
930 }
931
932 // handle here commands from menus and accelerators
933 if ( cmd == 0 || cmd == 1 )
934 {
935 if ( wxCurrentPopupMenu )
936 {
937 wxMenu *popupMenu = wxCurrentPopupMenu;
938 wxCurrentPopupMenu = NULL;
939
940 return popupMenu->MSWCommand(cmd, id);
941 }
942
943 if ( ProcessCommand(id) )
944 {
945 return TRUE;
946 }
947 }
948
949 return FALSE;
950}
951
952bool wxFrame::HandleMenuSelect(WXWORD nItem, WXWORD flags, WXHMENU hMenu)
953{
954 int item;
955 if ( flags == 0xFFFF && hMenu == 0 )
956 {
957 // menu was removed from screen
958 item = -1;
959 }
960 else if ( !(flags & MF_POPUP) && !(flags & MF_SEPARATOR) )
961 {
962 item = nItem;
963 }
964 else
965 {
966 // don't give hints for separators (doesn't make sense) nor for the
967 // items opening popup menus (they don't have them anyhow)
968 return FALSE;
969 }
970
971 wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, item);
972 event.SetEventObject( this );
973
974 return GetEventHandler()->ProcessEvent(event);
975}
976
977// ---------------------------------------------------------------------------
978// the window proc for wxFrame
979// ---------------------------------------------------------------------------
980
981long wxFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
982{
983 long rc = 0;
984 bool processed = FALSE;
985
986 switch ( message )
987 {
988 case WM_CLOSE:
989 // if we can't close, tell the system that we processed the
990 // message - otherwise it would close us
991 processed = !Close();
992 break;
993
994 case WM_COMMAND:
995 {
996 WORD id, cmd;
997 WXHWND hwnd;
998 UnpackCommand((WXWPARAM)wParam, (WXLPARAM)lParam,
999 &id, &hwnd, &cmd);
1000
1001 processed = HandleCommand(id, cmd, (WXHWND)hwnd);
1002 }
1003 break;
1004
1005 case WM_MENUSELECT:
1006 {
1007 WXWORD item, flags;
1008 WXHMENU hmenu;
1009 UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu);
1010
1011 processed = HandleMenuSelect(item, flags, hmenu);
1012 }
1013 break;
1014
1015 case WM_PAINT:
1016 processed = HandlePaint();
1017 break;
1018
1019 case WM_QUERYDRAGICON:
1020 {
1021 HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon)
1022 : (HICON)(m_defaultIcon);
1023 rc = (long)hIcon;
1024 processed = rc != 0;
1025 }
1026 break;
1027
1028 case WM_SIZE:
1029 processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam);
1030 break;
1031 }
1032
1033 if ( !processed )
1034 rc = wxWindow::MSWWindowProc(message, wParam, lParam);
1035
1036 return rc;
1037}
1038