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