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