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