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