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