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