]> git.saurik.com Git - wxWidgets.git/blob - src/msw/frame.cpp
1. MSW message handling simplifications
[wxWidgets.git] / src / msw / frame.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: frame.cpp
3 // Purpose: wxFrame
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 #ifdef __GNUG__
13 #pragma implementation "frame.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/setup.h"
25 #include "wx/frame.h"
26 #include "wx/menu.h"
27 #include "wx/app.h"
28 #include "wx/utils.h"
29 #include "wx/dialog.h"
30 #include "wx/settings.h"
31 #include "wx/dcclient.h"
32 #endif // WX_PRECOMP
33
34 #include "wx/msw/private.h"
35 #include "wx/statusbr.h"
36 #include "wx/toolbar.h"
37 #include "wx/menuitem.h"
38 #include "wx/log.h"
39
40 #ifdef LoadAccelerators
41 #undef LoadAccelerators
42 #endif
43
44 #if wxUSE_NATIVE_STATUSBAR
45 #include <wx/msw/statbr95.h>
46 #endif
47
48 extern wxWindowList wxModelessWindows;
49 extern wxList WXDLLEXPORT wxPendingDelete;
50 extern char wxFrameClassName[];
51 extern wxMenu *wxCurrentPopupMenu;
52
53 #if !USE_SHARED_LIBRARY
54 BEGIN_EVENT_TABLE(wxFrame, wxWindow)
55 EVT_SIZE(wxFrame::OnSize)
56 EVT_ACTIVATE(wxFrame::OnActivate)
57 EVT_MENU_HIGHLIGHT_ALL(wxFrame::OnMenuHighlight)
58 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
59 EVT_IDLE(wxFrame::OnIdle)
60 EVT_CLOSE(wxFrame::OnCloseWindow)
61 END_EVENT_TABLE()
62
63 IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxWindow)
64 #endif
65
66 #if wxUSE_NATIVE_STATUSBAR
67 bool wxFrame::m_useNativeStatusBar = TRUE;
68 #else
69 bool wxFrame::m_useNativeStatusBar = FALSE;
70 #endif
71
72 wxFrame::wxFrame()
73 {
74 m_frameToolBar = NULL ;
75 m_frameMenuBar = NULL;
76 m_frameStatusBar = NULL;
77
78 m_iconized = FALSE;
79 }
80
81 bool wxFrame::Create(wxWindow *parent,
82 wxWindowID id,
83 const wxString& title,
84 const wxPoint& pos,
85 const wxSize& size,
86 long style,
87 const wxString& name)
88 {
89 #if wxUSE_TOOLTIPS
90 m_hwndToolTip = 0;
91 #endif
92
93 if (!parent)
94 wxTopLevelWindows.Append(this);
95
96 SetName(name);
97 // m_modalShowing = FALSE;
98 m_windowStyle = style;
99 m_frameMenuBar = NULL;
100 m_frameToolBar = NULL ;
101 m_frameStatusBar = NULL;
102
103 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
104
105 // m_icon = NULL;
106 if ( id > -1 )
107 m_windowId = id;
108 else
109 m_windowId = (int)NewControlId();
110
111 if (parent) parent->AddChild(this);
112
113 int x = pos.x;
114 int y = pos.y;
115 int width = size.x;
116 int height = size.y;
117
118 m_iconized = FALSE;
119
120 // we pass NULL as parent to MSWCreate because frames with parents behave
121 // very strangely under Win95 shell
122 // Alteration by JACS: keep normal Windows behaviour (float on top of parent)
123 // with this style.
124 if ((m_windowStyle & wxFRAME_FLOAT_ON_PARENT) == 0)
125 parent = NULL;
126
127 MSWCreate(m_windowId, parent, wxFrameClassName, this, title,
128 x, y, width, height, style);
129
130 wxModelessWindows.Append(this);
131 return TRUE;
132 }
133
134 wxFrame::~wxFrame()
135 {
136 m_isBeingDeleted = TRUE;
137 wxTopLevelWindows.DeleteObject(this);
138
139 if (m_frameStatusBar)
140 delete m_frameStatusBar;
141 if (m_frameMenuBar)
142 delete m_frameMenuBar;
143
144 /* New behaviour March 1998: check if it's the last top-level window */
145 // if (wxTheApp && (this == wxTheApp->GetTopWindow()))
146
147 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
148 {
149 wxTheApp->SetTopWindow(NULL);
150
151 if (wxTheApp->GetExitOnFrameDelete())
152 {
153 PostQuitMessage(0);
154 }
155 }
156
157 wxModelessWindows.DeleteObject(this);
158
159 // For some reason, wxWindows can activate another task altogether
160 // when a frame is destroyed after a modal dialog has been invoked.
161 // Try to bring the parent to the top.
162 if (GetParent() && GetParent()->GetHWND())
163 ::BringWindowToTop((HWND) GetParent()->GetHWND());
164 }
165
166 WXHMENU wxFrame::GetWinMenu() const
167 {
168 return m_hMenu;
169 }
170
171 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
172 void wxFrame::DoGetClientSize(int *x, int *y) const
173 {
174 RECT rect;
175 ::GetClientRect((HWND) GetHWND(), &rect);
176
177 if ( GetStatusBar() )
178 {
179 int statusX, statusY;
180 GetStatusBar()->GetClientSize(&statusX, &statusY);
181 rect.bottom -= statusY;
182 }
183
184 wxPoint pt(GetClientAreaOrigin());
185 rect.bottom -= pt.y;
186 rect.right -= pt.x;
187
188 *x = rect.right;
189 *y = rect.bottom;
190 }
191
192 // Set the client size (i.e. leave the calculation of borders etc.
193 // to wxWindows)
194 void wxFrame::DoSetClientSize(int width, int height)
195 {
196 HWND hWnd = (HWND) GetHWND();
197
198 RECT rect;
199 ::GetClientRect(hWnd, &rect);
200
201 RECT rect2;
202 GetWindowRect(hWnd, &rect2);
203
204 // Find the difference between the entire window (title bar and all)
205 // and the client area; add this to the new client size to move the
206 // window
207 int actual_width = rect2.right - rect2.left - rect.right + width;
208 int actual_height = rect2.bottom - rect2.top - rect.bottom + height;
209
210 if ( GetStatusBar() )
211 {
212 int statusX, statusY;
213 GetStatusBar()->GetClientSize(&statusX, &statusY);
214 actual_height += statusY;
215 }
216
217 wxPoint pt(GetClientAreaOrigin());
218 actual_width += pt.y;
219 actual_height += pt.x;
220
221 POINT point;
222 point.x = rect2.left;
223 point.y = rect2.top;
224
225 MoveWindow(hWnd, point.x, point.y, actual_width, actual_height, (BOOL)TRUE);
226
227 wxSizeEvent event(wxSize(width, height), m_windowId);
228 event.SetEventObject( this );
229 GetEventHandler()->ProcessEvent(event);
230 }
231
232 void wxFrame::DoGetSize(int *width, int *height) const
233 {
234 RECT rect;
235 GetWindowRect((HWND) GetHWND(), &rect);
236 *width = rect.right - rect.left;
237 *height = rect.bottom - rect.top;
238 }
239
240 void wxFrame::DoGetPosition(int *x, int *y) const
241 {
242 RECT rect;
243 GetWindowRect((HWND) GetHWND(), &rect);
244 POINT point;
245 point.x = rect.left;
246 point.y = rect.top;
247
248 *x = point.x;
249 *y = point.y;
250 }
251
252 void wxFrame::DoSetSize(int x, int y, int width, int height, int sizeFlags)
253 {
254 int currentX, currentY;
255 int x1 = x;
256 int y1 = y;
257 int w1 = width;
258 int h1 = height;
259
260 GetPosition(&currentX, &currentY);
261 if (x == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
262 x1 = currentX;
263 if (y == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
264 y1 = currentY;
265
266 int ww,hh ;
267 GetSize(&ww,&hh) ;
268 if (width == -1) w1 = ww ;
269 if (height==-1) h1 = hh ;
270
271 MoveWindow((HWND) GetHWND(), x1, y1, w1, h1, (BOOL)TRUE);
272
273 wxSizeEvent event(wxSize(width, height), m_windowId);
274 event.SetEventObject( this );
275 GetEventHandler()->ProcessEvent(event);
276 }
277
278 bool wxFrame::Show(bool show)
279 {
280 int cshow;
281 if (show)
282 cshow = SW_SHOW;
283 else
284 cshow = SW_HIDE;
285
286 if (!show)
287 {
288 // Try to highlight the correct window (the parent)
289 HWND hWndParent = 0;
290 if (GetParent())
291 {
292 hWndParent = (HWND) GetParent()->GetHWND();
293 if (hWndParent)
294 ::BringWindowToTop(hWndParent);
295 }
296 }
297
298 ShowWindow((HWND) GetHWND(), (BOOL)cshow);
299 if (show)
300 {
301 BringWindowToTop((HWND) GetHWND());
302
303 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, m_windowId);
304 event.SetEventObject( this );
305 GetEventHandler()->ProcessEvent(event);
306 }
307 return TRUE;
308 }
309
310 void wxFrame::Iconize(bool iconize)
311 {
312 if (!iconize)
313 Show(TRUE);
314
315 int cshow;
316 if (iconize)
317 cshow = SW_MINIMIZE;
318 else
319 cshow = SW_RESTORE;
320 ShowWindow((HWND) GetHWND(), (BOOL)cshow);
321 m_iconized = iconize;
322 }
323
324 // Equivalent to maximize/restore in Windows
325 void wxFrame::Maximize(bool maximize)
326 {
327 Show(TRUE);
328 int cshow;
329 if (maximize)
330 cshow = SW_MAXIMIZE;
331 else
332 cshow = SW_RESTORE;
333 ShowWindow((HWND) GetHWND(), cshow);
334 m_iconized = FALSE;
335 }
336
337 bool wxFrame::IsIconized() const
338 {
339 ((wxFrame *)this)->m_iconized = (::IsIconic((HWND) GetHWND()) != 0);
340 return m_iconized;
341 }
342
343 // Is it maximized?
344 bool wxFrame::IsMaximized() const
345 {
346 return (::IsZoomed((HWND) GetHWND()) != 0) ;
347 }
348
349 void wxFrame::SetTitle(const wxString& title)
350 {
351 SetWindowText((HWND) GetHWND(), (const char *)title);
352 }
353
354 wxString wxFrame::GetTitle() const
355 {
356 GetWindowText((HWND) GetHWND(), wxBuffer, 1000);
357 return wxString(wxBuffer);
358 }
359
360 void wxFrame::SetIcon(const wxIcon& icon)
361 {
362 m_icon = icon;
363 #if defined(__WIN95__)
364 if ( m_icon.Ok() )
365 SendMessage((HWND) GetHWND(), WM_SETICON,
366 (WPARAM)TRUE, (LPARAM)(HICON) m_icon.GetHICON());
367 #endif
368 }
369
370 wxStatusBar *wxFrame::OnCreateStatusBar(int number, long style, wxWindowID id,
371 const wxString& name)
372 {
373 wxStatusBar *statusBar = NULL;
374
375 #if wxUSE_NATIVE_STATUSBAR
376 if (UsesNativeStatusBar())
377 {
378 statusBar = new wxStatusBar95(this, id, style);
379 }
380 else
381 #endif
382 {
383 statusBar = new wxStatusBar(this, id, wxPoint(0, 0), wxSize(100, 20),
384 style, name);
385
386 // Set the height according to the font and the border size
387 wxClientDC dc(statusBar);
388 dc.SetFont(statusBar->GetFont());
389
390 long x, y;
391 dc.GetTextExtent("X", &x, &y);
392
393 int height = (int)( (y * 1.1) + 2* statusBar->GetBorderY());
394
395 statusBar->SetSize(-1, -1, 100, height);
396 }
397
398 statusBar->SetFieldsCount(number);
399 return statusBar;
400 }
401
402 wxStatusBar* wxFrame::CreateStatusBar(int number, long style, wxWindowID id,
403 const wxString& name)
404 {
405 // VZ: calling CreateStatusBar twice is an error - why anyone would do it?
406 wxCHECK_MSG( m_frameStatusBar == NULL, FALSE,
407 "recreating status bar in wxFrame" );
408
409 m_frameStatusBar = OnCreateStatusBar(number, style, id,
410 name);
411 if ( m_frameStatusBar )
412 {
413 PositionStatusBar();
414 return m_frameStatusBar;
415 }
416 else
417 return NULL;
418 }
419
420 void wxFrame::SetStatusText(const wxString& text, int number)
421 {
422 wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set text for" );
423
424 m_frameStatusBar->SetStatusText(text, number);
425 }
426
427 void wxFrame::SetStatusWidths(int n, const int widths_field[])
428 {
429 wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set widths for" );
430
431 m_frameStatusBar->SetStatusWidths(n, widths_field);
432 PositionStatusBar();
433 }
434
435 void wxFrame::PositionStatusBar()
436 {
437 // native status bar positions itself
438 if (m_frameStatusBar
439 #if wxUSE_NATIVE_STATUSBAR
440 && !m_frameStatusBar->IsKindOf(CLASSINFO(wxStatusBar95))
441 #endif
442 )
443 {
444 int w, h;
445 GetClientSize(&w, &h);
446 int sw, sh;
447 m_frameStatusBar->GetSize(&sw, &sh);
448
449 // Since we wish the status bar to be directly under the client area,
450 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
451 m_frameStatusBar->SetSize(0, h, w, sh);
452 }
453 }
454
455 void wxFrame::SetMenuBar(wxMenuBar *menu_bar)
456 {
457 if (!menu_bar)
458 {
459 m_frameMenuBar = NULL;
460 return;
461 }
462
463 wxCHECK_RET( !menu_bar->GetFrame(), "this menubar is already attached" );
464
465 if (m_frameMenuBar)
466 delete m_frameMenuBar;
467
468 m_hMenu = menu_bar->Create();
469
470 if ( !m_hMenu )
471 return;
472
473 if ( !::SetMenu((HWND)GetHWND(), (HMENU)m_hMenu) )
474 {
475 wxLogLastError("SetMenu");
476 }
477
478 m_frameMenuBar = menu_bar;
479 menu_bar->Attach(this);
480 }
481
482 #if 0
483 bool wxFrame::LoadAccelerators(const wxString& table)
484 {
485 m_acceleratorTable = (WXHANDLE)
486 #ifdef __WIN32__
487 #ifdef UNICODE
488 ::LoadAcceleratorsW(wxGetInstance(), (const char *)table);
489 #else
490 ::LoadAcceleratorsA(wxGetInstance(), (const char *)table);
491 #endif
492 #else
493 ::LoadAccelerators(wxGetInstance(), (const char *)table);
494 #endif
495
496 // The above is necessary because LoadAccelerators is a macro
497 // which we have undefed earlier in the file to avoid confusion
498 // with wxFrame::LoadAccelerators. Ugh!
499
500 return (m_acceleratorTable != (WXHANDLE) NULL);
501 }
502 #endif
503
504 void wxFrame::Fit()
505 {
506 // Work out max. size
507 wxNode *node = GetChildren().First();
508 int max_width = 0;
509 int max_height = 0;
510 while (node)
511 {
512 // Find a child that's a subwindow, but not a dialog box.
513 wxWindow *win = (wxWindow *)node->Data();
514
515 if (!win->IsKindOf(CLASSINFO(wxFrame)) &&
516 !win->IsKindOf(CLASSINFO(wxDialog)))
517 {
518 int width, height;
519 int x, y;
520 win->GetSize(&width, &height);
521 win->GetPosition(&x, &y);
522
523 if ((x + width) > max_width)
524 max_width = x + width;
525 if ((y + height) > max_height)
526 max_height = y + height;
527 }
528 node = node->Next();
529 }
530 SetClientSize(max_width, max_height);
531 }
532
533 // Responds to colour changes, and passes event on to children.
534 void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
535 {
536 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
537 Refresh();
538
539 if ( m_frameStatusBar )
540 {
541 wxSysColourChangedEvent event2;
542 event2.SetEventObject( m_frameStatusBar );
543 m_frameStatusBar->GetEventHandler()->ProcessEvent(event2);
544 }
545
546 // Propagate the event to the non-top-level children
547 wxWindow::OnSysColourChanged(event);
548 }
549
550 /*
551 * Frame window
552 *
553 */
554
555 bool wxFrame::MSWCreate(int id, wxWindow *parent, const char *wclass, wxWindow *wx_win, const char *title,
556 int x, int y, int width, int height, long style)
557
558 {
559 m_defaultIcon = (WXHICON) (wxSTD_FRAME_ICON ? wxSTD_FRAME_ICON : wxDEFAULT_FRAME_ICON);
560
561 // If child windows aren't properly drawn initially, WS_CLIPCHILDREN
562 // could be the culprit. But without it, you can get a lot of flicker.
563
564 DWORD msflags = 0;
565 if ((style & wxCAPTION) == wxCAPTION)
566 msflags = WS_OVERLAPPED;
567 else
568 msflags = WS_POPUP;
569
570 if (style & wxMINIMIZE_BOX)
571 msflags |= WS_MINIMIZEBOX;
572 if (style & wxMAXIMIZE_BOX)
573 msflags |= WS_MAXIMIZEBOX;
574 if (style & wxTHICK_FRAME)
575 msflags |= WS_THICKFRAME;
576 if (style & wxSYSTEM_MENU)
577 msflags |= WS_SYSMENU;
578 if ((style & wxMINIMIZE) || (style & wxICONIZE))
579 msflags |= WS_MINIMIZE;
580 if (style & wxMAXIMIZE)
581 msflags |= WS_MAXIMIZE;
582 if (style & wxCAPTION)
583 msflags |= WS_CAPTION;
584 if (style & wxCLIP_CHILDREN)
585 msflags |= WS_CLIPCHILDREN;
586
587 // Keep this in wxFrame because it saves recoding this function
588 // in wxTinyFrame
589 #if wxUSE_ITSY_BITSY
590 if (style & wxTINY_CAPTION_VERT)
591 msflags |= IBS_VERTCAPTION;
592 if (style & wxTINY_CAPTION_HORIZ)
593 msflags |= IBS_HORZCAPTION;
594 #else
595 if (style & wxTINY_CAPTION_VERT)
596 msflags |= WS_CAPTION;
597 if (style & wxTINY_CAPTION_HORIZ)
598 msflags |= WS_CAPTION;
599 #endif
600 if ((style & wxTHICK_FRAME) == 0)
601 msflags |= WS_BORDER;
602
603 WXDWORD extendedStyle = MakeExtendedStyle(style);
604
605 #if !defined(__WIN16__) && !defined(__SC__)
606 if (style & wxFRAME_TOOL_WINDOW)
607 extendedStyle |= WS_EX_TOOLWINDOW;
608 #endif
609
610 if (style & wxSTAY_ON_TOP)
611 extendedStyle |= WS_EX_TOPMOST;
612
613 m_iconized = FALSE;
614 if ( !wxWindow::MSWCreate(id, parent, wclass, wx_win, title, x, y, width, height,
615 msflags, NULL, extendedStyle) )
616 return FALSE;
617
618 // Seems to be necessary if we use WS_POPUP
619 // style instead of WS_OVERLAPPED
620 if (width > -1 && height > -1)
621 ::PostMessage((HWND) GetHWND(), WM_SIZE, SIZE_RESTORED, MAKELPARAM(width, height));
622
623 return TRUE;
624 }
625
626 bool wxFrame::MSWOnPaint()
627 {
628 RECT rect;
629 if (GetUpdateRect((HWND) GetHWND(), &rect, FALSE))
630 {
631 if (m_iconized)
632 {
633 HICON the_icon;
634 if (m_icon.Ok())
635 the_icon = (HICON) m_icon.GetHICON();
636 else
637 the_icon = (HICON) m_defaultIcon;
638
639 PAINTSTRUCT ps;
640 // Hold a pointer to the dc so long as the OnPaint() message
641 // is being processed
642 HDC cdc = BeginPaint((HWND) GetHWND(), &ps);
643
644 // Erase background before painting or we get white background
645 this->MSWDefWindowProc(WM_ICONERASEBKGND,(WORD)(LONG) ps.hdc,0L);
646
647 if (the_icon)
648 {
649 RECT rect;
650 ::GetClientRect((HWND) GetHWND(), &rect);
651 int icon_width = 32;
652 int icon_height = 32;
653 int icon_x = (int)((rect.right - icon_width)/2);
654 int icon_y = (int)((rect.bottom - icon_height)/2);
655 DrawIcon(cdc, icon_x, icon_y, the_icon);
656 }
657
658 EndPaint((HWND) GetHWND(), &ps);
659 }
660 else
661 {
662 wxPaintEvent event(m_windowId);
663 event.m_eventObject = this;
664 if (!GetEventHandler()->ProcessEvent(event))
665 Default();
666 }
667 return 0;
668 }
669 return 1;
670 }
671
672 WXHICON wxFrame::MSWOnQueryDragIcon()
673 {
674 if (m_icon.Ok() && (m_icon.GetHICON() != 0))
675 return m_icon.GetHICON();
676 else
677 return m_defaultIcon;
678 }
679
680 bool wxFrame::MSWOnSize(int x, int y, WXUINT id)
681 {
682 bool processed = FALSE;
683
684 switch ( id )
685 {
686 case SIZENORMAL:
687 // only do it it if we were iconized before, otherwise resizing the
688 // parent frame has a curious side effect of bringing it under it's
689 // children
690 if ( !m_iconized )
691 break;
692
693 // restore all child frames too
694 IconizeChildFrames(FALSE);
695
696 // fall through
697
698 case SIZEFULLSCREEN:
699 m_iconized = FALSE;
700 break;
701
702 case SIZEICONIC:
703 // iconize all child frames too
704 IconizeChildFrames(TRUE);
705
706 m_iconized = TRUE;
707 break;
708 }
709
710 if ( !m_iconized )
711 {
712 // forward WM_SIZE to status bar control
713 #if wxUSE_NATIVE_STATUSBAR
714 if (m_frameStatusBar && m_frameStatusBar->IsKindOf(CLASSINFO(wxStatusBar95)))
715 {
716 wxSizeEvent event(wxSize(x, y), m_frameStatusBar->GetId());
717 event.SetEventObject( m_frameStatusBar );
718
719 ((wxStatusBar95 *)m_frameStatusBar)->OnSize(event);
720 }
721 #endif // wxUSE_NATIVE_STATUSBAR
722
723 PositionStatusBar();
724 PositionToolBar();
725
726 wxSizeEvent event(wxSize(x, y), m_windowId);
727 event.SetEventObject( this );
728 processed = GetEventHandler()->ProcessEvent(event);
729 }
730
731 return processed;
732 }
733
734 bool wxFrame::MSWOnCommand(WXWORD id, WXWORD cmd, WXHWND control)
735 {
736 if (cmd == 0 || cmd == 1 ) // Can be either a menu command or an accelerator.
737 {
738 // In case it's e.g. a toolbar.
739 wxWindow *win = wxFindWinFromHandle(control);
740 if (win)
741 return win->MSWCommand(cmd, id);
742
743 if (wxCurrentPopupMenu)
744 {
745 wxMenu *popupMenu = wxCurrentPopupMenu;
746 wxCurrentPopupMenu = NULL;
747 if (popupMenu->MSWCommand(cmd, id))
748 return TRUE;
749 }
750
751 if (GetMenuBar() && GetMenuBar()->FindItemForId(id))
752 {
753 ProcessCommand(id);
754 return TRUE;
755 }
756 else
757 return FALSE;
758 }
759 else
760 return wxWindow::MSWOnCommand(id, cmd, control);
761 }
762
763 bool wxFrame::MSWProcessMessage(WXMSG* pMsg)
764 {
765 return FALSE;
766 }
767
768 bool wxFrame::MSWTranslateMessage(WXMSG* pMsg)
769 {
770 if (m_acceleratorTable.Ok() &&
771 ::TranslateAccelerator((HWND) GetHWND(), (HACCEL) m_acceleratorTable.GetHACCEL(), (MSG *)pMsg))
772 return TRUE;
773
774 return FALSE;
775 }
776
777 // Default resizing behaviour - if only ONE subwindow, resize to client
778 // rectangle size
779 void wxFrame::OnSize(wxSizeEvent& event)
780 {
781 // if we're using constraints - do use them
782 #if wxUSE_CONSTRAINTS
783 if ( GetAutoLayout() )
784 {
785 Layout();
786 return;
787 }
788 #endif
789
790 // do we have _exactly_ one child?
791 wxWindow *child = NULL;
792 for ( wxNode *node = GetChildren().First(); node; node = node->Next() )
793 {
794 wxWindow *win = (wxWindow *)node->Data();
795 if ( !win->IsKindOf(CLASSINFO(wxFrame)) &&
796 !win->IsKindOf(CLASSINFO(wxDialog)) &&
797 (win != GetStatusBar()) &&
798 (win != GetToolBar()) )
799 {
800 if ( child )
801 return; // it's our second subwindow - nothing to do
802 child = win;
803 }
804 }
805
806 if ( child ) {
807 // we have exactly one child - set it's size to fill the whole frame
808 int clientW, clientH;
809 GetClientSize(&clientW, &clientH);
810
811 int x = 0;
812 int y = 0;
813
814 child->SetSize(x, y, clientW, clientH);
815 }
816 }
817
818 // Default activation behaviour - set the focus for the first child
819 // subwindow found.
820 void wxFrame::OnActivate(wxActivateEvent& event)
821 {
822 for(wxNode *node = GetChildren().First(); node; node = node->Next())
823 {
824 // Find a child that's a subwindow, but not a dialog box.
825 wxWindow *child = (wxWindow *)node->Data();
826 if (!child->IsKindOf(CLASSINFO(wxFrame)) &&
827 !child->IsKindOf(CLASSINFO(wxDialog)))
828 {
829 child->SetFocus();
830 return;
831 }
832 }
833 }
834
835 // The default implementation for the close window event.
836 void wxFrame::OnCloseWindow(wxCloseEvent& event)
837 {
838 this->Destroy();
839 }
840
841 // Destroy the window (delayed, if a managed window)
842 bool wxFrame::Destroy()
843 {
844 if (!wxPendingDelete.Member(this))
845 wxPendingDelete.Append(this);
846 return TRUE;
847 }
848
849 // Default menu selection behaviour - display a help string
850 void wxFrame::OnMenuHighlight(wxMenuEvent& event)
851 {
852 if (GetStatusBar())
853 {
854 int menuId = event.GetMenuId();
855 if ( menuId != -1 )
856 {
857 wxMenuBar *menuBar = GetMenuBar();
858 if (menuBar && menuBar->FindItem(menuId))
859 {
860 // set status text even if the string is empty - this will at
861 // least remove the string from the item which was previously
862 // selected
863 SetStatusText(menuBar->GetHelpString(menuId));
864 }
865 }
866 }
867 }
868
869 wxMenuBar *wxFrame::GetMenuBar() const
870 {
871 return m_frameMenuBar;
872 }
873
874 void wxFrame::Centre(int direction)
875 {
876 int display_width, display_height, width, height, x, y;
877 wxDisplaySize(&display_width, &display_height);
878
879 GetSize(&width, &height);
880 GetPosition(&x, &y);
881
882 if (direction & wxHORIZONTAL)
883 x = (int)((display_width - width)/2);
884 if (direction & wxVERTICAL)
885 y = (int)((display_height - height)/2);
886
887 SetSize(x, y, width, height);
888 }
889
890 // Call this to simulate a menu command
891 void wxFrame::Command(int id)
892 {
893 ProcessCommand(id);
894 }
895
896 void wxFrame::ProcessCommand(int id)
897 {
898 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
899 commandEvent.SetInt( id );
900 commandEvent.SetEventObject( this );
901
902 wxMenuBar *bar = GetMenuBar() ;
903 if (!bar)
904 return;
905
906 wxMenuItem *item = bar->FindItemForId(id) ;
907 if (item && item->IsCheckable())
908 {
909 bar->Check(id,!bar->Checked(id)) ;
910 }
911
912 /*
913 // Process events starting with the window with the focus, if any.
914 wxWindow* focusWin = wxFindFocusDescendant(this);
915
916 wxEvtHandler* evtHandler = focusWin ? focusWin->GetEventHandler() : GetEventHandler();
917 */
918
919 wxEvtHandler* evtHandler = GetEventHandler();
920 evtHandler->ProcessEvent(commandEvent);
921 }
922
923 // Checks if there is a toolbar, and returns the first free client position
924 wxPoint wxFrame::GetClientAreaOrigin() const
925 {
926 wxPoint pt(0, 0);
927 if (GetToolBar())
928 {
929 int w, h;
930 GetToolBar()->GetSize(& w, & h);
931
932 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
933 {
934 pt.x += w;
935 }
936 else
937 {
938 pt.y += h;
939 }
940 }
941 return pt;
942 }
943
944 void wxFrame::ScreenToClient(int *x, int *y) const
945 {
946 wxWindow::ScreenToClient(x, y);
947
948 // We may be faking the client origin.
949 // So a window that's really at (0, 30) may appear
950 // (to wxWin apps) to be at (0, 0).
951 wxPoint pt(GetClientAreaOrigin());
952 *x -= pt.x;
953 *y -= pt.y;
954 }
955
956 void wxFrame::ClientToScreen(int *x, int *y) const
957 {
958 // We may be faking the client origin.
959 // So a window that's really at (0, 30) may appear
960 // (to wxWin apps) to be at (0, 0).
961 wxPoint pt1(GetClientAreaOrigin());
962 *x += pt1.x;
963 *y += pt1.y;
964
965 wxWindow::ClientToScreen(x, y);
966 }
967
968 wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
969 {
970 wxCHECK_MSG( m_frameToolBar == NULL, FALSE,
971 "recreating toolbar in wxFrame" );
972
973 wxToolBar* toolBar = OnCreateToolBar(style, id, name);
974 if (toolBar)
975 {
976 SetToolBar(toolBar);
977 PositionToolBar();
978 return toolBar;
979 }
980 else
981 {
982 return NULL;
983 }
984 }
985
986 wxToolBar* wxFrame::OnCreateToolBar(long style, wxWindowID id, const wxString& name)
987 {
988 return new wxToolBar(this, id, wxDefaultPosition, wxDefaultSize, style, name);
989 }
990
991 void wxFrame::PositionToolBar()
992 {
993 RECT rect;
994 ::GetClientRect((HWND) GetHWND(), &rect);
995
996 if ( GetStatusBar() )
997 {
998 int statusX, statusY;
999 GetStatusBar()->GetClientSize(&statusX, &statusY);
1000 rect.bottom -= statusY;
1001 }
1002
1003 if (GetToolBar())
1004 {
1005 int tw, th;
1006 GetToolBar()->GetSize(& tw, & th);
1007
1008 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
1009 {
1010 // Use the 'real' MSW position
1011 GetToolBar()->SetSize(0, 0, tw, rect.bottom, wxSIZE_NO_ADJUSTMENTS);
1012 }
1013 else
1014 {
1015 // Use the 'real' MSW position
1016 GetToolBar()->SetSize(0, 0, rect.right, th, wxSIZE_NO_ADJUSTMENTS);
1017 }
1018 }
1019 }
1020
1021 // propagate our state change to all child frames: this allows us to emulate X
1022 // Windows behaviour where child frames float independently of the parent one
1023 // on the desktop, but are iconized/restored with it
1024 void wxFrame::IconizeChildFrames(bool bIconize)
1025 {
1026 for ( wxWindowList::Node *node = GetChildren().GetFirst();
1027 node;
1028 node = node->GetNext() )
1029 {
1030 wxWindow *win = node->GetData();
1031
1032 if ( win->IsKindOf(CLASSINFO(wxFrame)) )
1033 {
1034 ((wxFrame *)win)->Iconize(bIconize);
1035 }
1036 }
1037 }
1038
1039 // ===========================================================================
1040 // our private (non virtual) message handlers
1041 // ===========================================================================
1042
1043 bool wxFrame::HandleMenuSelect(WXWORD nItem, WXWORD nFlags, WXHMENU hMenu)
1044 {
1045 int item;
1046 if ( nFlags == 0xFFFF && hMenu == 0 )
1047 {
1048 // FIXME: what does this do? does it ever happen?
1049 item = -1;
1050 }
1051 else if ((nFlags != MF_SEPARATOR) && (nItem != 0) && (nItem != 65535))
1052 {
1053 item = nItem;
1054 }
1055 else
1056 {
1057 return FALSE;
1058 }
1059
1060 wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, item);
1061 event.SetEventObject( this );
1062
1063 return GetEventHandler()->ProcessEvent(event);
1064 }
1065
1066 // ---------------------------------------------------------------------------
1067 // the window proc for wxFrame
1068 // ---------------------------------------------------------------------------
1069
1070 long wxFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
1071 {
1072 long rc = 0;
1073 bool processed = FALSE;
1074
1075 switch ( message )
1076 {
1077 case WM_MENUSELECT:
1078 {
1079 WORD item = (WORD)wParam;
1080 #ifdef __WIN32__
1081 WORD flags = HIWORD(wParam);
1082 HMENU sysmenu = (HMENU)lParam;
1083 #else
1084 WORD flags = LOWORD(lParam);
1085 HMENU sysmenu = (HMENU)HIWORD(lParam);
1086 #endif
1087 processed = HandleMenuSelect(item, flags, (WXHMENU)sysmenu);
1088 }
1089 break;
1090 }
1091
1092 if ( !processed )
1093 rc = wxWindow::MSWWindowProc(message, wParam, lParam);
1094
1095 return rc;
1096 }