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