]> git.saurik.com Git - wxWidgets.git/blob - src/msw/frame.cpp
wxInputConsumer
[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::Raise()
351 {
352 #ifdef __WIN16__
353 // no SetForegroundWindow() in Win16
354 wxFrameBase::Raise();
355 #else // Win32
356 ::SetForegroundWindow(GetHwnd());
357 #endif // Win16/32
358 }
359
360 void wxFrameMSW::Iconize(bool iconize)
361 {
362 DoShowWindow(iconize ? SW_MINIMIZE : SW_RESTORE);
363 }
364
365 void wxFrameMSW::Maximize(bool maximize)
366 {
367 if ( IsShown() )
368 {
369 // just maximize it directly
370 DoShowWindow(maximize ? SW_MAXIMIZE : SW_RESTORE);
371 }
372 else // hidden
373 {
374 // we can't maximize the hidden frame because it shows it as well, so
375 // just remember that we should do it later in this case
376 m_maximizeOnShow = TRUE;
377 }
378 }
379
380 void wxFrameMSW::Restore()
381 {
382 DoShowWindow(SW_RESTORE);
383 }
384
385 bool wxFrameMSW::IsIconized() const
386 {
387 #ifdef __WXMICROWIN__
388 // TODO
389 return FALSE;
390 #else
391 ((wxFrameMSW *)this)->m_iconized = (::IsIconic(GetHwnd()) != 0);
392 return m_iconized;
393 #endif
394 }
395
396 // Is it maximized?
397 bool wxFrameMSW::IsMaximized() const
398 {
399 #ifdef __WXMICROWIN__
400 // TODO
401 return FALSE;
402 #else
403 return (::IsZoomed(GetHwnd()) != 0);
404 #endif
405 }
406
407 void wxFrameMSW::SetIcon(const wxIcon& icon)
408 {
409 wxFrameBase::SetIcon(icon);
410
411 #if defined(__WIN95__) && !defined(__WXMICROWIN__)
412 if ( m_icon.Ok() )
413 {
414 SendMessage(GetHwnd(), WM_SETICON,
415 (WPARAM)TRUE, (LPARAM)(HICON) m_icon.GetHICON());
416 }
417 #endif // __WIN95__
418 }
419
420 // generate an artificial resize event
421 void wxFrameMSW::SendSizeEvent()
422 {
423 RECT r;
424 #ifdef __WIN16__
425 ::GetWindowRect(GetHwnd(), &r);
426 #else
427 if ( !::GetWindowRect(GetHwnd(), &r) )
428 {
429 wxLogLastError(_T("GetWindowRect"));
430 }
431 #endif
432
433 if ( !m_iconized )
434 {
435 (void)::PostMessage(GetHwnd(), WM_SIZE,
436 IsMaximized() ? SIZE_MAXIMIZED : SIZE_RESTORED,
437 MAKELPARAM(r.right - r.left, r.bottom - r.top));
438 }
439 }
440
441 #if wxUSE_STATUSBAR
442 wxStatusBar *wxFrameMSW::OnCreateStatusBar(int number,
443 long style,
444 wxWindowID id,
445 const wxString& name)
446 {
447 wxStatusBar *statusBar = NULL;
448
449 #if wxUSE_NATIVE_STATUSBAR
450 if ( !UsesNativeStatusBar() )
451 {
452 statusBar = (wxStatusBar *)new wxStatusBarGeneric(this, id, style);
453 }
454 else
455 #endif
456 {
457 statusBar = new wxStatusBar(this, id, style, name);
458 }
459
460 // Set the height according to the font and the border size
461 wxClientDC dc(statusBar);
462 dc.SetFont(statusBar->GetFont());
463
464 wxCoord y;
465 dc.GetTextExtent(_T("X"), NULL, &y );
466
467 int height = (int)( (11*y)/10 + 2*statusBar->GetBorderY());
468
469 statusBar->SetSize(-1, -1, -1, height);
470
471 statusBar->SetFieldsCount(number);
472
473 return statusBar;
474 }
475
476 void wxFrameMSW::PositionStatusBar()
477 {
478 if ( !m_frameStatusBar )
479 return;
480
481 int w, h;
482 GetClientSize(&w, &h);
483 int sw, sh;
484 m_frameStatusBar->GetSize(&sw, &sh);
485
486 // Since we wish the status bar to be directly under the client area,
487 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
488 m_frameStatusBar->SetSize(0, h, w, sh);
489 }
490 #endif // wxUSE_STATUSBAR
491
492 #if wxUSE_MENUS_NATIVE
493
494 void wxFrameMSW::AttachMenuBar(wxMenuBar *menubar)
495 {
496 wxFrameBase::AttachMenuBar(menubar);
497
498 if ( !menubar )
499 {
500 // actually remove the menu from the frame
501 m_hMenu = (WXHMENU)0;
502 InternalSetMenuBar();
503 }
504 else // set new non NULL menu bar
505 {
506 // Can set a menubar several times.
507 if ( menubar->GetHMenu() )
508 {
509 m_hMenu = menubar->GetHMenu();
510 }
511 else // no HMENU yet
512 {
513 m_hMenu = menubar->Create();
514
515 if ( !m_hMenu )
516 {
517 wxFAIL_MSG( _T("failed to create menu bar") );
518 return;
519 }
520 }
521
522 InternalSetMenuBar();
523 }
524 }
525
526 void wxFrameMSW::InternalSetMenuBar()
527 {
528 #ifndef __WXMICROWIN__
529 if ( !::SetMenu(GetHwnd(), (HMENU)m_hMenu) )
530 {
531 wxLogLastError(wxT("SetMenu"));
532 }
533 #endif
534 }
535
536 #endif // wxUSE_MENUS_NATIVE
537
538 // Responds to colour changes, and passes event on to children.
539 void wxFrameMSW::OnSysColourChanged(wxSysColourChangedEvent& event)
540 {
541 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
542 Refresh();
543
544 #if wxUSE_STATUSBAR
545 if ( m_frameStatusBar )
546 {
547 wxSysColourChangedEvent event2;
548 event2.SetEventObject( m_frameStatusBar );
549 m_frameStatusBar->GetEventHandler()->ProcessEvent(event2);
550 }
551 #endif // wxUSE_STATUSBAR
552
553 // Propagate the event to the non-top-level children
554 wxWindow::OnSysColourChanged(event);
555 }
556
557 // Pass TRUE to show full screen, FALSE to restore.
558 bool wxFrameMSW::ShowFullScreen(bool show, long style)
559 {
560 if (show)
561 {
562 if (IsFullScreen())
563 return FALSE;
564
565 m_fsIsShowing = TRUE;
566 m_fsStyle = style;
567
568 #if wxUSE_TOOLBAR
569 wxToolBar *theToolBar = GetToolBar();
570 if (theToolBar)
571 theToolBar->GetSize(NULL, &m_fsToolBarHeight);
572
573 // zap the toolbar, menubar, and statusbar
574
575 if ((style & wxFULLSCREEN_NOTOOLBAR) && theToolBar)
576 {
577 theToolBar->SetSize(-1,0);
578 theToolBar->Show(FALSE);
579 }
580 #endif // wxUSE_TOOLBAR
581
582 #ifndef __WXMICROWIN__
583 if (style & wxFULLSCREEN_NOMENUBAR)
584 SetMenu((HWND)GetHWND(), (HMENU) NULL);
585 #endif
586
587 #if wxUSE_STATUSBAR
588 wxStatusBar *theStatusBar = GetStatusBar();
589 if (theStatusBar)
590 theStatusBar->GetSize(NULL, &m_fsStatusBarHeight);
591
592 // Save the number of fields in the statusbar
593 if ((style & wxFULLSCREEN_NOSTATUSBAR) && theStatusBar)
594 {
595 //m_fsStatusBarFields = theStatusBar->GetFieldsCount();
596 //SetStatusBar((wxStatusBar*) NULL);
597 //delete theStatusBar;
598 theStatusBar->Show(FALSE);
599 }
600 else
601 m_fsStatusBarFields = 0;
602 #endif // wxUSE_STATUSBAR
603
604 // zap the frame borders
605
606 // save the 'normal' window style
607 m_fsOldWindowStyle = GetWindowLong((HWND)GetHWND(), GWL_STYLE);
608
609 // save the old position, width & height, maximize state
610 m_fsOldSize = GetRect();
611 m_fsIsMaximized = IsMaximized();
612
613 // decide which window style flags to turn off
614 LONG newStyle = m_fsOldWindowStyle;
615 LONG offFlags = 0;
616
617 if (style & wxFULLSCREEN_NOBORDER)
618 offFlags |= WS_BORDER | WS_THICKFRAME;
619 if (style & wxFULLSCREEN_NOCAPTION)
620 offFlags |= (WS_CAPTION | WS_SYSMENU);
621
622 newStyle &= (~offFlags);
623
624 // change our window style to be compatible with full-screen mode
625 SetWindowLong((HWND)GetHWND(), GWL_STYLE, newStyle);
626
627 // resize to the size of the desktop
628 int width, height;
629
630 RECT rect;
631 ::GetWindowRect(GetDesktopWindow(), &rect);
632 width = rect.right - rect.left;
633 height = rect.bottom - rect.top;
634
635 SetSize(width, height);
636
637 // now flush the window style cache and actually go full-screen
638 SetWindowPos((HWND)GetHWND(), HWND_TOP, 0, 0, width, height, SWP_FRAMECHANGED);
639
640 wxSizeEvent event(wxSize(width, height), GetId());
641 GetEventHandler()->ProcessEvent(event);
642
643 return TRUE;
644 }
645 else
646 {
647 if (!IsFullScreen())
648 return FALSE;
649
650 m_fsIsShowing = FALSE;
651
652 #if wxUSE_TOOLBAR
653 wxToolBar *theToolBar = GetToolBar();
654
655 // restore the toolbar, menubar, and statusbar
656 if (theToolBar && (m_fsStyle & wxFULLSCREEN_NOTOOLBAR))
657 {
658 theToolBar->SetSize(-1, m_fsToolBarHeight);
659 theToolBar->Show(TRUE);
660 }
661 #endif // wxUSE_TOOLBAR
662
663 #if wxUSE_STATUSBAR
664 if ( m_fsStyle & wxFULLSCREEN_NOSTATUSBAR )
665 {
666 //CreateStatusBar(m_fsStatusBarFields);
667 if (GetStatusBar())
668 {
669 GetStatusBar()->Show(TRUE);
670 PositionStatusBar();
671 }
672 }
673 #endif // wxUSE_STATUSBAR
674
675 #ifndef __WXMICROWIN__
676 if ((m_fsStyle & wxFULLSCREEN_NOMENUBAR) && (m_hMenu != 0))
677 SetMenu((HWND)GetHWND(), (HMENU)m_hMenu);
678 #endif
679
680 Maximize(m_fsIsMaximized);
681 SetWindowLong((HWND)GetHWND(),GWL_STYLE, m_fsOldWindowStyle);
682 SetWindowPos((HWND)GetHWND(),HWND_TOP,m_fsOldSize.x, m_fsOldSize.y,
683 m_fsOldSize.width, m_fsOldSize.height, SWP_FRAMECHANGED);
684
685 return TRUE;
686 }
687 }
688
689 /*
690 * Frame window
691 *
692 */
693
694 bool wxFrameMSW::MSWCreate(int id, wxWindow *parent, const wxChar *wclass, wxWindow *wx_win, const wxChar *title,
695 int x, int y, int width, int height, long style)
696
697 {
698 m_defaultIcon = (WXHICON) (wxSTD_FRAME_ICON ? wxSTD_FRAME_ICON : wxDEFAULT_FRAME_ICON);
699
700 // If child windows aren't properly drawn initially, WS_CLIPCHILDREN
701 // could be the culprit. But without it, you can get a lot of flicker.
702
703 DWORD msflags = 0;
704 if ( style & wxCAPTION )
705 {
706 if ( style & wxFRAME_TOOL_WINDOW )
707 msflags |= WS_POPUPWINDOW;
708 else
709 msflags |= WS_OVERLAPPED;
710 }
711 else
712 {
713 msflags |= WS_POPUP;
714 }
715
716 if (style & wxMINIMIZE_BOX)
717 msflags |= WS_MINIMIZEBOX;
718 if (style & wxMAXIMIZE_BOX)
719 msflags |= WS_MAXIMIZEBOX;
720 if (style & wxTHICK_FRAME)
721 msflags |= WS_THICKFRAME;
722 if (style & wxSYSTEM_MENU)
723 msflags |= WS_SYSMENU;
724 if ( style & wxMINIMIZE )
725 msflags |= WS_MINIMIZE;
726 if (style & wxMAXIMIZE)
727 msflags |= WS_MAXIMIZE;
728 if (style & wxCAPTION)
729 msflags |= WS_CAPTION;
730 if (style & wxCLIP_CHILDREN)
731 msflags |= WS_CLIPCHILDREN;
732
733 // Keep this in wxFrameMSW because it saves recoding this function
734 // in wxTinyFrame
735 #if wxUSE_ITSY_BITSY && !defined(__WIN32__)
736 if (style & wxTINY_CAPTION_VERT)
737 msflags |= IBS_VERTCAPTION;
738 if (style & wxTINY_CAPTION_HORIZ)
739 msflags |= IBS_HORZCAPTION;
740 #else
741 if (style & wxTINY_CAPTION_VERT)
742 msflags |= WS_CAPTION;
743 if (style & wxTINY_CAPTION_HORIZ)
744 msflags |= WS_CAPTION;
745 #endif
746 if ((style & wxTHICK_FRAME) == 0)
747 msflags |= WS_BORDER;
748
749 WXDWORD extendedStyle = MakeExtendedStyle(style);
750
751 // make all frames appear in the win9x shell taskbar unless
752 // wxFRAME_TOOL_WINDOW or wxFRAME_NO_TASKBAR is given - without giving them
753 // WS_EX_APPWINDOW style, the child (i.e. owned) frames wouldn't appear in it
754 #if !defined(__WIN16__) && !defined(__SC__)
755 if ( (style & wxFRAME_TOOL_WINDOW) ||
756 (style & wxFRAME_NO_TASKBAR) )
757 extendedStyle |= WS_EX_TOOLWINDOW;
758 else if ( !(style & wxFRAME_NO_TASKBAR) )
759 extendedStyle |= WS_EX_APPWINDOW;
760 #endif
761
762 if (style & wxSTAY_ON_TOP)
763 extendedStyle |= WS_EX_TOPMOST;
764
765 #ifndef __WIN16__
766 if (m_exStyle & wxFRAME_EX_CONTEXTHELP)
767 extendedStyle |= WS_EX_CONTEXTHELP;
768 #endif
769
770 m_iconized = FALSE;
771 if ( !wxWindow::MSWCreate(id, parent, wclass, wx_win, title, x, y, width, height,
772 msflags, NULL, extendedStyle) )
773 return FALSE;
774
775 // Seems to be necessary if we use WS_POPUP
776 // style instead of WS_OVERLAPPED
777 if (width > -1 && height > -1)
778 ::PostMessage(GetHwnd(), WM_SIZE, SIZE_RESTORED, MAKELPARAM(width, height));
779
780 return TRUE;
781 }
782
783 // Default activation behaviour - set the focus for the first child
784 // subwindow found.
785 void wxFrameMSW::OnActivate(wxActivateEvent& event)
786 {
787 if ( event.GetActive() )
788 {
789 // restore focus to the child which was last focused
790 wxLogTrace(_T("focus"), _T("wxFrameMSW %08x activated."), m_hWnd);
791
792 wxWindow *parent = m_winLastFocused ? m_winLastFocused->GetParent()
793 : NULL;
794 if ( !parent )
795 {
796 parent = this;
797 }
798
799 wxSetFocusToChild(parent, &m_winLastFocused);
800 }
801 else // deactivating
802 {
803 // remember the last focused child if it is our child
804 m_winLastFocused = FindFocus();
805
806 // so we NULL it out if it's a child from some other frame
807 wxWindow *win = m_winLastFocused;
808 while ( win )
809 {
810 if ( win->IsTopLevel() )
811 {
812 if ( win != this )
813 {
814 m_winLastFocused = NULL;
815 }
816
817 break;
818 }
819
820 win = win->GetParent();
821 }
822
823 wxLogTrace(_T("focus"),
824 _T("wxFrameMSW %08x deactivated, last focused: %08x."),
825 m_hWnd,
826 m_winLastFocused ? GetHwndOf(m_winLastFocused)
827 : NULL);
828
829 event.Skip();
830 }
831 }
832
833 // ----------------------------------------------------------------------------
834 // tool/status bar stuff
835 // ----------------------------------------------------------------------------
836
837 #if wxUSE_TOOLBAR
838
839 wxToolBar* wxFrameMSW::CreateToolBar(long style, wxWindowID id, const wxString& name)
840 {
841 if ( wxFrameBase::CreateToolBar(style, id, name) )
842 {
843 PositionToolBar();
844 }
845
846 return m_frameToolBar;
847 }
848
849 void wxFrameMSW::PositionToolBar()
850 {
851 RECT rect;
852 ::GetClientRect(GetHwnd(), &rect);
853
854 #if wxUSE_STATUSBAR
855 if ( GetStatusBar() )
856 {
857 int statusX, statusY;
858 GetStatusBar()->GetClientSize(&statusX, &statusY);
859 rect.bottom -= statusY;
860 }
861 #endif // wxUSE_STATUSBAR
862
863 if ( GetToolBar() && GetToolBar()->IsShown() )
864 {
865 int tw, th;
866 GetToolBar()->GetSize(&tw, &th);
867
868 if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL )
869 {
870 th = rect.bottom;
871 }
872 else
873 {
874 tw = rect.right;
875 }
876
877 // Use the 'real' MSW position here
878 GetToolBar()->SetSize(0, 0, tw, th, wxSIZE_NO_ADJUSTMENTS);
879 }
880 }
881 #endif // wxUSE_TOOLBAR
882
883 // ----------------------------------------------------------------------------
884 // frame state (iconized/maximized/...)
885 // ----------------------------------------------------------------------------
886
887 // propagate our state change to all child frames: this allows us to emulate X
888 // Windows behaviour where child frames float independently of the parent one
889 // on the desktop, but are iconized/restored with it
890 void wxFrameMSW::IconizeChildFrames(bool bIconize)
891 {
892 for ( wxWindowList::Node *node = GetChildren().GetFirst();
893 node;
894 node = node->GetNext() )
895 {
896 wxWindow *win = node->GetData();
897
898 // iconizing the frames with this style under Win95 shell puts them at
899 // the bottom of the screen (as the MDI children) instead of making
900 // them appear in the taskbar because they are, by virtue of this
901 // style, not managed by the taskbar - instead leave Windows take care
902 // of them
903 #ifdef __WIN95__
904 if ( win->GetWindowStyle() & wxFRAME_TOOL_WINDOW )
905 continue;
906 #endif // Win95
907
908 // the child MDI frames are a special case and should not be touched by
909 // the parent frame - instead, they are managed by the user
910 wxFrameMSW *frame = wxDynamicCast(win, wxFrame);
911 if ( frame
912 #if wxUSE_MDI_ARCHITECTURE
913 && !wxDynamicCast(frame, wxMDIChildFrame)
914 #endif // wxUSE_MDI_ARCHITECTURE
915 )
916 {
917 frame->Iconize(bIconize);
918 }
919 }
920 }
921
922 // ===========================================================================
923 // message processing
924 // ===========================================================================
925
926 // ---------------------------------------------------------------------------
927 // preprocessing
928 // ---------------------------------------------------------------------------
929
930 bool wxFrameMSW::MSWTranslateMessage(WXMSG* pMsg)
931 {
932 if ( wxWindow::MSWTranslateMessage(pMsg) )
933 return TRUE;
934
935 #if wxUSE_MENUS && wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
936 // try the menu bar accels
937 wxMenuBar *menuBar = GetMenuBar();
938 if ( !menuBar )
939 return FALSE;
940
941 const wxAcceleratorTable& acceleratorTable = menuBar->GetAccelTable();
942 return acceleratorTable.Translate(this, pMsg);
943 #else
944 return FALSE;
945 #endif // wxUSE_MENUS && wxUSE_ACCEL
946 }
947
948 // ---------------------------------------------------------------------------
949 // our private (non virtual) message handlers
950 // ---------------------------------------------------------------------------
951
952 bool wxFrameMSW::HandlePaint()
953 {
954 RECT rect;
955 if ( GetUpdateRect(GetHwnd(), &rect, FALSE) )
956 {
957 #ifndef __WXMICROWIN__
958 if ( m_iconized )
959 {
960 HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon)
961 : (HICON)m_defaultIcon;
962
963 // Hold a pointer to the dc so long as the OnPaint() message
964 // is being processed
965 PAINTSTRUCT ps;
966 HDC hdc = ::BeginPaint(GetHwnd(), &ps);
967
968 // Erase background before painting or we get white background
969 MSWDefWindowProc(WM_ICONERASEBKGND, (WORD)(LONG)ps.hdc, 0L);
970
971 if ( hIcon )
972 {
973 RECT rect;
974 ::GetClientRect(GetHwnd(), &rect);
975
976 // FIXME: why hardcoded?
977 static const int icon_width = 32;
978 static const int icon_height = 32;
979
980 int icon_x = (int)((rect.right - icon_width)/2);
981 int icon_y = (int)((rect.bottom - icon_height)/2);
982
983 ::DrawIcon(hdc, icon_x, icon_y, hIcon);
984 }
985
986 ::EndPaint(GetHwnd(), &ps);
987
988 return TRUE;
989 }
990 else
991 #endif
992 {
993 return wxWindow::HandlePaint();
994 }
995 }
996 else
997 {
998 // nothing to paint - processed
999 return TRUE;
1000 }
1001 }
1002
1003 bool wxFrameMSW::HandleSize(int x, int y, WXUINT id)
1004 {
1005 bool processed = FALSE;
1006 #ifndef __WXMICROWIN__
1007
1008 switch ( id )
1009 {
1010 case SIZENORMAL:
1011 // only do it it if we were iconized before, otherwise resizing the
1012 // parent frame has a curious side effect of bringing it under it's
1013 // children
1014 if ( !m_iconized )
1015 break;
1016
1017 // restore all child frames too
1018 IconizeChildFrames(FALSE);
1019
1020 (void)SendIconizeEvent(FALSE);
1021
1022 // fall through
1023
1024 case SIZEFULLSCREEN:
1025 m_iconized = FALSE;
1026 break;
1027
1028 case SIZEICONIC:
1029 // iconize all child frames too
1030 IconizeChildFrames(TRUE);
1031
1032 (void)SendIconizeEvent();
1033
1034 m_iconized = TRUE;
1035 break;
1036 }
1037 #endif
1038
1039 if ( !m_iconized )
1040 {
1041 #if wxUSE_STATUSBAR
1042 PositionStatusBar();
1043 #endif // wxUSE_STATUSBAR
1044
1045 #if wxUSE_TOOLBAR
1046 PositionToolBar();
1047 #endif // wxUSE_TOOLBAR
1048
1049 wxSizeEvent event(wxSize(x, y), m_windowId);
1050 event.SetEventObject( this );
1051 processed = GetEventHandler()->ProcessEvent(event);
1052 }
1053
1054 return processed;
1055 }
1056
1057 bool wxFrameMSW::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control)
1058 {
1059 if ( control )
1060 {
1061 // In case it's e.g. a toolbar.
1062 wxWindow *win = wxFindWinFromHandle(control);
1063 if ( win )
1064 return win->MSWCommand(cmd, id);
1065 }
1066
1067 // handle here commands from menus and accelerators
1068 if ( cmd == 0 || cmd == 1 )
1069 {
1070 #if wxUSE_MENUS_NATIVE
1071 if ( wxCurrentPopupMenu )
1072 {
1073 wxMenu *popupMenu = wxCurrentPopupMenu;
1074 wxCurrentPopupMenu = NULL;
1075
1076 return popupMenu->MSWCommand(cmd, id);
1077 }
1078 #endif // wxUSE_MENUS_NATIVE
1079
1080 if ( ProcessCommand(id) )
1081 {
1082 return TRUE;
1083 }
1084 }
1085
1086 return FALSE;
1087 }
1088
1089 bool wxFrameMSW::HandleMenuSelect(WXWORD nItem, WXWORD flags, WXHMENU hMenu)
1090 {
1091 int item;
1092 if ( flags == 0xFFFF && hMenu == 0 )
1093 {
1094 // menu was removed from screen
1095 item = -1;
1096 }
1097 #ifndef __WXMICROWIN__
1098 else if ( !(flags & MF_POPUP) && !(flags & MF_SEPARATOR) )
1099 {
1100 item = nItem;
1101 }
1102 #endif
1103 else
1104 {
1105 #if wxUSE_STATUSBAR
1106 // don't give hints for separators (doesn't make sense) nor for the
1107 // items opening popup menus (they don't have them anyhow) but do clear
1108 // the status line - otherwise, we would be left with the help message
1109 // for the previous item which doesn't apply any more
1110 wxStatusBar *statbar = GetStatusBar();
1111 if ( statbar )
1112 {
1113 statbar->SetStatusText(wxEmptyString);
1114 }
1115 #endif // wxUSE_STATUSBAR
1116
1117 return FALSE;
1118 }
1119
1120 wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, item);
1121 event.SetEventObject( this );
1122
1123 return GetEventHandler()->ProcessEvent(event);
1124 }
1125
1126 // ---------------------------------------------------------------------------
1127 // the window proc for wxFrameMSW
1128 // ---------------------------------------------------------------------------
1129
1130 long wxFrameMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
1131 {
1132 long rc = 0;
1133 bool processed = FALSE;
1134
1135 switch ( message )
1136 {
1137 case WM_CLOSE:
1138 // if we can't close, tell the system that we processed the
1139 // message - otherwise it would close us
1140 processed = !Close();
1141 break;
1142
1143 case WM_COMMAND:
1144 {
1145 WORD id, cmd;
1146 WXHWND hwnd;
1147 UnpackCommand((WXWPARAM)wParam, (WXLPARAM)lParam,
1148 &id, &hwnd, &cmd);
1149
1150 processed = HandleCommand(id, cmd, (WXHWND)hwnd);
1151 }
1152 break;
1153
1154 #ifndef __WXMICROWIN__
1155 case WM_MENUSELECT:
1156 {
1157 WXWORD item, flags;
1158 WXHMENU hmenu;
1159 UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu);
1160
1161 processed = HandleMenuSelect(item, flags, hmenu);
1162 }
1163 break;
1164 #endif
1165
1166 case WM_PAINT:
1167 processed = HandlePaint();
1168 break;
1169
1170 #ifndef __WXMICROWIN__
1171 case WM_QUERYDRAGICON:
1172 {
1173 HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon)
1174 : (HICON)(m_defaultIcon);
1175 rc = (long)hIcon;
1176 processed = rc != 0;
1177 }
1178 break;
1179 #endif
1180
1181 case WM_SIZE:
1182 processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam);
1183 break;
1184 }
1185
1186 if ( !processed )
1187 rc = wxWindow::MSWWindowProc(message, wParam, lParam);
1188
1189 return rc;
1190 }
1191