]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/frame.cpp
added test for writing empty value to the config
[wxWidgets.git] / src / msw / frame.cpp
... / ...
CommitLineData
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
66extern wxWindowList wxModelessWindows;
67extern wxList WXDLLEXPORT wxPendingDelete;
68extern const wxChar *wxFrameClassName;
69
70#if wxUSE_MENUS_NATIVE
71extern wxMenu *wxCurrentPopupMenu;
72#endif // wxUSE_MENUS_NATIVE
73
74// ----------------------------------------------------------------------------
75// event tables
76// ----------------------------------------------------------------------------
77
78BEGIN_EVENT_TABLE(wxFrameMSW, wxFrameBase)
79 EVT_ACTIVATE(wxFrameMSW::OnActivate)
80 EVT_SYS_COLOUR_CHANGED(wxFrameMSW::OnSysColourChanged)
81END_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
107void 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
132bool 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
172wxFrameMSW::~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.
205void 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)
231void 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
272void 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
281void 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
294void wxFrameMSW::DoShowWindow(int nShowCmd)
295{
296 ::ShowWindow(GetHwnd(), nShowCmd);
297
298 m_iconized = nShowCmd == SW_MINIMIZE;
299}
300
301bool 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
351void wxFrameMSW::Iconize(bool iconize)
352{
353 DoShowWindow(iconize ? SW_MINIMIZE : SW_RESTORE);
354}
355
356void 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
371void wxFrameMSW::Restore()
372{
373 DoShowWindow(SW_RESTORE);
374}
375
376bool 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?
388bool wxFrameMSW::IsMaximized() const
389{
390#ifdef __WXMICROWIN__
391 // TODO
392 return FALSE;
393#else
394 return (::IsZoomed(GetHwnd()) != 0);
395#endif
396}
397
398void 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
412void 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
433wxStatusBar *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
467void 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
485void 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
517void 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.
530void 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.
549bool 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
685bool 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.
776void 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
830wxToolBar* 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
840void 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
881void 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
921bool 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
943bool 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
994bool 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
1048bool 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
1080bool 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
1121long 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