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