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