1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: MDI classes
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "mdi.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
29 #include "wx/dialog.h"
30 #include "wx/statusbr.h"
31 #include "wx/settings.h"
35 #include "wx/msw/private.h"
37 #if USE_NATIVE_STATUSBAR
38 #include <wx/msw/statbr95.h>
43 extern wxList wxModelessWindows
;
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
54 // Status border dimensions
55 #define wxTHICK_LINE_BORDER 3
56 #define wxTHICK_LINE_WIDTH 1
58 extern char wxMDIFrameClassName
[];
59 extern char wxMDIChildFrameClassName
[];
60 extern wxWindow
*wxWndHook
;
62 #if !USE_SHARED_LIBRARY
63 IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame
, wxFrame
)
64 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame
, wxFrame
)
65 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow
, wxWindow
)
67 BEGIN_EVENT_TABLE(wxMDIParentFrame
, wxFrame
)
68 EVT_SIZE(wxMDIParentFrame::OnSize
)
69 EVT_ACTIVATE(wxMDIParentFrame::OnActivate
)
70 EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged
)
73 BEGIN_EVENT_TABLE(wxMDIClientWindow
, wxWindow
)
74 EVT_SCROLL(wxMDIClientWindow::OnScroll
)
79 wxMDIParentFrame::wxMDIParentFrame(void)
81 m_clientWindow
= NULL
;
82 m_currentChild
= NULL
;
84 m_parentFrameActive
= TRUE
;
85 m_frameToolBar
= NULL
;
88 bool wxMDIParentFrame::Create(wxWindow
*parent
,
90 const wxString
& title
,
96 m_defaultIcon
= (WXHICON
) (wxSTD_MDIPARENTFRAME_ICON
? wxSTD_MDIPARENTFRAME_ICON
: wxDEFAULT_MDIPARENTFRAME_ICON
);
98 m_frameToolBar
= NULL
;
99 m_clientWindow
= NULL
;
100 m_currentChild
= NULL
;
102 m_parentFrameActive
= TRUE
;
105 wxTopLevelWindows
.Append(this);
108 m_windowStyle
= style
;
110 if (parent
) parent
->AddChild(this);
115 m_windowId
= (int)NewControlId();
122 m_windowMenu
= (WXHMENU
) ::LoadMenu(wxGetInstance(), "wxWindowMenu");
125 wxDebugMsg("Loaded m_windowMenu %d\n", m_windowMenu
);
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
;
146 wxWindow::MSWCreate(m_windowId
, parent
, wxMDIFrameClassName
, this, title
, x
, y
, width
, height
,
149 wxModelessWindows
.Append(this);
154 wxMDIParentFrame::~wxMDIParentFrame(void)
158 DestroyMenu((HMENU
) m_windowMenu
); // Destroy dummy "Window" menu
161 if (m_clientWindow
->MSWGetOldWndProc())
162 m_clientWindow
->UnsubclassWin();
164 m_clientWindow
->m_hWnd
= 0;
165 delete m_clientWindow
;
168 // Get size *available for subwindows* i.e. excluding menu bar.
169 void wxMDIParentFrame::GetClientSize(int *x
, int *y
) const
172 GetClientRect((HWND
) GetHWND(), &rect
);
174 int cwidth
= rect
.right
;
175 int cheight
= rect
.bottom
;
180 m_frameToolBar->GetSize(&tw, &th);
184 if ( GetStatusBar() )
187 GetStatusBar()->GetSize(&sw
, &sh
);
195 void wxMDIParentFrame::SetMenuBar(wxMenuBar
*menu_bar
)
199 m_frameMenuBar
= NULL
;
203 if (menu_bar
->m_menuBarFrame
)
207 HMENU menu
= CreateMenu();
209 for (i
= 0; i
< menu_bar
->m_menuCount
; i
++)
211 HMENU popup
= (HMENU
)menu_bar
->m_menus
[i
]->m_hMenu
;
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.
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
]);
223 menu_bar
->m_hMenu
= (WXHMENU
)menu
;
225 delete m_frameMenuBar
;
227 this->m_hMenu
= (WXHMENU
) menu
;
229 // MDI parent-specific code follows
231 HMENU subMenu
= GetSubMenu((HMENU
) m_windowMenu
, 0);
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
++)
239 int chars
= GetMenuString(menu
, i
, buf
, 100, MF_BYPOSITION
);
240 if ((chars
> 0) && (strcmp(buf
, "&Help") == 0 ||
241 strcmp(buf
, "Help") == 0))
244 InsertMenu(menu
, i
, MF_BYPOSITION
| MF_POPUP
| MF_STRING
,
245 (UINT
)subMenu
, "&Window");
250 AppendMenu(menu
, MF_POPUP
,
253 m_parentFrameActive
= TRUE
;
255 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDISETMENU
,
259 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDISETMENU
, 0,
260 MAKELPARAM(menu
, subMenu
));
262 DrawMenuBar((HWND
) GetHWND());
264 m_frameMenuBar
= menu_bar
;
265 menu_bar
->m_menuBarFrame
= this;
268 void wxMDIParentFrame::OnSize(wxSizeEvent
& event
)
277 GetClientSize(&width
, &height
);
281 GetToolBar()->GetSize(&wt
, &ht
);
284 GetToolBar()->SetSize(0, 0, width
, ht
);
287 if ( GetClientWindow() )
288 GetClientWindow()->SetSize(x
, y
, width
, height
);
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
);
297 void wxMDIParentFrame::OnActivate(wxActivateEvent
& event
)
302 #if WXWIN_COMPATIBILITY
303 void wxMDIParentFrame::OldOnSize(int x
, int y
)
305 #if WXWIN_COMPATIBILITY == 1
306 wxSizeEvent
event(wxSize(x
, y
), m_windowId
);
307 event
.SetEventObject( this );
308 GetEventHandler()->ProcessEvent(event
);
318 GetClientSize(&width
, &height
);
322 GetToolBar()->GetSize(&wt
, &ht
);
327 if ( GetClientWindow() )
328 GetClientWindow()->SetSize(x
, y
, width
, height
);
333 // Default activation behaviour - nothing.
334 // Default activation behaviour - override dedault wxFrame behaviour
335 void wxMDIParentFrame::OldOnActivate(bool flag
)
337 #if WXWIN_COMPATIBILITY == 1
338 wxActivateEvent
event(wxEVT_ACTIVATE
, flag
, m_windowId
);
339 event
.SetEventObject( this );
340 GetEventHandler()->ProcessEvent(event
);
347 // Returns the active MDI child window
348 wxMDIChildFrame
*wxMDIParentFrame::GetActiveChild(void) const
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);
355 return (wxMDIChildFrame
*)wxFindWinFromHandle((WXHWND
) hWnd
);
358 // Create the client window class (don't Create the window,
359 // just return a new class)
360 wxMDIClientWindow
*wxMDIParentFrame::OnCreateClient(void)
362 return new wxMDIClientWindow
;
365 // Responds to colour changes, and passes event on to children.
366 void wxMDIParentFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
)
368 if ( m_clientWindow
)
370 m_clientWindow
->SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
));
371 m_clientWindow
->Refresh();
374 if ( m_frameToolBar )
376 wxSysColourChangedEvent event2;
377 event2.eventObject = m_frameToolBar;
378 m_frameToolBar->GetEventHandler()->ProcessEvent(event2);
382 // Propagate the event to the non-top-level children
383 wxFrame::OnSysColourChanged(event
);
387 void wxMDIParentFrame::Cascade(void)
389 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDICASCADE
, 0, 0);
392 void wxMDIParentFrame::Tile(void)
394 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDITILE
, MDITILE_HORIZONTAL
, 0);
397 void wxMDIParentFrame::ArrangeIcons(void)
399 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDIICONARRANGE
, 0, 0);
402 void wxMDIParentFrame::ActivateNext(void)
404 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDINEXT
, 0, 0);
407 void wxMDIParentFrame::ActivatePrevious(void)
409 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDINEXT
, 0, 1);
414 // Returns a style for the client window - usually 0
415 // or, for example, wxHSCROLL | wxVSCROLL
416 long wxMDIParentFrame::GetClientStyle(void) const
418 return wxHSCROLL | wxVSCROLL ;
422 bool wxMDIParentFrame::MSWOnDestroy(void)
427 void wxMDIParentFrame::MSWOnCreate(WXLPCREATESTRUCT
WXUNUSED(cs
))
429 m_clientWindow
= new wxMDIClientWindow
;
430 // Uses own style for client style
431 m_clientWindow
->CreateClient(this, GetWindowStyleFlag());
434 void wxMDIParentFrame::MSWOnSize(const int x
, const int y
, const WXUINT id
)
449 // forward WM_SIZE to status bar control
450 #if USE_NATIVE_STATUSBAR
451 if (m_frameStatusBar
&& m_frameStatusBar
->IsKindOf(CLASSINFO(wxStatusBar95
)))
453 wxSizeEvent
event(wxSize(x
, y
), m_frameStatusBar
->GetId());
454 event
.SetEventObject( m_frameStatusBar
);
456 ((wxStatusBar95
*)m_frameStatusBar
)->OnSize(event
);
462 GetEventHandler()->OldOnSize(x
, y
);
466 bool wxMDIParentFrame::MSWOnActivate(const int state
, const bool minimized
, const WXHWND activate
)
468 wxWindow::MSWOnActivate(state
, minimized
, activate
);
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
)))
474 #if WXWIN_COMPATIBILITY
475 m_currentChild
->GetEventHandler()->OldOnActivate(TRUE
);
477 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
,
478 m_currentChild
.m_windowId
);
479 event
.eventObject
= m_currentChild
;
480 m_currentChild
->GetEventHandler()->ProcessEvent(event
);
486 bool wxMDIParentFrame::MSWOnCommand(const WXWORD id
, const WXWORD cmd
, const WXHWND control
)
490 // In case it's e.g. a toolbar.
491 wxWindow
*win
= wxFindWinFromHandle(control
);
493 return win
->MSWCommand(cmd
, id
);
497 case IDM_WINDOWCASCADE
:
498 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDICASCADE
, MDITILE_SKIPDISABLED
, 0);
501 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDITILE
, MDITILE_HORIZONTAL
, 0);
503 case IDM_WINDOWICONS
:
504 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDIICONARRANGE
, 0, 0);
507 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDINEXT
, 0, 0);
515 wxDebugMsg("wxMDIFrame::OnCommand %d: system command: calling default window proc\n", GetHWND());
517 return FALSE
; // Get WndProc to call default proc
520 if (m_parentFrameActive
&& (id
< wxFIRST_MDI_CHILD
|| id
> wxLAST_MDI_CHILD
))
525 else if (m_currentChild
&& (id
< wxFIRST_MDI_CHILD
|| id
> wxLAST_MDI_CHILD
))
528 wxDebugMsg("wxMDIFrame::MSWOnCommand %d: calling child OnCommand\n", GetHWND());
530 return m_currentChild
->MSWOnCommand(id
, cmd
, control
);
533 if (id
>= wxFIRST_MDI_CHILD
&& id
<= wxLAST_MDI_CHILD
)
535 wxNode
* node
= GetChildren()->First();
538 wxWindow
* child
= (wxWindow
*) node
->Data();
539 if (child
->GetHWND())
542 long childId
= GetWindowLong((HWND
) child
->GetHWND(), GWL_ID
);
544 long childId
= GetWindowWord((HWND
) child
->GetHWND(), GWW_ID
);
548 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDIACTIVATE
, (WPARAM
) (HWND
) child
->GetHWND(), 0);
555 wxWindow* child = FindItem(id);
558 ::SendMessage( (HWND) GetClientWindow()->GetHWND(), WM_MDIACTIVATE, (WPARAM) (HWND) child->GetHWND(), 0);
567 void wxMDIParentFrame::MSWOnMenuHighlight(const WXWORD nItem
, const WXWORD nFlags
, const WXHMENU hSysMenu
)
569 if (m_parentFrameActive
)
572 if (nFlags
== 0xFFFF && hSysMenu
== (WXHMENU
) NULL
)
573 GetEventHandler()->OldOnMenuSelect(-1);
574 else if (nFlags
!= MF_SEPARATOR
)
575 GetEventHandler()->OldOnMenuSelect(nItem
);
577 else if (m_currentChild
)
579 m_currentChild
->MSWOnMenuHighlight(nItem
, nFlags
, hSysMenu
);
583 long wxMDIParentFrame::MSWDefWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
586 if ( GetClientWindow() )
587 clientWnd
= GetClientWindow()->GetHWND();
591 return DefFrameProc((HWND
) GetHWND(), (HWND
) clientWnd
, message
, wParam
, lParam
);
594 bool wxMDIParentFrame::MSWProcessMessage(WXMSG
* msg
)
596 MSG
*pMsg
= (MSG
*)msg
;
598 if ((m_currentChild
!= (wxWindow
*)NULL
) && (m_currentChild
->GetHWND() != (WXHWND
) NULL
) && m_currentChild
->MSWProcessMessage(msg
))
601 if (m_acceleratorTable
!= (WXHANDLE
) NULL
&&
602 ::TranslateAccelerator((HWND
) GetHWND(), (HANDLE
) m_acceleratorTable
, pMsg
))
605 if (pMsg
->message
== WM_KEYDOWN
|| pMsg
->message
== WM_SYSKEYDOWN
)
607 if (::TranslateMDISysAccel((HWND
) GetClientWindow()->GetHWND(), pMsg
))
614 bool wxMDIParentFrame::MSWOnEraseBkgnd(const WXHDC
WXUNUSED(pDC
))
619 extern wxWindow
*wxWndHook
;
620 extern wxList
*wxWinHandleList
;
622 wxMDIChildFrame::wxMDIChildFrame(void)
627 bool wxMDIChildFrame::Create(wxMDIParentFrame
*parent
,
629 const wxString
& title
,
633 const wxString
& name
)
635 m_defaultIcon
= (WXHICON
) (wxSTD_MDICHILDFRAME_ICON
? wxSTD_MDICHILDFRAME_ICON
: wxDEFAULT_MDICHILDFRAME_ICON
);
642 m_windowId
= (int)NewControlId();
644 if (parent
) parent
->AddChild(this);
655 mcs
.szClass
= wxMDIChildFrameClassName
;
657 mcs
.hOwner
= wxGetInstance();
658 if (x
> -1) mcs
.x
= x
;
659 else mcs
.x
= CW_USEDEFAULT
;
661 if (y
> -1) mcs
.y
= y
;
662 else mcs
.y
= CW_USEDEFAULT
;
664 if (width
> -1) mcs
.cx
= width
;
665 else mcs
.cx
= CW_USEDEFAULT
;
667 if (height
> -1) mcs
.cy
= height
;
668 else mcs
.cy
= CW_USEDEFAULT
;
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
;
690 DWORD Return
= SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(),
691 WM_MDICREATE
, 0, (LONG
)(LPSTR
)&mcs
);
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
;
697 // This gets reassigned so can't be stored
698 // m_windowId = GetWindowLong((HWND) m_hWnd, GWL_ID);
701 wxWinHandleList
->Append((long)GetHWND(), this);
703 SetWindowLong((HWND
) GetHWND(), 0, (long)this);
705 wxModelessWindows
.Append(this);
709 wxMDIChildFrame::~wxMDIChildFrame(void)
713 ResetWindowStyle(NULL
);
716 // Set the client size (i.e. leave the calculation of borders etc.
718 void wxMDIChildFrame::SetClientSize(const int width
, const int height
)
720 HWND hWnd
= (HWND
) GetHWND();
723 GetClientRect(hWnd
, &rect
);
726 GetWindowRect(hWnd
, &rect2
);
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
731 int actual_width
= rect2
.right
- rect2
.left
- rect
.right
+ width
;
732 int actual_height
= rect2
.bottom
- rect2
.top
- rect
.bottom
+ height
;
737 GetStatusBar()->GetSize(&sx
, &sy
);
742 point
.x
= rect2
.left
;
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
);
750 MoveWindow(hWnd
, point
.x
, point
.y
, actual_width
, actual_height
, (BOOL
)TRUE
);
751 #if WXWIN_COMPATIBILITY
752 GetEventHandler()->OldOnSize(width
, height
);
754 wxSizeEvent
event(wxSize(width
, height
), m_windowId
);
755 event
.eventObject
= this;
756 GetEventHandler()->ProcessEvent(event
);
760 void wxMDIChildFrame::GetPosition(int *x
, int *y
) const
763 GetWindowRect((HWND
) GetHWND(), &rect
);
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
);
777 void wxMDIChildFrame::SetMenuBar(wxMenuBar
*menu_bar
)
781 m_frameMenuBar
= NULL
;
785 if (menu_bar
->m_menuBarFrame
)
789 HMENU menu
= CreateMenu();
791 for (i
= 0; i
< menu_bar
->m_menuCount
; i
++)
793 HMENU popup
= (HMENU
)menu_bar
->m_menus
[i
]->m_hMenu
;
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.
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
]);
805 menu_bar
->m_hMenu
= (WXHMENU
)menu
;
807 delete m_frameMenuBar
;
809 this->m_hMenu
= (WXHMENU
) menu
;
811 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
813 parent
->m_parentFrameActive
= FALSE
;
814 HMENU subMenu
= GetSubMenu((HWND
) parent
->GetWindowMenu(), 0);
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
++)
822 int chars
= GetMenuString(menu
, i
, buf
, 100, MF_BYPOSITION
);
823 if ((chars
> 0) && (strcmp(buf
, "&Help") == 0 ||
824 strcmp(buf
, "Help") == 0))
827 InsertMenu(menu
, i
, MF_BYPOSITION
| MF_POPUP
| MF_STRING
,
828 (UINT
)subMenu
, "&Window");
833 AppendMenu(menu
, MF_POPUP
,
837 SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
,
841 SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
, 0,
842 MAKELPARAM(menu
, subMenu
));
845 DrawMenuBar((HWND
) parent
->GetHWND());
846 m_frameMenuBar
= menu_bar
;
847 menu_bar
->m_menuBarFrame
= this;
851 void wxMDIChildFrame::Maximize(void)
853 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
854 if ( parent
&& parent
->GetClientWindow() )
855 ::SendMessage( (HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDIMAXIMIZE
, (WPARAM
) (HWND
) GetHWND(), 0);
858 void wxMDIChildFrame::Restore(void)
860 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
861 if ( parent
&& parent
->GetClientWindow() )
862 ::SendMessage( (HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDIRESTORE
, (WPARAM
) (HWND
) GetHWND(), 0);
865 void wxMDIChildFrame::Activate(void)
867 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
868 if ( parent
&& parent
->GetClientWindow() )
869 ::SendMessage( (HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDIACTIVATE
, (WPARAM
) (HWND
) GetHWND(), 0);
872 static HWND invalidHandle
= 0;
873 void wxMDIChildFrame::MSWOnSize(const int x
, const int y
, const WXUINT id
)
875 if (!GetHWND()) return;
877 if (invalidHandle
== (HWND
) GetHWND())
880 wxDebugMsg("wxMDIChildFrame::OnSize %d: invalid, so returning.\n", GetHWND());
885 (void)MSWDefWindowProc(m_lastMsg
, m_lastWParam
, m_lastLParam
);
900 // forward WM_SIZE to status bar control
901 #if USE_NATIVE_STATUSBAR
902 if (m_frameStatusBar
&& m_frameStatusBar
->IsKindOf(CLASSINFO(wxStatusBar95
)))
904 wxSizeEvent
event(wxSize(x
, y
), m_frameStatusBar
->GetId());
905 event
.SetEventObject( m_frameStatusBar
);
907 ((wxStatusBar95
*)m_frameStatusBar
)->OnSize(event
);
913 wxWindow::MSWOnSize(x
, y
, id
);
917 bool wxMDIChildFrame::MSWOnCommand(const WXWORD id
, const WXWORD cmd
, const WXHWND control
)
920 wxDebugMsg("wxMDIChildFrame::MSWOnCommand %d\n", GetHWND());
922 if ((cmd
== 0) && GetHWND())
924 // In case it's e.g. a toolbar.
925 wxWindow
*win
= wxFindWinFromHandle(control
);
927 return win
->MSWCommand(cmd
, id
);
929 if (GetMenuBar() && GetMenuBar()->FindItemForId(id
))
942 long wxMDIChildFrame::MSWDefWindowProc(WXUINT message
, WXUINT wParam
, WXLPARAM lParam
)
945 return DefMDIChildProc((HWND
) GetHWND(), (UINT
) message
, (WPARAM
) wParam
, (LPARAM
) lParam
);
949 bool wxMDIChildFrame::MSWProcessMessage(WXMSG
*msg
)
951 MSG
*pMsg
= (MSG
*)msg
;
952 if (m_acceleratorTable
&& GetHWND())
954 wxFrame
*parent
= (wxFrame
*)GetParent();
955 HWND parent_hwnd
= (HWND
) parent
->GetHWND();
956 return (::TranslateAccelerator(parent_hwnd
, (HANDLE
) m_acceleratorTable
, pMsg
) != 0);
961 long wxMDIChildFrame::MSWOnMDIActivate(const long activate
, const WXHWND
WXUNUSED(one
), const WXHWND
WXUNUSED(two
))
963 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
964 HMENU parent_menu
= (HMENU
) parent
->GetWinMenu();
966 wxDebugMsg("Parent menu is %d\n", parent_menu
);
968 HMENU child_menu
= (HMENU
) GetWinMenu();
970 wxDebugMsg("Child menu is %d\n", child_menu
);
976 parent
->m_currentChild
= this;
979 parent
->m_parentFrameActive
= FALSE
;
980 HMENU subMenu
= GetSubMenu((HMENU
) parent
->GetWindowMenu(), 0);
982 wxDebugMsg("Window submenu is %d\n", subMenu
);
984 // HMENU subMenu = 0;
986 ::SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
,
990 ::SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
, 0,
991 MAKELONG(child_menu
, subMenu
));
994 ::DrawMenuBar((HWND
) parent
->GetHWND());
996 GetEventHandler()->OldOnActivate(TRUE
);
1000 if (parent
->m_currentChild
== this)
1001 parent
->m_currentChild
= NULL
;
1002 GetEventHandler()->OldOnActivate(FALSE
);
1004 // m_active = FALSE;
1007 parent
->m_parentFrameActive
= TRUE
;
1008 HMENU subMenu
= GetSubMenu((HMENU
) parent
->GetWindowMenu(), 0);
1010 wxDebugMsg("Window submenu is %d\n", subMenu
);
1012 // HMENU subMenu = 0;
1014 ::SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
,
1015 (WPARAM
)parent_menu
,
1018 ::SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
, 0,
1019 MAKELONG(parent_menu
, subMenu
));
1022 ::DrawMenuBar((HWND
) parent
->GetHWND());
1026 bool flag
= (activate
!= 0);
1027 GetEventHandler()->OldOnActivate(flag
);
1029 wxDebugMsg("Finished (de)activating\n");
1034 void wxMDIChildFrame::MSWDestroyWindow(void)
1036 MSWDetachWindowMenu();
1037 invalidHandle
= (HWND
) GetHWND();
1039 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
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
1046 HWND oldHandle
= (HWND
)GetHWND();
1048 wxDebugMsg("*** About to DestroyWindow MDI child %d\n", oldHandle
);
1051 SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDIDESTROY
, (WPARAM
)oldHandle
, (LPARAM
)0);
1053 SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDIDESTROY
, (HWND
)oldHandle
, 0);
1056 wxDebugMsg("*** Finished DestroyWindow MDI child %d\n", oldHandle
);
1062 ::DestroyMenu((HMENU
) m_hMenu
);
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.)
1071 bool wxMDIChildFrame::ResetWindowStyle(void *vrect
)
1073 #if defined(__WIN95__)
1074 RECT
*rect
= (RECT
*)vrect
;
1075 wxMDIParentFrame
* pFrameWnd
= (wxMDIParentFrame
*)GetParent();
1076 wxMDIChildFrame
* pChild
= pFrameWnd
->GetActiveChild();
1077 if (!pChild
|| (pChild
== this))
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
);
1085 dwNewStyle
|= WS_EX_CLIENTEDGE
;
1087 if (dwStyle
!= dwNewStyle
)
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
);
1094 ::GetClientRect((HWND
) pFrameWnd
->GetClientWindow()->GetHWND(), rect
);
1104 void wxMDIChildFrame::MSWOnWindowPosChanging(void *pos
)
1106 WINDOWPOS
*lpPos
= (WINDOWPOS
*)pos
;
1107 #if defined(__WIN95__)
1108 if (!(lpPos
->flags
& SWP_NOSIZE
))
1111 DWORD dwExStyle
= ::GetWindowLong((HWND
) GetHWND(), GWL_EXSTYLE
);
1112 DWORD dwStyle
= ::GetWindowLong((HWND
) GetHWND(), GWL_STYLE
);
1113 if (ResetWindowStyle((void *) & rectClient
) && (dwStyle
& WS_MAXIMIZE
))
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
;
1121 wxMDIParentFrame
* pFrameWnd
= (wxMDIParentFrame
*)GetParent();
1122 if (pFrameWnd
&& pFrameWnd
->GetToolBar())
1124 pFrameWnd
->GetToolBar()->Refresh();
1132 wxMDIClientWindow::wxMDIClientWindow(void)
1138 wxMDIClientWindow::~wxMDIClientWindow(void)
1142 bool wxMDIClientWindow::CreateClient(wxMDIParentFrame
*parent
, const long style
)
1144 m_backgroundColour
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
);
1146 CLIENTCREATESTRUCT ccs
;
1147 m_windowStyle
= style
;
1148 m_windowParent
= parent
;
1150 ccs
.hWindowMenu
= (HMENU
) parent
->GetWindowMenu();
1151 ccs
.idFirstChild
= wxFIRST_MDI_CHILD
;
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
;
1159 #if defined(__WIN95__)
1160 DWORD exStyle
= WS_EX_CLIENTEDGE
;
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
);
1172 return (m_hWnd
!= 0) ;
1175 // Window procedure: here for debugging purposes
1176 long wxMDIClientWindow::MSWWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1178 return wxWindow::MSWWindowProc(nMsg
, wParam
, lParam
);
1179 // return MSWDefWindowProc(nMsg, wParam, lParam);
1182 long wxMDIClientWindow::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1184 if ( MSWGetOldWndProc() != 0)
1185 return ::CallWindowProc(CASTWNDPROC (FARPROC
) MSWGetOldWndProc(), (HWND
) GetHWND(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1187 return ::DefWindowProc((HWND
) m_hWnd
, (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1190 // Explicitly call default scroll behaviour
1191 void wxMDIClientWindow::OnScroll(wxScrollEvent
& event
)
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.
1199 if ( event
.GetOrientation() == wxHORIZONTAL
)
1200 m_scrollX
= event
.GetPosition(); // Always returns zero!
1202 m_scrollY
= event
.GetPosition(); // Always returns zero!
1207 // Should hand the message to the default proc
1208 long wxMDIClientWindow::MSWOnMDIActivate(const long bActivate
, const WXHWND
, const WXHWND
)