]> git.saurik.com Git - wxWidgets.git/blob - src/msw/frame.cpp
wxWindow split (MSW part of changes)
[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 wxList 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 void 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 wxWindow::MSWCreate(id, parent, wclass, wx_win, title, x, y, width, height,
615 msflags, NULL, extendedStyle);
616 // Seems to be necessary if we use WS_POPUP
617 // style instead of WS_OVERLAPPED
618 if (width > -1 && height > -1)
619 ::PostMessage((HWND) GetHWND(), WM_SIZE, SIZE_RESTORED, MAKELPARAM(width, height));
620 }
621
622 bool wxFrame::MSWOnPaint()
623 {
624 RECT rect;
625 if (GetUpdateRect((HWND) GetHWND(), &rect, FALSE))
626 {
627 if (m_iconized)
628 {
629 HICON the_icon;
630 if (m_icon.Ok())
631 the_icon = (HICON) m_icon.GetHICON();
632 else
633 the_icon = (HICON) m_defaultIcon;
634
635 PAINTSTRUCT ps;
636 // Hold a pointer to the dc so long as the OnPaint() message
637 // is being processed
638 HDC cdc = BeginPaint((HWND) GetHWND(), &ps);
639
640 // Erase background before painting or we get white background
641 this->MSWDefWindowProc(WM_ICONERASEBKGND,(WORD)(LONG) ps.hdc,0L);
642
643 if (the_icon)
644 {
645 RECT rect;
646 ::GetClientRect((HWND) GetHWND(), &rect);
647 int icon_width = 32;
648 int icon_height = 32;
649 int icon_x = (int)((rect.right - icon_width)/2);
650 int icon_y = (int)((rect.bottom - icon_height)/2);
651 DrawIcon(cdc, icon_x, icon_y, the_icon);
652 }
653
654 EndPaint((HWND) GetHWND(), &ps);
655 }
656 else
657 {
658 wxPaintEvent event(m_windowId);
659 event.m_eventObject = this;
660 if (!GetEventHandler()->ProcessEvent(event))
661 Default();
662 }
663 return 0;
664 }
665 return 1;
666 }
667
668 WXHICON wxFrame::MSWOnQueryDragIcon()
669 {
670 if (m_icon.Ok() && (m_icon.GetHICON() != 0))
671 return m_icon.GetHICON();
672 else
673 return m_defaultIcon;
674 }
675
676 void wxFrame::MSWOnSize(int x, int y, WXUINT id)
677 {
678 switch (id)
679 {
680 case SIZENORMAL:
681 // only do it it if we were iconized before, otherwise resizing the
682 // parent frame has a curious side effect of bringing it under it's
683 // children
684 if ( !m_iconized )
685 break;
686
687 // restore all child frames too
688 IconizeChildFrames(FALSE);
689
690 // fall through
691
692 case SIZEFULLSCREEN:
693 m_iconized = FALSE;
694 break;
695
696 case SIZEICONIC:
697 // iconize all child frames too
698 IconizeChildFrames(TRUE);
699
700 m_iconized = TRUE;
701 break;
702 }
703
704 if (!m_iconized)
705 {
706 // forward WM_SIZE to status bar control
707 #if wxUSE_NATIVE_STATUSBAR
708 if (m_frameStatusBar && m_frameStatusBar->IsKindOf(CLASSINFO(wxStatusBar95)))
709 {
710 wxSizeEvent event(wxSize(x, y), m_frameStatusBar->GetId());
711 event.SetEventObject( m_frameStatusBar );
712
713 ((wxStatusBar95 *)m_frameStatusBar)->OnSize(event);
714 }
715 #endif
716
717 PositionStatusBar();
718 PositionToolBar();
719
720 wxSizeEvent event(wxSize(x, y), m_windowId);
721 event.SetEventObject( this );
722 if (!GetEventHandler()->ProcessEvent(event))
723 Default();
724 }
725 }
726
727 bool wxFrame::MSWOnClose()
728 {
729 return Close();
730 }
731
732 bool wxFrame::MSWOnCommand(WXWORD id, WXWORD cmd, WXHWND control)
733 {
734 if (cmd == 0 || cmd == 1 ) // Can be either a menu command or an accelerator.
735 {
736 // In case it's e.g. a toolbar.
737 wxWindow *win = wxFindWinFromHandle(control);
738 if (win)
739 return win->MSWCommand(cmd, id);
740
741 if (wxCurrentPopupMenu)
742 {
743 wxMenu *popupMenu = wxCurrentPopupMenu;
744 wxCurrentPopupMenu = NULL;
745 if (popupMenu->MSWCommand(cmd, id))
746 return TRUE;
747 }
748
749 if (GetMenuBar() && GetMenuBar()->FindItemForId(id))
750 {
751 ProcessCommand(id);
752 return TRUE;
753 }
754 else
755 return FALSE;
756 }
757 else
758 return wxWindow::MSWOnCommand(id, cmd, control);
759 }
760
761 void wxFrame::MSWOnMenuHighlight(WXWORD nItem, WXWORD nFlags, WXHMENU hSysMenu)
762 {
763 if (nFlags == 0xFFFF && hSysMenu == 0)
764 {
765 wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, -1);
766 event.SetEventObject( this );
767 GetEventHandler()->ProcessEvent(event);
768 }
769 else if ((nFlags != MF_SEPARATOR) && (nItem != 0) && (nItem != 65535))
770 {
771 wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, nItem);
772 event.SetEventObject( this );
773 GetEventHandler()->ProcessEvent(event);
774 }
775 }
776
777 bool wxFrame::MSWProcessMessage(WXMSG* pMsg)
778 {
779 return FALSE;
780 }
781
782 bool wxFrame::MSWTranslateMessage(WXMSG* pMsg)
783 {
784 if (m_acceleratorTable.Ok() &&
785 ::TranslateAccelerator((HWND) GetHWND(), (HACCEL) m_acceleratorTable.GetHACCEL(), (MSG *)pMsg))
786 return TRUE;
787
788 return FALSE;
789 }
790
791 // Default resizing behaviour - if only ONE subwindow,
792 // resize to client rectangle size
793 void wxFrame::OnSize(wxSizeEvent& event)
794 {
795 // if we're using constraints - do use them
796 #if wxUSE_CONSTRAINTS
797 if ( GetAutoLayout() ) {
798 Layout();
799 return;
800 }
801 #endif
802
803 // do we have _exactly_ one child?
804 wxWindow *child = NULL;
805 for ( wxNode *node = GetChildren().First(); node; node = node->Next() )
806 {
807 wxWindow *win = (wxWindow *)node->Data();
808 if ( !win->IsKindOf(CLASSINFO(wxFrame)) &&
809 !win->IsKindOf(CLASSINFO(wxDialog)) &&
810 (win != GetStatusBar()) &&
811 (win != GetToolBar()) )
812 {
813 if ( child )
814 return; // it's our second subwindow - nothing to do
815 child = win;
816 }
817 }
818
819 if ( child ) {
820 // we have exactly one child - set it's size to fill the whole frame
821 int clientW, clientH;
822 GetClientSize(&clientW, &clientH);
823
824 int x = 0;
825 int y = 0;
826
827 child->SetSize(x, y, clientW, clientH);
828 }
829 }
830
831 // Default activation behaviour - set the focus for the first child
832 // subwindow found.
833 void wxFrame::OnActivate(wxActivateEvent& event)
834 {
835 for(wxNode *node = GetChildren().First(); node; node = node->Next())
836 {
837 // Find a child that's a subwindow, but not a dialog box.
838 wxWindow *child = (wxWindow *)node->Data();
839 if (!child->IsKindOf(CLASSINFO(wxFrame)) &&
840 !child->IsKindOf(CLASSINFO(wxDialog)))
841 {
842 child->SetFocus();
843 return;
844 }
845 }
846 }
847
848 // The default implementation for the close window event.
849 void wxFrame::OnCloseWindow(wxCloseEvent& event)
850 {
851 this->Destroy();
852 }
853
854 // Destroy the window (delayed, if a managed window)
855 bool wxFrame::Destroy()
856 {
857 if (!wxPendingDelete.Member(this))
858 wxPendingDelete.Append(this);
859 return TRUE;
860 }
861
862 // Default menu selection behaviour - display a help string
863 void wxFrame::OnMenuHighlight(wxMenuEvent& event)
864 {
865 if (GetStatusBar())
866 {
867 int menuId = event.GetMenuId();
868 if ( menuId != -1 )
869 {
870 wxMenuBar *menuBar = GetMenuBar();
871 if (menuBar && menuBar->FindItem(menuId))
872 {
873 // set status text even if the string is empty - this will at
874 // least remove the string from the item which was previously
875 // selected
876 SetStatusText(menuBar->GetHelpString(menuId));
877 }
878 }
879 }
880 }
881
882 wxMenuBar *wxFrame::GetMenuBar() const
883 {
884 return m_frameMenuBar;
885 }
886
887 void wxFrame::Centre(int direction)
888 {
889 int display_width, display_height, width, height, x, y;
890 wxDisplaySize(&display_width, &display_height);
891
892 GetSize(&width, &height);
893 GetPosition(&x, &y);
894
895 if (direction & wxHORIZONTAL)
896 x = (int)((display_width - width)/2);
897 if (direction & wxVERTICAL)
898 y = (int)((display_height - height)/2);
899
900 SetSize(x, y, width, height);
901 }
902
903 // Call this to simulate a menu command
904 void wxFrame::Command(int id)
905 {
906 ProcessCommand(id);
907 }
908
909 void wxFrame::ProcessCommand(int id)
910 {
911 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
912 commandEvent.SetInt( id );
913 commandEvent.SetEventObject( this );
914
915 wxMenuBar *bar = GetMenuBar() ;
916 if (!bar)
917 return;
918
919 wxMenuItem *item = bar->FindItemForId(id) ;
920 if (item && item->IsCheckable())
921 {
922 bar->Check(id,!bar->Checked(id)) ;
923 }
924
925 /*
926 // Process events starting with the window with the focus, if any.
927 wxWindow* focusWin = wxFindFocusDescendant(this);
928
929 wxEvtHandler* evtHandler = focusWin ? focusWin->GetEventHandler() : GetEventHandler();
930 */
931
932 wxEvtHandler* evtHandler = GetEventHandler();
933 evtHandler->ProcessEvent(commandEvent);
934 }
935
936 // Checks if there is a toolbar, and returns the first free client position
937 wxPoint wxFrame::GetClientAreaOrigin() const
938 {
939 wxPoint pt(0, 0);
940 if (GetToolBar())
941 {
942 int w, h;
943 GetToolBar()->GetSize(& w, & h);
944
945 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
946 {
947 pt.x += w;
948 }
949 else
950 {
951 pt.y += h;
952 }
953 }
954 return pt;
955 }
956
957 void wxFrame::ScreenToClient(int *x, int *y) const
958 {
959 wxWindow::ScreenToClient(x, y);
960
961 // We may be faking the client origin.
962 // So a window that's really at (0, 30) may appear
963 // (to wxWin apps) to be at (0, 0).
964 wxPoint pt(GetClientAreaOrigin());
965 *x -= pt.x;
966 *y -= pt.y;
967 }
968
969 void wxFrame::ClientToScreen(int *x, int *y) const
970 {
971 // We may be faking the client origin.
972 // So a window that's really at (0, 30) may appear
973 // (to wxWin apps) to be at (0, 0).
974 wxPoint pt1(GetClientAreaOrigin());
975 *x += pt1.x;
976 *y += pt1.y;
977
978 wxWindow::ClientToScreen(x, y);
979 }
980
981 wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
982 {
983 wxCHECK_MSG( m_frameToolBar == NULL, FALSE,
984 "recreating toolbar in wxFrame" );
985
986 wxToolBar* toolBar = OnCreateToolBar(style, id, name);
987 if (toolBar)
988 {
989 SetToolBar(toolBar);
990 PositionToolBar();
991 return toolBar;
992 }
993 else
994 {
995 return NULL;
996 }
997 }
998
999 wxToolBar* wxFrame::OnCreateToolBar(long style, wxWindowID id, const wxString& name)
1000 {
1001 return new wxToolBar(this, id, wxDefaultPosition, wxDefaultSize, style, name);
1002 }
1003
1004 void wxFrame::PositionToolBar()
1005 {
1006 RECT rect;
1007 ::GetClientRect((HWND) GetHWND(), &rect);
1008
1009 if ( GetStatusBar() )
1010 {
1011 int statusX, statusY;
1012 GetStatusBar()->GetClientSize(&statusX, &statusY);
1013 rect.bottom -= statusY;
1014 }
1015
1016 if (GetToolBar())
1017 {
1018 int tw, th;
1019 GetToolBar()->GetSize(& tw, & th);
1020
1021 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
1022 {
1023 // Use the 'real' MSW position
1024 GetToolBar()->SetSize(0, 0, tw, rect.bottom, wxSIZE_NO_ADJUSTMENTS);
1025 }
1026 else
1027 {
1028 // Use the 'real' MSW position
1029 GetToolBar()->SetSize(0, 0, rect.right, th, wxSIZE_NO_ADJUSTMENTS);
1030 }
1031 }
1032 }
1033
1034 // propagate our state change to all child frames
1035 void wxFrame::IconizeChildFrames(bool bIconize)
1036 {
1037 for ( wxNode *node = GetChildren().First(); node; node = node->Next() ) {
1038 wxWindow *win = (wxWindow *)node->Data();
1039 if ( win->IsKindOf(CLASSINFO(wxFrame)) ) {
1040 ((wxFrame *)win)->Iconize(bIconize);
1041 }
1042 }
1043 }
1044