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