]> git.saurik.com Git - wxWidgets.git/blame - 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
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
7c0ea335 2// Name: msw/frame.cpp
2bda0e17
KB
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
7c0ea335
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
2bda0e17 20#ifdef __GNUG__
7c0ea335 21 #pragma implementation "frame.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
9f3362c4 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
31#ifndef WX_PRECOMP
9f3362c4
VZ
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"
d3cc7c65 40 #include "wx/mdi.h"
9f3362c4 41#endif // WX_PRECOMP
2bda0e17
KB
42
43#include "wx/msw/private.h"
7c0ea335
VZ
44
45#if wxUSE_STATUSBAR
46 #include "wx/statusbr.h"
ed791986 47 #include "wx/generic/statusbr.h"
7c0ea335
VZ
48#endif // wxUSE_STATUSBAR
49
50#if wxUSE_TOOLBAR
51 #include "wx/toolbar.h"
52#endif // wxUSE_TOOLBAR
53
2bda0e17 54#include "wx/menuitem.h"
6776a0b2 55#include "wx/log.h"
2bda0e17 56
7c0ea335
VZ
57// ----------------------------------------------------------------------------
58// globals
59// ----------------------------------------------------------------------------
2bda0e17 60
a23fd0e1 61extern wxWindowList wxModelessWindows;
cde9f08e 62extern wxList WXDLLEXPORT wxPendingDelete;
2ffa221c 63extern const wxChar *wxFrameClassName;
e1a6fc11 64extern wxMenu *wxCurrentPopupMenu;
2bda0e17 65
7c0ea335
VZ
66// ----------------------------------------------------------------------------
67// event tables
68// ----------------------------------------------------------------------------
69
7c0ea335
VZ
70BEGIN_EVENT_TABLE(wxFrame, wxFrameBase)
71 EVT_ACTIVATE(wxFrame::OnActivate)
72 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
2bda0e17
KB
73END_EVENT_TABLE()
74
75IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxWindow)
2bda0e17 76
7c0ea335
VZ
77// ============================================================================
78// implementation
79// ============================================================================
80
81// ----------------------------------------------------------------------------
82// static class members
83// ----------------------------------------------------------------------------
84
47d67540 85#if wxUSE_NATIVE_STATUSBAR
9f3362c4 86 bool wxFrame::m_useNativeStatusBar = TRUE;
2bda0e17 87#else
9f3362c4 88 bool wxFrame::m_useNativeStatusBar = FALSE;
2bda0e17
KB
89#endif
90
7c0ea335
VZ
91// ----------------------------------------------------------------------------
92// creation/destruction
93// ----------------------------------------------------------------------------
2bda0e17 94
7c0ea335 95void wxFrame::Init()
2bda0e17 96{
7c0ea335
VZ
97 m_iconized = FALSE;
98
9f3362c4
VZ
99#if wxUSE_TOOLTIPS
100 m_hwndToolTip = 0;
101#endif
a2327a9f
JS
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;
7c0ea335 112}
9f3362c4 113
7c0ea335
VZ
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{
2bda0e17 122 SetName(name);
2bda0e17
KB
123 m_windowStyle = style;
124 m_frameMenuBar = NULL;
7c0ea335 125 m_frameToolBar = NULL;
2bda0e17
KB
126 m_frameStatusBar = NULL;
127
128 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
129
2bda0e17
KB
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;
d2aef312
VZ
143
144 // we pass NULL as parent to MSWCreate because frames with parents behave
145 // very strangely under Win95 shell
aeab10d0
JS
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
319fefa9
VZ
151 if (!parent)
152 wxTopLevelWindows.Append(this);
153
aeab10d0 154 MSWCreate(m_windowId, parent, wxFrameClassName, this, title,
d2aef312 155 x, y, width, height, style);
2bda0e17
KB
156
157 wxModelessWindows.Append(this);
158 return TRUE;
159}
160
bfc6fde4 161wxFrame::~wxFrame()
2bda0e17
KB
162{
163 m_isBeingDeleted = TRUE;
164 wxTopLevelWindows.DeleteObject(this);
165
7c0ea335 166 DeleteAllBars();
2bda0e17
KB
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.
36e2955a
UM
183 // MT:Only do this if this frame is currently the active window, else weird
184 // things start to happen
185 if ( wxGetActiveWindow() == this )
2bda0e17
KB
186 if (GetParent() && GetParent()->GetHWND())
187 ::BringWindowToTop((HWND) GetParent()->GetHWND());
188}
189
81d66cf3 190// Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
cc2b7472 191void wxFrame::DoGetClientSize(int *x, int *y) const
2bda0e17
KB
192{
193 RECT rect;
42e69d6b 194 ::GetClientRect(GetHwnd(), &rect);
2bda0e17 195
7c0ea335 196#if wxUSE_STATUSBAR
a2327a9f 197 if ( GetStatusBar() && GetStatusBar()->IsShown() )
2bda0e17 198 {
81d66cf3
JS
199 int statusX, statusY;
200 GetStatusBar()->GetClientSize(&statusX, &statusY);
201 rect.bottom -= statusY;
2bda0e17 202 }
7c0ea335 203#endif // wxUSE_STATUSBAR
81d66cf3
JS
204
205 wxPoint pt(GetClientAreaOrigin());
206 rect.bottom -= pt.y;
207 rect.right -= pt.x;
208
0655ad29
VZ
209 if ( x )
210 *x = rect.right;
211 if ( y )
212 *y = rect.bottom;
2bda0e17
KB
213}
214
215// Set the client size (i.e. leave the calculation of borders etc.
216// to wxWindows)
bfc6fde4 217void wxFrame::DoSetClientSize(int width, int height)
2bda0e17 218{
42e69d6b 219 HWND hWnd = GetHwnd();
2bda0e17
KB
220
221 RECT rect;
2de8030d 222 ::GetClientRect(hWnd, &rect);
2bda0e17
KB
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
7c0ea335 233#if wxUSE_STATUSBAR
a2327a9f 234 if ( GetStatusBar() && GetStatusBar()->IsShown())
2bda0e17 235 {
81d66cf3
JS
236 int statusX, statusY;
237 GetStatusBar()->GetClientSize(&statusX, &statusY);
238 actual_height += statusY;
2bda0e17 239 }
7c0ea335 240#endif // wxUSE_STATUSBAR
2bda0e17 241
81d66cf3
JS
242 wxPoint pt(GetClientAreaOrigin());
243 actual_width += pt.y;
244 actual_height += pt.x;
245
2bda0e17
KB
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);
debe6624 251
2bda0e17
KB
252 wxSizeEvent event(wxSize(width, height), m_windowId);
253 event.SetEventObject( this );
254 GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
255}
256
cc2b7472 257void wxFrame::DoGetSize(int *width, int *height) const
2bda0e17
KB
258{
259 RECT rect;
42e69d6b 260 GetWindowRect(GetHwnd(), &rect);
2bda0e17
KB
261 *width = rect.right - rect.left;
262 *height = rect.bottom - rect.top;
263}
264
cc2b7472 265void wxFrame::DoGetPosition(int *x, int *y) const
2bda0e17
KB
266{
267 RECT rect;
42e69d6b 268 GetWindowRect(GetHwnd(), &rect);
2bda0e17
KB
269 POINT point;
270 point.x = rect.left;
271 point.y = rect.top;
272
273 *x = point.x;
274 *y = point.y;
275}
276
7c0ea335
VZ
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
debe6624 288bool wxFrame::Show(bool show)
2bda0e17 289{
7c0ea335 290 DoShowWindow(show ? SW_SHOW : SW_HIDE);
2bda0e17 291
7c0ea335 292 if ( show )
2bda0e17 293 {
7c0ea335 294 ::BringWindowToTop(GetHwnd());
2bda0e17 295
7c0ea335
VZ
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 }
2bda0e17 310
7c0ea335 311 return TRUE;
2bda0e17
KB
312}
313
debe6624 314void wxFrame::Iconize(bool iconize)
2bda0e17 315{
7c0ea335 316 DoShowWindow(iconize ? SW_MINIMIZE : SW_RESTORE);
2bda0e17
KB
317}
318
debe6624 319void wxFrame::Maximize(bool maximize)
2bda0e17 320{
7c0ea335
VZ
321 DoShowWindow(maximize ? SW_MAXIMIZE : SW_RESTORE);
322}
323
324void wxFrame::Restore()
325{
326 DoShowWindow(SW_RESTORE);
2bda0e17
KB
327}
328
bfc6fde4 329bool wxFrame::IsIconized() const
2bda0e17 330{
42e69d6b 331 ((wxFrame *)this)->m_iconized = (::IsIconic(GetHwnd()) != 0);
2bda0e17
KB
332 return m_iconized;
333}
334
6f63ec3f 335// Is it maximized?
bfc6fde4 336bool wxFrame::IsMaximized() const
6f63ec3f 337{
7c0ea335 338 return (::IsZoomed(GetHwnd()) != 0);
2bda0e17
KB
339}
340
341void wxFrame::SetIcon(const wxIcon& icon)
342{
7c0ea335
VZ
343 wxFrameBase::SetIcon(icon);
344
2bda0e17 345#if defined(__WIN95__)
7c0ea335
VZ
346 if ( m_icon.Ok() )
347 {
348 SendMessage(GetHwnd(), WM_SETICON,
349 (WPARAM)TRUE, (LPARAM)(HICON) m_icon.GetHICON());
350 }
351#endif // __WIN95__
2bda0e17
KB
352}
353
d427503c 354#if wxUSE_STATUSBAR
7c0ea335
VZ
355wxStatusBar *wxFrame::OnCreateStatusBar(int number,
356 long style,
357 wxWindowID id,
358 const wxString& name)
2bda0e17
KB
359{
360 wxStatusBar *statusBar = NULL;
361
47d67540 362#if wxUSE_NATIVE_STATUSBAR
7c0ea335 363 if ( UsesNativeStatusBar() )
2bda0e17 364 {
ed791986 365 statusBar = (wxStatusBar *)new wxStatusBar95(this, id, style);
0d0512bd
VZ
366
367 statusBar->SetFieldsCount(number);
2bda0e17
KB
368 }
369 else
370#endif
371 {
ed791986
VZ
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);
2bda0e17
KB
386 }
387
7c0ea335 388 return statusBar;
2bda0e17
KB
389}
390
bfc6fde4 391void wxFrame::PositionStatusBar()
2bda0e17 392{
ed791986
VZ
393 if ( !m_frameStatusBar )
394 return;
395
cbc66a27
VZ
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);
2bda0e17 404}
d427503c 405#endif // wxUSE_STATUSBAR
2bda0e17 406
ea9a4296
UM
407void wxFrame::DetachMenuBar()
408{
409 if (m_frameMenuBar)
410 {
411 m_frameMenuBar->Detach();
412 m_frameMenuBar = NULL;
413 }
414}
415
2bda0e17
KB
416void wxFrame::SetMenuBar(wxMenuBar *menu_bar)
417{
c2dcfdef
VZ
418 if (!menu_bar)
419 {
ea9a4296 420 DetachMenuBar();
c2dcfdef
VZ
421 return;
422 }
2bda0e17 423
065de612
JS
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
223d09f6 456 wxCHECK_RET( !menu_bar->GetFrame(), wxT("this menubar is already attached") );
2bda0e17 457
c2dcfdef
VZ
458 if (m_frameMenuBar)
459 delete m_frameMenuBar;
2bda0e17 460
c2dcfdef 461 m_hMenu = menu_bar->Create();
2bda0e17 462
c2dcfdef
VZ
463 if ( !m_hMenu )
464 return;
2bda0e17 465
42e69d6b 466 InternalSetMenuBar();
2bda0e17 467
c2dcfdef
VZ
468 m_frameMenuBar = menu_bar;
469 menu_bar->Attach(this);
065de612 470#endif
2bda0e17
KB
471}
472
42e69d6b 473void wxFrame::InternalSetMenuBar()
2bda0e17 474{
42e69d6b 475 if ( !::SetMenu(GetHwnd(), (HMENU)m_hMenu) )
2bda0e17 476 {
42e69d6b 477 wxLogLastError("SetMenu");
2bda0e17 478 }
2bda0e17
KB
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 );
02800301 491 m_frameStatusBar->GetEventHandler()->ProcessEvent(event2);
2bda0e17
KB
492 }
493
494 // Propagate the event to the non-top-level children
495 wxWindow::OnSysColourChanged(event);
496}
497
a2327a9f
JS
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
2bda0e17
KB
615/*
616 * Frame window
617 *
618 */
619
837e5743 620bool wxFrame::MSWCreate(int id, wxWindow *parent, const wxChar *wclass, wxWindow *wx_win, const wxChar *title,
debe6624 621 int x, int y, int width, int height, long style)
2bda0e17
KB
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
2bda0e17
KB
629 DWORD msflags = 0;
630 if ((style & wxCAPTION) == wxCAPTION)
1c089c47 631 msflags = WS_OVERLAPPED;
2bda0e17 632 else
1c089c47 633 msflags = WS_POPUP;
2bda0e17
KB
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;
1c089c47
JS
649 if (style & wxCLIP_CHILDREN)
650 msflags |= WS_CLIPCHILDREN;
2bda0e17
KB
651
652 // Keep this in wxFrame because it saves recoding this function
653 // in wxTinyFrame
8355a72f 654#if wxUSE_ITSY_BITSY && !defined(__WIN32__)
2bda0e17
KB
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
2432b92d 670#if !defined(__WIN16__) && !defined(__SC__)
cd2df130
JS
671 if (style & wxFRAME_TOOL_WINDOW)
672 extendedStyle |= WS_EX_TOOLWINDOW;
1e6d9499 673#endif
cd2df130 674
2bda0e17
KB
675 if (style & wxSTAY_ON_TOP)
676 extendedStyle |= WS_EX_TOPMOST;
677
678 m_iconized = FALSE;
a23fd0e1
VZ
679 if ( !wxWindow::MSWCreate(id, parent, wclass, wx_win, title, x, y, width, height,
680 msflags, NULL, extendedStyle) )
681 return FALSE;
682
2bda0e17
KB
683 // Seems to be necessary if we use WS_POPUP
684 // style instead of WS_OVERLAPPED
685 if (width > -1 && height > -1)
42e69d6b 686 ::PostMessage(GetHwnd(), WM_SIZE, SIZE_RESTORED, MAKELPARAM(width, height));
a23fd0e1
VZ
687
688 return TRUE;
2bda0e17
KB
689}
690
2bda0e17
KB
691// Default activation behaviour - set the focus for the first child
692// subwindow found.
693void wxFrame::OnActivate(wxActivateEvent& event)
694{
00c4e897
VZ
695 if ( !event.GetActive() )
696 {
697 event.Skip();
698
699 return;
700 }
701
702 wxLogTrace(_T("focus"), _T("wxFrame %08x activated."), m_hWnd);
703
319fefa9
VZ
704 for ( wxWindowList::Node *node = GetChildren().GetFirst();
705 node;
706 node = node->GetNext() )
2bda0e17 707 {
319fefa9
VZ
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();
00c4e897 724 break;
319fefa9 725 }
2bda0e17 726 }
2bda0e17
KB
727}
728
7c0ea335
VZ
729// ----------------------------------------------------------------------------
730// tool/status bar stuff
731// ----------------------------------------------------------------------------
732
d427503c 733#if wxUSE_TOOLBAR
7c0ea335 734
81d66cf3
JS
735wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
736{
7c0ea335 737 if ( wxFrameBase::CreateToolBar(style, id, name) )
81d66cf3 738 {
81d66cf3 739 PositionToolBar();
81d66cf3 740 }
81d66cf3 741
7c0ea335 742 return m_frameToolBar;
81d66cf3
JS
743}
744
bfc6fde4 745void wxFrame::PositionToolBar()
81d66cf3 746{
81d66cf3 747 RECT rect;
42e69d6b 748 ::GetClientRect(GetHwnd(), &rect);
81d66cf3 749
7c0ea335 750#if wxUSE_STATUSBAR
81d66cf3
JS
751 if ( GetStatusBar() )
752 {
7c0ea335
VZ
753 int statusX, statusY;
754 GetStatusBar()->GetClientSize(&statusX, &statusY);
755 rect.bottom -= statusY;
81d66cf3 756 }
7c0ea335 757#endif // wxUSE_STATUSBAR
81d66cf3 758
a2327a9f 759 if ( GetToolBar() && GetToolBar()->IsShown() )
81d66cf3
JS
760 {
761 int tw, th;
7c0ea335 762 GetToolBar()->GetSize(&tw, &th);
81d66cf3 763
7c0ea335 764 if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL )
81d66cf3 765 {
7c0ea335 766 th = rect.bottom;
81d66cf3
JS
767 }
768 else
769 {
7c0ea335 770 tw = rect.right;
81d66cf3 771 }
7c0ea335
VZ
772
773 // Use the 'real' MSW position here
774 GetToolBar()->SetSize(0, 0, tw, th, wxSIZE_NO_ADJUSTMENTS);
81d66cf3
JS
775 }
776}
d427503c 777#endif // wxUSE_TOOLBAR
d2aef312 778
7c0ea335
VZ
779// ----------------------------------------------------------------------------
780// frame state (iconized/maximized/...)
781// ----------------------------------------------------------------------------
782
a23fd0e1
VZ
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
d2aef312
VZ
786void wxFrame::IconizeChildFrames(bool bIconize)
787{
a23fd0e1
VZ
788 for ( wxWindowList::Node *node = GetChildren().GetFirst();
789 node;
790 node = node->GetNext() )
791 {
792 wxWindow *win = node->GetData();
793
3f7bc32b
VZ
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) )
a23fd0e1 798 {
3f7bc32b 799 frame->Iconize(bIconize);
a23fd0e1 800 }
d2aef312 801 }
d2aef312
VZ
802}
803
a23fd0e1 804// ===========================================================================
42e69d6b 805// message processing
a23fd0e1
VZ
806// ===========================================================================
807
42e69d6b
VZ
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();
c50f1fb9 823 return acceleratorTable.Translate(this, pMsg);
42e69d6b
VZ
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 {
c50f1fb9 837 HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon)
42e69d6b
VZ
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 {
5d1d2d46 869 return wxWindow::HandlePaint();
42e69d6b
VZ
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 {
42e69d6b
VZ
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
c219cecc 952bool wxFrame::HandleMenuSelect(WXWORD nItem, WXWORD flags, WXHMENU hMenu)
a23fd0e1
VZ
953{
954 int item;
c219cecc 955 if ( flags == 0xFFFF && hMenu == 0 )
a23fd0e1 956 {
c219cecc 957 // menu was removed from screen
a23fd0e1
VZ
958 item = -1;
959 }
c219cecc 960 else if ( !(flags & MF_POPUP) && !(flags & MF_SEPARATOR) )
a23fd0e1
VZ
961 {
962 item = nItem;
963 }
964 else
965 {
c219cecc
VZ
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)
a23fd0e1
VZ
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 {
42e69d6b
VZ
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
a23fd0e1
VZ
1005 case WM_MENUSELECT:
1006 {
42e69d6b
VZ
1007 WXWORD item, flags;
1008 WXHMENU hmenu;
1009 UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu);
1010
1011 processed = HandleMenuSelect(item, flags, hmenu);
a23fd0e1
VZ
1012 }
1013 break;
42e69d6b
VZ
1014
1015 case WM_PAINT:
1016 processed = HandlePaint();
1017 break;
1018
1019 case WM_QUERYDRAGICON:
1020 {
c50f1fb9 1021 HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon)
42e69d6b
VZ
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;
a23fd0e1
VZ
1031 }
1032
1033 if ( !processed )
1034 rc = wxWindow::MSWWindowProc(message, wParam, lParam);
1035
1036 return rc;
1037}
21802234 1038