]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/mdi.cpp
fixed an over-optimisation
[wxWidgets.git] / src / msw / mdi.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: mdi.cpp
3// Purpose: MDI classes
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
20#ifdef __GNUG__
21 #pragma implementation "mdi.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/setup.h"
33 #include "wx/frame.h"
34 #include "wx/menu.h"
35 #include "wx/app.h"
36 #include "wx/utils.h"
37 #include "wx/dialog.h"
38 #include "wx/statusbr.h"
39 #include "wx/settings.h"
40#endif
41
42#include "wx/mdi.h"
43#include "wx/msw/private.h"
44
45#if wxUSE_NATIVE_STATUSBAR
46 #include <wx/msw/statbr95.h>
47#endif
48
49#include <string.h>
50
51// ---------------------------------------------------------------------------
52// global variables
53// ---------------------------------------------------------------------------
54
55extern wxWindowList wxModelessWindows; // from dialog.cpp
56extern wxMenu *wxCurrentPopupMenu;
57
58extern char wxMDIFrameClassName[];
59extern char wxMDIChildFrameClassName[];
60extern wxWindow *wxWndHook; // from window.cpp
61
62extern wxList *wxWinHandleList;
63
64// ---------------------------------------------------------------------------
65// constants
66// ---------------------------------------------------------------------------
67
68static const int IDM_WINDOWTILE = 4001;
69static const int IDM_WINDOWCASCADE = 4002;
70static const int IDM_WINDOWICONS = 4003;
71static const int IDM_WINDOWNEXT = 4004;
72
73// This range gives a maximum of 500 MDI children. Should be enough :-)
74static const int wxFIRST_MDI_CHILD = 4100;
75static const int wxLAST_MDI_CHILD = 4600;
76
77// Status border dimensions
78static const int wxTHICK_LINE_BORDER = 3;
79static const int wxTHICK_LINE_WIDTH = 1;
80
81// ===========================================================================
82// implementation
83// ===========================================================================
84
85// ---------------------------------------------------------------------------
86// wxWin macros
87// ---------------------------------------------------------------------------
88
89#if !USE_SHARED_LIBRARY
90 IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame, wxFrame)
91 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame, wxFrame)
92 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxWindow)
93#endif // USE_SHARED_LIBRARY
94
95BEGIN_EVENT_TABLE(wxMDIParentFrame, wxFrame)
96 EVT_SIZE(wxMDIParentFrame::OnSize)
97 EVT_ACTIVATE(wxMDIParentFrame::OnActivate)
98 EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged)
99END_EVENT_TABLE()
100
101BEGIN_EVENT_TABLE(wxMDIClientWindow, wxWindow)
102 EVT_SCROLL(wxMDIClientWindow::OnScroll)
103END_EVENT_TABLE()
104
105// ---------------------------------------------------------------------------
106// wxMDIParentFrame
107// ---------------------------------------------------------------------------
108
109wxMDIParentFrame::wxMDIParentFrame()
110{
111 m_clientWindow = NULL;
112 m_currentChild = NULL;
113 m_windowMenu = 0;
114 m_parentFrameActive = TRUE;
115}
116
117bool wxMDIParentFrame::Create(wxWindow *parent,
118 wxWindowID id,
119 const wxString& title,
120 const wxPoint& pos,
121 const wxSize& size,
122 long style,
123 const wxString& name)
124{
125 m_defaultIcon = (WXHICON) (wxSTD_MDIPARENTFRAME_ICON ? wxSTD_MDIPARENTFRAME_ICON : wxDEFAULT_MDIPARENTFRAME_ICON);
126
127 m_clientWindow = NULL;
128 m_currentChild = NULL;
129 m_windowMenu = 0;
130 m_parentFrameActive = TRUE;
131
132 if (!parent)
133 wxTopLevelWindows.Append(this);
134
135 SetName(name);
136 m_windowStyle = style;
137
138 if (parent) parent->AddChild(this);
139
140 if ( id > -1 )
141 m_windowId = id;
142 else
143 m_windowId = (int)NewControlId();
144
145 int x = pos.x;
146 int y = pos.y;
147 int width = size.x;
148 int height = size.y;
149
150 m_windowMenu = (WXHMENU) ::LoadMenu(wxGetInstance(), "wxWindowMenu");
151
152 DWORD msflags = WS_OVERLAPPED ;
153 if (style & wxMINIMIZE_BOX)
154 msflags |= WS_MINIMIZEBOX;
155 if (style & wxMAXIMIZE_BOX)
156 msflags |= WS_MAXIMIZEBOX;
157 if (style & wxTHICK_FRAME)
158 msflags |= WS_THICKFRAME;
159 if (style & wxSYSTEM_MENU)
160 msflags |= WS_SYSMENU;
161 if ((style & wxMINIMIZE) || (style & wxICONIZE))
162 msflags |= WS_MINIMIZE;
163 if (style & wxMAXIMIZE)
164 msflags |= WS_MAXIMIZE;
165 if (style & wxCAPTION)
166 msflags |= WS_CAPTION;
167
168 // Adding WS_CLIPCHILDREN causes children not to be properly
169 // drawn when first displaying them.
170// if (style & wxCLIP_CHILDREN)
171// msflags |= WS_CLIPCHILDREN;
172
173 wxWindow::MSWCreate(m_windowId, parent, wxMDIFrameClassName, this, title, x, y, width, height,
174 msflags);
175
176 wxModelessWindows.Append(this);
177
178 return TRUE;
179}
180
181wxMDIParentFrame::~wxMDIParentFrame()
182{
183 DestroyChildren();
184
185 DestroyMenu((HMENU) m_windowMenu); // Destroy dummy "Window" menu
186 m_windowMenu = 0;
187
188 if (m_clientWindow->MSWGetOldWndProc())
189 m_clientWindow->UnsubclassWin();
190
191 m_clientWindow->SetHWND(0);
192 delete m_clientWindow;
193}
194
195void wxMDIParentFrame::SetMenuBar(wxMenuBar *menu_bar)
196{
197 if (!menu_bar)
198 {
199 m_frameMenuBar = NULL;
200 return;
201 }
202
203 if ( menu_bar->IsAttached() )
204 return;
205
206 m_hMenu = menu_bar->Create();
207
208 if (m_frameMenuBar)
209 delete m_frameMenuBar;
210
211 // MDI parent-specific code follows
212
213 HMENU subMenu = GetSubMenu((HMENU) m_windowMenu, 0);
214
215 // Try to insert Window menu in front of Help, otherwise append it.
216 HMENU menu = (HMENU)m_hMenu;
217 int N = GetMenuItemCount(menu);
218 bool success = FALSE;
219 for (int i = 0; i < N; i++)
220 {
221 char buf[100];
222 int chars = GetMenuString(menu, i, buf, 100, MF_BYPOSITION);
223 if ((chars > 0) && (strcmp(buf, "&Help") == 0 ||
224 strcmp(buf, "Help") == 0))
225 {
226 success = TRUE;
227 InsertMenu(menu, i, MF_BYPOSITION | MF_POPUP | MF_STRING,
228 (UINT)subMenu, "&Window");
229 break;
230 }
231 }
232 if (!success)
233 AppendMenu(menu, MF_POPUP,
234 (UINT)subMenu,
235 "&Window");
236 m_parentFrameActive = TRUE;
237#ifdef __WIN32__
238 SendMessage((HWND) GetClientWindow()->GetHWND(), WM_MDISETMENU,
239 (WPARAM)menu,
240 (LPARAM)subMenu);
241#else
242 SendMessage((HWND) GetClientWindow()->GetHWND(), WM_MDISETMENU, 0,
243 MAKELPARAM(menu, subMenu));
244#endif
245 DrawMenuBar((HWND) GetHWND());
246
247 m_frameMenuBar = menu_bar;
248 menu_bar->Attach(this);
249}
250
251void wxMDIParentFrame::OnSize(wxSizeEvent& event)
252{
253#if wxUSE_CONSTRAINTS
254 if ( GetAutoLayout() )
255 {
256 Layout();
257 return;
258 }
259#endif // wxUSE_CONSTRAINTS
260
261 int x = 0;
262 int y = 0;
263 int width, height;
264 GetClientSize(&width, &height);
265
266 if ( GetClientWindow() )
267 GetClientWindow()->SetSize(x, y, width, height);
268}
269
270void wxMDIParentFrame::OnActivate(wxActivateEvent& event)
271{
272 // Do nothing
273}
274
275// Returns the active MDI child window
276wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const
277{
278 HWND hWnd = (HWND)::SendMessage(GetWinHwnd(GetClientWindow()),
279 WM_MDIGETACTIVE, 0, 0L);
280 if ( hWnd == 0 )
281 return NULL;
282 else
283 return (wxMDIChildFrame *)wxFindWinFromHandle((WXHWND) hWnd);
284}
285
286// Create the client window class (don't Create the window, just return a new
287// class)
288wxMDIClientWindow *wxMDIParentFrame::OnCreateClient()
289{
290 return new wxMDIClientWindow;
291}
292
293// Responds to colour changes, and passes event on to children.
294void wxMDIParentFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
295{
296 if ( m_clientWindow )
297 {
298 m_clientWindow->SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
299 m_clientWindow->Refresh();
300 }
301/*
302 if ( m_frameToolBar )
303 {
304 wxSysColourChangedEvent event2;
305 event2.eventObject = m_frameToolBar;
306 m_frameToolBar->GetEventHandler()->ProcessEvent(event2);
307 }
308*/
309
310 // Propagate the event to the non-top-level children
311 wxFrame::OnSysColourChanged(event);
312}
313
314// MDI operations
315void wxMDIParentFrame::Cascade()
316{
317 ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDICASCADE, 0, 0);
318}
319
320void wxMDIParentFrame::Tile()
321{
322 ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDITILE, MDITILE_HORIZONTAL, 0);
323}
324
325void wxMDIParentFrame::ArrangeIcons()
326{
327 ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDIICONARRANGE, 0, 0);
328}
329
330void wxMDIParentFrame::ActivateNext()
331{
332 ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDINEXT, 0, 0);
333}
334
335void wxMDIParentFrame::ActivatePrevious()
336{
337 ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDINEXT, 0, 1);
338}
339
340// the MDI parent frame window proc
341long wxMDIParentFrame::MSWWindowProc(WXUINT message,
342 WXWPARAM wParam,
343 WXLPARAM lParam)
344{
345 long rc = 0;
346 bool processed = FALSE;
347
348 switch ( message )
349 {
350 case WM_CREATE:
351 m_clientWindow = OnCreateClient();
352 // Uses own style for client style
353 if ( !m_clientWindow->CreateClient(this, GetWindowStyleFlag()) )
354 {
355 wxLogMessage(_("Failed to create MDI parent frame."));
356
357 rc = -1;
358 }
359
360 processed = TRUE;
361 break;
362
363 case WM_ERASEBKGND:
364 processed = TRUE;
365
366 // we erase background ourselves
367 rc = TRUE;
368 break;
369
370 case WM_MENUSELECT:
371 {
372 WORD item = (WORD)wParam;
373#ifdef __WIN32__
374 WORD flags = HIWORD(wParam);
375 HMENU menu = (HMENU)lParam;
376#else
377 WORD flags = LOWORD(lParam);
378 HMENU menu = (HMENU)HIWORD(lParam);
379#endif
380 if ( m_parentFrameActive )
381 {
382 processed = HandleMenuSelect(item, flags, (WXHMENU)menu);
383 }
384 else if (m_currentChild)
385 {
386 processed = m_currentChild->
387 HandleMenuSelect(item, flags, (WXHMENU)menu);
388 }
389 }
390 break;
391 }
392
393 if ( !processed )
394 rc = wxFrame::MSWWindowProc(message, wParam, lParam);
395
396 return rc;
397}
398
399bool wxMDIParentFrame::MSWOnActivate(int state, bool minimized, WXHWND activate)
400{
401 bool processed = FALSE;
402
403 if ( wxWindow::MSWOnActivate(state, minimized, activate) )
404 {
405 // already processed
406 processed = TRUE;
407 }
408
409 // If this window is an MDI parent, we must also send an OnActivate message
410 // to the current child.
411 if ( (m_currentChild != NULL) &&
412 ((state == WA_ACTIVE) || (state == WA_CLICKACTIVE)) )
413 {
414 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, m_currentChild->GetId());
415 event.SetEventObject( m_currentChild );
416 if ( m_currentChild->GetEventHandler()->ProcessEvent(event) )
417 processed = TRUE;
418 }
419
420 return processed;
421}
422
423bool wxMDIParentFrame::MSWOnCommand(WXWORD id, WXWORD cmd, WXHWND control)
424{
425// if (cmd == 0) // Why did I do this test?
426 {
427 // In case it's e.g. a toolbar.
428 wxWindow *win = wxFindWinFromHandle(control);
429 if (win)
430 return win->MSWCommand(cmd, id);
431
432/*
433 if (wxCurrentPopupMenu)
434 {
435 wxMenu *popupMenu = wxCurrentPopupMenu;
436 wxCurrentPopupMenu = NULL;
437 if (!popupMenu->MSWCommand(cmd, id))
438 return TRUE;
439 }
440*/
441
442 switch (id)
443 {
444 case IDM_WINDOWCASCADE:
445 SendMessage((HWND) GetClientWindow()->GetHWND(), WM_MDICASCADE, MDITILE_SKIPDISABLED, 0);
446 return TRUE;
447 case IDM_WINDOWTILE:
448 SendMessage((HWND) GetClientWindow()->GetHWND(), WM_MDITILE, MDITILE_HORIZONTAL, 0);
449 return TRUE;
450 case IDM_WINDOWICONS:
451 SendMessage((HWND) GetClientWindow()->GetHWND(), WM_MDIICONARRANGE, 0, 0);
452 return TRUE;
453 case IDM_WINDOWNEXT:
454 SendMessage((HWND) GetClientWindow()->GetHWND(), WM_MDINEXT, 0, 0);
455 return TRUE;
456 default:
457 break;
458 }
459 if (id >= 0xF000)
460 {
461 return FALSE; // Get WndProc to call default proc
462 }
463
464 if (m_parentFrameActive && (id < wxFIRST_MDI_CHILD || id > wxLAST_MDI_CHILD))
465 {
466 ProcessCommand(id);
467 return TRUE;
468 }
469 else if (m_currentChild && (id < wxFIRST_MDI_CHILD || id > wxLAST_MDI_CHILD))
470 {
471 return m_currentChild->MSWOnCommand(id, cmd, control);
472 }
473 }
474 if (id >= wxFIRST_MDI_CHILD && id <= wxLAST_MDI_CHILD)
475 {
476 wxNode* node = GetChildren().First();
477 while (node)
478 {
479 wxWindow* child = (wxWindow*) node->Data();
480 if (child->GetHWND())
481 {
482#ifdef __WIN32__
483 long childId = GetWindowLong((HWND) child->GetHWND(), GWL_ID);
484#else
485 long childId = GetWindowWord((HWND) child->GetHWND(), GWW_ID);
486#endif
487 if (childId == id)
488 {
489 ::SendMessage( (HWND) GetClientWindow()->GetHWND(), WM_MDIACTIVATE, (WPARAM) (HWND) child->GetHWND(), 0);
490 return TRUE;
491 }
492 }
493 node = node->Next();
494 }
495/*
496 wxWindow* child = FindItem(id);
497 if (child)
498 {
499 ::SendMessage( (HWND) GetClientWindow()->GetHWND(), WM_MDIACTIVATE, (WPARAM) (HWND) child->GetHWND(), 0);
500 return TRUE;
501 }
502*/
503 }
504
505 return wxWindow::MSWOnCommand(id, cmd, control);
506}
507
508long wxMDIParentFrame::MSWDefWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
509{
510 WXHWND clientWnd;
511 if ( GetClientWindow() )
512 clientWnd = GetClientWindow()->GetHWND();
513 else
514 clientWnd = 0;
515
516 return DefFrameProc(GetHwnd(), (HWND)clientWnd, message, wParam, lParam);
517}
518
519bool wxMDIParentFrame::MSWProcessMessage(WXMSG* msg)
520{
521 return m_currentChild && m_currentChild->GetHWND() &&
522 m_currentChild->MSWProcessMessage(msg);
523}
524
525bool wxMDIParentFrame::MSWTranslateMessage(WXMSG* msg)
526{
527 MSG *pMsg = (MSG *)msg;
528
529 if ( m_currentChild && m_currentChild->GetHWND() &&
530 m_currentChild->MSWTranslateMessage(msg) )
531 {
532 return TRUE;
533 }
534
535 if ( m_acceleratorTable.Ok() &&
536 ::TranslateAccelerator(GetHwnd(),
537 GetTableHaccel(&m_acceleratorTable),
538 pMsg) )
539 {
540 return TRUE;
541 }
542
543 if ( pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN )
544 {
545 if ( ::TranslateMDISysAccel(GetWinHwnd(GetClientWindow()), pMsg))
546 return TRUE;
547 }
548
549 return FALSE;
550}
551
552// ---------------------------------------------------------------------------
553// wxMDIChildFrame
554// ---------------------------------------------------------------------------
555
556wxMDIChildFrame::wxMDIChildFrame()
557{
558// m_active = FALSE;
559}
560
561bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
562 wxWindowID id,
563 const wxString& title,
564 const wxPoint& pos,
565 const wxSize& size,
566 long style,
567 const wxString& name)
568{
569 m_defaultIcon = (WXHICON) (wxSTD_MDICHILDFRAME_ICON ? wxSTD_MDICHILDFRAME_ICON : wxDEFAULT_MDICHILDFRAME_ICON);
570
571 SetName(name);
572
573 if ( id > -1 )
574 m_windowId = id;
575 else
576 m_windowId = (int)NewControlId();
577
578 if (parent) parent->AddChild(this);
579
580 wxWndHook = this;
581
582 int x = pos.x;
583 int y = pos.y;
584 int width = size.x;
585 int height = size.y;
586
587 MDICREATESTRUCT mcs;
588
589 mcs.szClass = wxMDIChildFrameClassName;
590 mcs.szTitle = title;
591 mcs.hOwner = wxGetInstance();
592 if (x > -1) mcs.x = x;
593 else mcs.x = CW_USEDEFAULT;
594
595 if (y > -1) mcs.y = y;
596 else mcs.y = CW_USEDEFAULT;
597
598 if (width > -1) mcs.cx = width;
599 else mcs.cx = CW_USEDEFAULT;
600
601 if (height > -1) mcs.cy = height;
602 else mcs.cy = CW_USEDEFAULT;
603
604 DWORD msflags = WS_OVERLAPPED | WS_CLIPCHILDREN ;
605 if (style & wxMINIMIZE_BOX)
606 msflags |= WS_MINIMIZEBOX;
607 if (style & wxMAXIMIZE_BOX)
608 msflags |= WS_MAXIMIZEBOX;
609 if (style & wxTHICK_FRAME)
610 msflags |= WS_THICKFRAME;
611 if (style & wxSYSTEM_MENU)
612 msflags |= WS_SYSMENU;
613 if ((style & wxMINIMIZE) || (style & wxICONIZE))
614 msflags |= WS_MINIMIZE;
615 if (style & wxMAXIMIZE)
616 msflags |= WS_MAXIMIZE;
617 if (style & wxCAPTION)
618 msflags |= WS_CAPTION;
619
620 mcs.style = msflags;
621
622 mcs.lParam = 0;
623
624 DWORD Return = SendMessage((HWND) parent->GetClientWindow()->GetHWND(),
625 WM_MDICREATE, 0, (LONG)(LPSTR)&mcs);
626
627 //handle = (HWND)LOWORD(Return);
628 // Must be the DWORRD for WIN32. And in 16 bits, HIWORD=0 (says Microsoft)
629 m_hWnd = (WXHWND)Return;
630
631 // This gets reassigned so can't be stored
632// m_windowId = GetWindowLong((HWND) m_hWnd, GWL_ID);
633
634 wxWndHook = NULL;
635 wxWinHandleList->Append((long)GetHWND(), this);
636
637 SetWindowLong((HWND) GetHWND(), 0, (long)this);
638
639 wxModelessWindows.Append(this);
640 return TRUE;
641}
642
643wxMDIChildFrame::~wxMDIChildFrame()
644{
645 MSWDestroyWindow();
646
647 ResetWindowStyle(NULL);
648}
649
650// Set the client size (i.e. leave the calculation of borders etc.
651// to wxWindows)
652void wxMDIChildFrame::DoSetClientSize(int width, int height)
653{
654 HWND hWnd = (HWND) GetHWND();
655
656 RECT rect;
657 ::GetClientRect(hWnd, &rect);
658
659 RECT rect2;
660 GetWindowRect(hWnd, &rect2);
661
662 // Find the difference between the entire window (title bar and all)
663 // and the client area; add this to the new client size to move the
664 // window
665 int actual_width = rect2.right - rect2.left - rect.right + width;
666 int actual_height = rect2.bottom - rect2.top - rect.bottom + height;
667
668 if (GetStatusBar())
669 {
670 int sx, sy;
671 GetStatusBar()->GetSize(&sx, &sy);
672 actual_height += sy;
673 }
674
675 POINT point;
676 point.x = rect2.left;
677 point.y = rect2.top;
678
679 // If there's an MDI parent, must subtract the parent's top left corner
680 // since MoveWindow moves relative to the parent
681 wxMDIParentFrame *mdiParent = (wxMDIParentFrame *)GetParent();
682 ::ScreenToClient((HWND) mdiParent->GetClientWindow()->GetHWND(), &point);
683
684 MoveWindow(hWnd, point.x, point.y, actual_width, actual_height, (BOOL)TRUE);
685
686 wxSizeEvent event(wxSize(width, height), m_windowId);
687 event.SetEventObject( this );
688 GetEventHandler()->ProcessEvent(event);
689}
690
691void wxMDIChildFrame::DoGetPosition(int *x, int *y) const
692{
693 RECT rect;
694 GetWindowRect((HWND) GetHWND(), &rect);
695 POINT point;
696 point.x = rect.left;
697 point.y = rect.top;
698
699 // Since we now have the absolute screen coords,
700 // if there's a parent we must subtract its top left corner
701 wxMDIParentFrame *mdiParent = (wxMDIParentFrame *)GetParent();
702 ::ScreenToClient((HWND) mdiParent->GetClientWindow()->GetHWND(), &point);
703
704 *x = point.x;
705 *y = point.y;
706}
707
708void wxMDIChildFrame::SetMenuBar(wxMenuBar *menu_bar)
709{
710 if (!menu_bar)
711 {
712 m_frameMenuBar = NULL;
713 return;
714 }
715
716 if ( menu_bar->IsAttached() )
717 return;
718
719 m_hMenu = menu_bar->Create();
720
721 if (m_frameMenuBar)
722 delete m_frameMenuBar;
723
724 wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
725
726 parent->m_parentFrameActive = FALSE;
727 HMENU subMenu = GetSubMenu((HMENU) parent->GetWindowMenu(), 0);
728
729 // Try to insert Window menu in front of Help, otherwise append it.
730 HMENU menu = (HMENU)m_hMenu;
731 int N = GetMenuItemCount(menu);
732 bool success = FALSE;
733 for (int i = 0; i < N; i++)
734 {
735 char buf[100];
736 int chars = GetMenuString(menu, i, buf, 100, MF_BYPOSITION);
737 if ((chars > 0) && (strcmp(buf, "&Help") == 0 ||
738 strcmp(buf, "Help") == 0))
739 {
740 success = TRUE;
741 InsertMenu(menu, i, MF_BYPOSITION | MF_POPUP | MF_STRING,
742 (UINT)subMenu, "&Window");
743 break;
744 }
745 }
746 if (!success)
747 AppendMenu(menu, MF_POPUP,
748 (UINT)subMenu,
749 "&Window");
750#ifdef __WIN32__
751 SendMessage((HWND) parent->GetClientWindow()->GetHWND(), WM_MDISETMENU,
752 (WPARAM)menu,
753 (LPARAM)subMenu);
754#else
755 SendMessage((HWND) parent->GetClientWindow()->GetHWND(), WM_MDISETMENU, 0,
756 MAKELPARAM(menu, subMenu));
757#endif
758
759 DrawMenuBar((HWND) parent->GetHWND());
760 m_frameMenuBar = menu_bar;
761 menu_bar->Attach(this);
762}
763
764// MDI operations
765void wxMDIChildFrame::Maximize()
766{
767 wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
768 if ( parent && parent->GetClientWindow() )
769 ::SendMessage( (HWND) parent->GetClientWindow()->GetHWND(), WM_MDIMAXIMIZE, (WPARAM) (HWND) GetHWND(), 0);
770}
771
772void wxMDIChildFrame::Restore()
773{
774 wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
775 if ( parent && parent->GetClientWindow() )
776 ::SendMessage( (HWND) parent->GetClientWindow()->GetHWND(), WM_MDIRESTORE, (WPARAM) (HWND) GetHWND(), 0);
777}
778
779void wxMDIChildFrame::Activate()
780{
781 wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
782 if ( parent && parent->GetClientWindow() )
783 ::SendMessage( (HWND) parent->GetClientWindow()->GetHWND(), WM_MDIACTIVATE, (WPARAM) (HWND) GetHWND(), 0);
784}
785
786static HWND invalidHandle = 0;
787bool wxMDIChildFrame::MSWOnSize(int x, int y, WXUINT id)
788{
789 HWND hwnd = GetHwnd();
790
791 if ( !hwnd || hwnd == invalidHandle )
792 {
793 return FALSE;
794 }
795
796 switch (id)
797 {
798 case SIZEFULLSCREEN:
799 case SIZENORMAL:
800 m_iconized = FALSE;
801 break;
802
803 case SIZEICONIC:
804 m_iconized = TRUE;
805 break;
806 }
807
808 if (!m_iconized)
809 {
810 // forward WM_SIZE to status bar control
811#if wxUSE_NATIVE_STATUSBAR
812 if (m_frameStatusBar && m_frameStatusBar->IsKindOf(CLASSINFO(wxStatusBar95)))
813 {
814 wxSizeEvent event(wxSize(x, y), m_frameStatusBar->GetId());
815 event.SetEventObject( m_frameStatusBar );
816
817 ((wxStatusBar95 *)m_frameStatusBar)->OnSize(event);
818 }
819#endif
820
821 PositionStatusBar();
822 PositionToolBar();
823
824 return wxWindow::MSWOnSize(x, y, id);
825 }
826 else
827 {
828 return FALSE;
829 }
830}
831
832bool wxMDIChildFrame::MSWOnCommand(WXWORD id, WXWORD cmd, WXHWND control)
833{
834// if ((cmd == 0) && GetHWND())
835 if (GetHWND())
836 {
837 // In case it's e.g. a toolbar.
838 wxWindow *win = wxFindWinFromHandle(control);
839 if (win)
840 return win->MSWCommand(cmd, id);
841
842 if (wxCurrentPopupMenu)
843 {
844 wxMenu *popupMenu = wxCurrentPopupMenu;
845 wxCurrentPopupMenu = NULL;
846 if (popupMenu->MSWCommand(cmd, id))
847 return TRUE;
848 }
849
850 if (GetMenuBar() && GetMenuBar()->FindItemForId(id))
851 {
852 ProcessCommand(id);
853 return TRUE;
854 }
855 else
856 return FALSE;
857 return TRUE;
858 }
859 else
860 return wxWindow::MSWOnCommand(id, cmd, control);
861}
862
863long wxMDIChildFrame::MSWDefWindowProc(WXUINT message, WXUINT wParam, WXLPARAM lParam)
864{
865 if (GetHWND())
866 return DefMDIChildProc((HWND) GetHWND(), (UINT) message, (WPARAM) wParam, (LPARAM) lParam);
867 else return 0;
868}
869
870bool wxMDIChildFrame::MSWProcessMessage(WXMSG *msg)
871{
872 return FALSE;
873}
874
875bool wxMDIChildFrame::MSWTranslateMessage(WXMSG* msg)
876{
877 MSG *pMsg = (MSG *)msg;
878 if (m_acceleratorTable.Ok())
879 {
880 wxFrame *parent = (wxFrame *)GetParent();
881 HWND parent_hwnd = (HWND) parent->GetHWND();
882 return (::TranslateAccelerator(parent_hwnd, (HACCEL) m_acceleratorTable.GetHACCEL(), pMsg) != 0);
883 }
884
885 return FALSE;
886}
887
888bool wxMDIChildFrame::MSWOnMDIActivate(long activate, WXHWND WXUNUSED(one), WXHWND WXUNUSED(two))
889{
890 wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
891 HMENU parent_menu = (HMENU) parent->GetWinMenu();
892 HMENU child_menu = (HMENU) GetWinMenu();
893
894 if (activate)
895 {
896// m_active = TRUE;
897 parent->m_currentChild = this;
898 if (child_menu)
899 {
900 parent->m_parentFrameActive = FALSE;
901 HMENU subMenu = GetSubMenu((HMENU) parent->GetWindowMenu(), 0);
902#ifdef __WIN32__
903 ::SendMessage((HWND) parent->GetClientWindow()->GetHWND(), WM_MDISETMENU,
904 (WPARAM)child_menu,
905 (LPARAM)subMenu);
906#else
907 ::SendMessage((HWND) parent->GetClientWindow()->GetHWND(), WM_MDISETMENU, 0,
908 MAKELONG(child_menu, subMenu));
909#endif
910
911 ::DrawMenuBar((HWND) parent->GetHWND());
912 }
913 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, m_windowId);
914 event.SetEventObject( this );
915 return GetEventHandler()->ProcessEvent(event);
916 }
917 else
918 {
919 if (parent->m_currentChild == this)
920 parent->m_currentChild = NULL;
921
922 wxActivateEvent event(wxEVT_ACTIVATE, FALSE, m_windowId);
923 event.SetEventObject( this );
924 if ( GetEventHandler()->ProcessEvent(event) )
925 return TRUE;
926
927// m_active = FALSE;
928 if (parent_menu)
929 {
930 parent->m_parentFrameActive = TRUE;
931 HMENU subMenu = GetSubMenu((HMENU) parent->GetWindowMenu(), 0);
932#ifdef __WIN32__
933 ::SendMessage((HWND) parent->GetClientWindow()->GetHWND(), WM_MDISETMENU,
934 (WPARAM)parent_menu,
935 (LPARAM)subMenu);
936#else
937 ::SendMessage((HWND) parent->GetClientWindow()->GetHWND(), WM_MDISETMENU, 0,
938 MAKELONG(parent_menu, subMenu));
939#endif
940
941 ::DrawMenuBar((HWND) parent->GetHWND());
942 }
943 }
944 bool flag = (activate != 0);
945 wxActivateEvent event(wxEVT_ACTIVATE, flag, m_windowId);
946 event.SetEventObject( this );
947 return GetEventHandler()->ProcessEvent(event);
948}
949
950void wxMDIChildFrame::MSWDestroyWindow()
951{
952 MSWDetachWindowMenu();
953 invalidHandle = (HWND) GetHWND();
954
955 wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
956
957 // Must make sure this handle is invalidated (set to NULL)
958 // since all sorts of things could happen after the
959 // child client is destroyed, but before the wxFrame is
960 // destroyed.
961
962 HWND oldHandle = (HWND)GetHWND();
963#ifdef __WIN32__
964 SendMessage((HWND) parent->GetClientWindow()->GetHWND(), WM_MDIDESTROY, (WPARAM)oldHandle, (LPARAM)0);
965#else
966 SendMessage((HWND) parent->GetClientWindow()->GetHWND(), WM_MDIDESTROY, (HWND)oldHandle, 0);
967#endif
968 invalidHandle = 0;
969
970 if (m_hMenu)
971 {
972 ::DestroyMenu((HMENU) m_hMenu);
973 m_hMenu = 0;
974 }
975 m_hWnd = 0;
976}
977
978// Change the client window's extended style so we don't
979// get a client edge style when a child is maximised (a double
980// border looks silly.)
981bool wxMDIChildFrame::ResetWindowStyle(void *vrect)
982{
983#if defined(__WIN95__)
984 RECT *rect = (RECT *)vrect;
985 wxMDIParentFrame* pFrameWnd = (wxMDIParentFrame *)GetParent();
986 wxMDIChildFrame* pChild = pFrameWnd->GetActiveChild();
987 if (!pChild || (pChild == this))
988 {
989 DWORD dwStyle = ::GetWindowLong((HWND) pFrameWnd->GetClientWindow()->GetHWND(), GWL_EXSTYLE);
990 DWORD dwThisStyle = ::GetWindowLong((HWND) GetHWND(), GWL_STYLE);
991 DWORD dwNewStyle = dwStyle;
992 if (pChild != NULL && (dwThisStyle & WS_MAXIMIZE))
993 dwNewStyle &= ~(WS_EX_CLIENTEDGE);
994 else
995 dwNewStyle |= WS_EX_CLIENTEDGE;
996
997 if (dwStyle != dwNewStyle)
998 {
999 ::RedrawWindow((HWND) pFrameWnd->GetClientWindow()->GetHWND(), NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
1000 ::SetWindowLong((HWND) pFrameWnd->GetClientWindow()->GetHWND(), GWL_EXSTYLE, dwNewStyle);
1001 ::SetWindowPos((HWND) pFrameWnd->GetClientWindow()->GetHWND(), NULL, 0, 0, 0, 0,
1002 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOCOPYBITS);
1003 if (rect)
1004 ::GetClientRect((HWND) pFrameWnd->GetClientWindow()->GetHWND(), rect);
1005 return TRUE;
1006 }
1007 }
1008 return FALSE;
1009#else
1010 return FALSE;
1011#endif
1012}
1013
1014bool wxMDIChildFrame::MSWOnWindowPosChanging(void *pos)
1015{
1016 WINDOWPOS *lpPos = (WINDOWPOS *)pos;
1017#if defined(__WIN95__)
1018 if (!(lpPos->flags & SWP_NOSIZE))
1019 {
1020 RECT rectClient;
1021 DWORD dwExStyle = ::GetWindowLong((HWND) GetHWND(), GWL_EXSTYLE);
1022 DWORD dwStyle = ::GetWindowLong((HWND) GetHWND(), GWL_STYLE);
1023 if (ResetWindowStyle((void *) & rectClient) && (dwStyle & WS_MAXIMIZE))
1024 {
1025 ::AdjustWindowRectEx(&rectClient, dwStyle, FALSE, dwExStyle);
1026 lpPos->x = rectClient.left;
1027 lpPos->y = rectClient.top;
1028 lpPos->cx = rectClient.right - rectClient.left;
1029 lpPos->cy = rectClient.bottom - rectClient.top;
1030 }
1031 wxMDIParentFrame* pFrameWnd = (wxMDIParentFrame *)GetParent();
1032 if (pFrameWnd && pFrameWnd->GetToolBar())
1033 {
1034 pFrameWnd->GetToolBar()->Refresh();
1035 }
1036 }
1037#endif
1038
1039 return FALSE;
1040}
1041
1042// Client window
1043wxMDIClientWindow::wxMDIClientWindow()
1044{
1045 m_scrollX = 0;
1046 m_scrollY = 0;
1047}
1048
1049wxMDIClientWindow::~wxMDIClientWindow()
1050{
1051}
1052
1053bool wxMDIClientWindow::CreateClient(wxMDIParentFrame *parent, long style)
1054{
1055 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE);
1056
1057 CLIENTCREATESTRUCT ccs;
1058 m_windowStyle = style;
1059 m_parent = parent;
1060
1061 ccs.hWindowMenu = (HMENU) parent->GetWindowMenu();
1062 ccs.idFirstChild = wxFIRST_MDI_CHILD;
1063
1064 DWORD msStyle = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN ;
1065 if ( parent->GetWindowStyleFlag() & wxHSCROLL )
1066 msStyle |= WS_HSCROLL;
1067 if ( parent->GetWindowStyleFlag() & wxVSCROLL )
1068 msStyle |= WS_VSCROLL ;
1069
1070#if defined(__WIN95__)
1071 DWORD exStyle = WS_EX_CLIENTEDGE;
1072#else
1073 DWORD exStyle = 0;
1074#endif
1075
1076 wxWndHook = this;
1077 m_hWnd = (WXHWND) ::CreateWindowEx(exStyle, "mdiclient", NULL,
1078 msStyle, 0, 0, 0, 0, (HWND) parent->GetHWND(), NULL,
1079 wxGetInstance(), (LPSTR)(LPCLIENTCREATESTRUCT)&ccs);
1080 SubclassWin(m_hWnd);
1081 wxWndHook = NULL;
1082
1083 return (m_hWnd != 0) ;
1084}
1085
1086// Window procedure: here for debugging purposes
1087long wxMDIClientWindow::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
1088{
1089 return wxWindow::MSWWindowProc(nMsg, wParam, lParam);
1090// return MSWDefWindowProc(nMsg, wParam, lParam);
1091}
1092
1093long wxMDIClientWindow::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
1094{
1095 if ( MSWGetOldWndProc() != 0)
1096 return ::CallWindowProc(CASTWNDPROC MSWGetOldWndProc(), (HWND) GetHWND(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam);
1097 else
1098 return ::DefWindowProc((HWND) m_hWnd, (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam);
1099}
1100
1101// Explicitly call default scroll behaviour
1102void wxMDIClientWindow::OnScroll(wxScrollEvent& event)
1103{
1104 // Note: for client windows, the scroll position is not set in
1105 // WM_HSCROLL, WM_VSCROLL, so we can't easily determine what
1106 // scroll position we're at.
1107 // This makes it hard to paint patterns or bitmaps in the background,
1108 // and have the client area scrollable as well.
1109
1110 if ( event.GetOrientation() == wxHORIZONTAL )
1111 m_scrollX = event.GetPosition(); // Always returns zero!
1112 else
1113 m_scrollY = event.GetPosition(); // Always returns zero!
1114
1115 Default();
1116}