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 wxUSE_NATIVE_STATUSBAR
38 #include <wx/msw/statbr95.h>
43 extern wxList wxModelessWindows
;
44 extern wxMenu
*wxCurrentPopupMenu
;
46 #define IDM_WINDOWTILE 4001
47 #define IDM_WINDOWCASCADE 4002
48 #define IDM_WINDOWICONS 4003
49 #define IDM_WINDOWNEXT 4004
50 // This range gives a maximum of 500
51 // MDI children. Should be enough :-)
52 #define wxFIRST_MDI_CHILD 4100
53 #define wxLAST_MDI_CHILD 4600
55 // Status border dimensions
56 #define wxTHICK_LINE_BORDER 3
57 #define wxTHICK_LINE_WIDTH 1
59 extern char wxMDIFrameClassName
[];
60 extern char wxMDIChildFrameClassName
[];
61 extern wxWindow
*wxWndHook
;
63 #if !USE_SHARED_LIBRARY
64 IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame
, wxFrame
)
65 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame
, wxFrame
)
66 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow
, wxWindow
)
68 BEGIN_EVENT_TABLE(wxMDIParentFrame
, wxFrame
)
69 EVT_SIZE(wxMDIParentFrame::OnSize
)
70 EVT_ACTIVATE(wxMDIParentFrame::OnActivate
)
71 EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged
)
74 BEGIN_EVENT_TABLE(wxMDIClientWindow
, wxWindow
)
75 EVT_SCROLL(wxMDIClientWindow::OnScroll
)
80 wxMDIParentFrame::wxMDIParentFrame(void)
82 m_clientWindow
= NULL
;
83 m_currentChild
= NULL
;
85 m_parentFrameActive
= TRUE
;
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_clientWindow
= NULL
;
99 m_currentChild
= NULL
;
101 m_parentFrameActive
= TRUE
;
104 wxTopLevelWindows
.Append(this);
107 m_windowStyle
= style
;
109 if (parent
) parent
->AddChild(this);
114 m_windowId
= (int)NewControlId();
121 m_windowMenu
= (WXHMENU
) ::LoadMenu(wxGetInstance(), "wxWindowMenu");
123 DWORD msflags
= WS_OVERLAPPED
;
124 if (style
& wxMINIMIZE_BOX
)
125 msflags
|= WS_MINIMIZEBOX
;
126 if (style
& wxMAXIMIZE_BOX
)
127 msflags
|= WS_MAXIMIZEBOX
;
128 if (style
& wxTHICK_FRAME
)
129 msflags
|= WS_THICKFRAME
;
130 if (style
& wxSYSTEM_MENU
)
131 msflags
|= WS_SYSMENU
;
132 if ((style
& wxMINIMIZE
) || (style
& wxICONIZE
))
133 msflags
|= WS_MINIMIZE
;
134 if (style
& wxMAXIMIZE
)
135 msflags
|= WS_MAXIMIZE
;
136 if (style
& wxCAPTION
)
137 msflags
|= WS_CAPTION
;
139 // Adding WS_CLIPCHILDREN causes children not to be properly
140 // drawn when first displaying them.
141 // if (style & wxCLIP_CHILDREN)
142 // msflags |= WS_CLIPCHILDREN;
144 wxWindow::MSWCreate(m_windowId
, parent
, wxMDIFrameClassName
, this, title
, x
, y
, width
, height
,
147 wxModelessWindows
.Append(this);
152 wxMDIParentFrame::~wxMDIParentFrame(void)
156 DestroyMenu((HMENU
) m_windowMenu
); // Destroy dummy "Window" menu
159 if (m_clientWindow
->MSWGetOldWndProc())
160 m_clientWindow
->UnsubclassWin();
162 m_clientWindow
->m_hWnd
= 0;
163 delete m_clientWindow
;
166 // Get size *available for subwindows* i.e. excluding menu bar.
167 void wxMDIParentFrame::GetClientSize(int *x
, int *y
) const
170 ::GetClientRect((HWND
) GetHWND(), &rect
);
172 int cwidth
= rect
.right
;
173 int cheight
= rect
.bottom
;
175 if ( GetStatusBar() )
178 GetStatusBar()->GetSize(&sw
, &sh
);
182 wxPoint
pt(GetClientAreaOrigin());
190 void wxMDIParentFrame::SetMenuBar(wxMenuBar
*menu_bar
)
194 m_frameMenuBar
= NULL
;
198 if (menu_bar
->m_menuBarFrame
)
202 HMENU menu
= CreateMenu();
204 for (i
= 0; i
< menu_bar
->m_menuCount
; i
++)
206 HMENU popup
= (HMENU
)menu_bar
->m_menus
[i
]->m_hMenu
;
208 // After looking Bounds Checker result, it seems that all
209 // menus must be individually destroyed. So, don't reset m_hMenu,
210 // to allow ~wxMenu to do the job.
212 menu_bar
->m_menus
[i
]->m_savehMenu
= (WXHMENU
) popup
;
213 // Uncommenting for the moment... JACS
214 menu_bar
->m_menus
[i
]->m_hMenu
= (WXHMENU
) NULL
;
215 AppendMenu(menu
, MF_POPUP
| MF_STRING
, (UINT
)popup
, menu_bar
->m_titles
[i
]);
218 menu_bar
->m_hMenu
= (WXHMENU
)menu
;
220 delete m_frameMenuBar
;
222 this->m_hMenu
= (WXHMENU
) menu
;
224 // MDI parent-specific code follows
226 HMENU subMenu
= GetSubMenu((HMENU
) m_windowMenu
, 0);
228 // Try to insert Window menu in front of Help, otherwise append it.
229 int N
= GetMenuItemCount(menu
);
230 bool success
= FALSE
;
231 for (i
= 0; i
< N
; i
++)
234 int chars
= GetMenuString(menu
, i
, buf
, 100, MF_BYPOSITION
);
235 if ((chars
> 0) && (strcmp(buf
, "&Help") == 0 ||
236 strcmp(buf
, "Help") == 0))
239 InsertMenu(menu
, i
, MF_BYPOSITION
| MF_POPUP
| MF_STRING
,
240 (UINT
)subMenu
, "&Window");
245 AppendMenu(menu
, MF_POPUP
,
248 m_parentFrameActive
= TRUE
;
250 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDISETMENU
,
254 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDISETMENU
, 0,
255 MAKELPARAM(menu
, subMenu
));
257 DrawMenuBar((HWND
) GetHWND());
259 m_frameMenuBar
= menu_bar
;
260 menu_bar
->m_menuBarFrame
= this;
263 void wxMDIParentFrame::OnSize(wxSizeEvent
& event
)
265 #if wxUSE_CONSTRAINTS
272 GetClientSize(&width
, &height
);
274 if ( GetClientWindow() )
275 GetClientWindow()->SetSize(x
, y
, width
, height
);
277 /* Already done in MSWOnSize
278 // forward WM_SIZE to status bar control
279 #if wxUSE_NATIVE_STATUSBAR
280 if (m_frameStatusBar && m_frameStatusBar->IsKindOf(CLASSINFO(wxStatusBar95)))
281 ((wxStatusBar95 *)m_frameStatusBar)->OnSize(event);
287 void wxMDIParentFrame::OnActivate(wxActivateEvent
& event
)
292 // Returns the active MDI child window
293 wxMDIChildFrame
*wxMDIParentFrame::GetActiveChild(void) const
295 // HWND hWnd = (HWND)LOWORD(SendMessage((HWND) GetClientWindow()->GetHWND(), WM_MDIGETACTIVE, 0, 0L));
296 HWND hWnd
= (HWND
)SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDIGETACTIVE
, 0, 0L);
300 return (wxMDIChildFrame
*)wxFindWinFromHandle((WXHWND
) hWnd
);
303 // Create the client window class (don't Create the window,
304 // just return a new class)
305 wxMDIClientWindow
*wxMDIParentFrame::OnCreateClient(void)
307 return new wxMDIClientWindow
;
310 // Responds to colour changes, and passes event on to children.
311 void wxMDIParentFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
)
313 if ( m_clientWindow
)
315 m_clientWindow
->SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
));
316 m_clientWindow
->Refresh();
319 if ( m_frameToolBar )
321 wxSysColourChangedEvent event2;
322 event2.eventObject = m_frameToolBar;
323 m_frameToolBar->GetEventHandler()->ProcessEvent(event2);
327 // Propagate the event to the non-top-level children
328 wxFrame::OnSysColourChanged(event
);
332 void wxMDIParentFrame::Cascade(void)
334 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDICASCADE
, 0, 0);
337 void wxMDIParentFrame::Tile(void)
339 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDITILE
, MDITILE_HORIZONTAL
, 0);
342 void wxMDIParentFrame::ArrangeIcons(void)
344 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDIICONARRANGE
, 0, 0);
347 void wxMDIParentFrame::ActivateNext(void)
349 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDINEXT
, 0, 0);
352 void wxMDIParentFrame::ActivatePrevious(void)
354 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDINEXT
, 0, 1);
359 // Returns a style for the client window - usually 0
360 // or, for example, wxHSCROLL | wxVSCROLL
361 long wxMDIParentFrame::GetClientStyle(void) const
363 return wxHSCROLL | wxVSCROLL ;
367 bool wxMDIParentFrame::MSWOnDestroy(void)
372 void wxMDIParentFrame::MSWOnCreate(WXLPCREATESTRUCT
WXUNUSED(cs
))
374 m_clientWindow
= OnCreateClient();
375 // Uses own style for client style
376 m_clientWindow
->CreateClient(this, GetWindowStyleFlag());
379 void wxMDIParentFrame::MSWOnSize(int x
, int y
, WXUINT id
)
394 // forward WM_SIZE to status bar control
395 #if wxUSE_NATIVE_STATUSBAR
396 if (m_frameStatusBar
&& m_frameStatusBar
->IsKindOf(CLASSINFO(wxStatusBar95
)))
398 wxSizeEvent
event(wxSize(x
, y
), m_frameStatusBar
->GetId());
399 event
.SetEventObject( m_frameStatusBar
);
401 ((wxStatusBar95
*)m_frameStatusBar
)->OnSize(event
);
408 wxSizeEvent
event(wxSize(x
, y
), m_windowId
);
409 event
.SetEventObject( this );
410 if (!GetEventHandler()->ProcessEvent(event
))
415 bool wxMDIParentFrame::MSWOnActivate(int state
, bool minimized
, WXHWND activate
)
417 wxWindow::MSWOnActivate(state
, minimized
, activate
);
419 // If this window is an MDI parent, we must also send an OnActivate message
420 // to the current child.
421 if ((m_currentChild
!= NULL
) && ((state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
)))
423 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, m_currentChild
->GetId());
424 event
.SetEventObject( m_currentChild
);
425 m_currentChild
->GetEventHandler()->ProcessEvent(event
);
430 bool wxMDIParentFrame::MSWOnCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
432 // if (cmd == 0) // Why did I do this test?
434 // In case it's e.g. a toolbar.
435 wxWindow
*win
= wxFindWinFromHandle(control
);
437 return win
->MSWCommand(cmd
, id
);
440 if (wxCurrentPopupMenu)
442 wxMenu *popupMenu = wxCurrentPopupMenu;
443 wxCurrentPopupMenu = NULL;
444 if (!popupMenu->MSWCommand(cmd, id))
451 case IDM_WINDOWCASCADE
:
452 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDICASCADE
, MDITILE_SKIPDISABLED
, 0);
455 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDITILE
, MDITILE_HORIZONTAL
, 0);
457 case IDM_WINDOWICONS
:
458 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDIICONARRANGE
, 0, 0);
461 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDINEXT
, 0, 0);
468 return FALSE
; // Get WndProc to call default proc
471 if (m_parentFrameActive
&& (id
< wxFIRST_MDI_CHILD
|| id
> wxLAST_MDI_CHILD
))
476 else if (m_currentChild
&& (id
< wxFIRST_MDI_CHILD
|| id
> wxLAST_MDI_CHILD
))
478 return m_currentChild
->MSWOnCommand(id
, cmd
, control
);
481 if (id
>= wxFIRST_MDI_CHILD
&& id
<= wxLAST_MDI_CHILD
)
483 wxNode
* node
= GetChildren().First();
486 wxWindow
* child
= (wxWindow
*) node
->Data();
487 if (child
->GetHWND())
490 long childId
= GetWindowLong((HWND
) child
->GetHWND(), GWL_ID
);
492 long childId
= GetWindowWord((HWND
) child
->GetHWND(), GWW_ID
);
496 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDIACTIVATE
, (WPARAM
) (HWND
) child
->GetHWND(), 0);
503 wxWindow* child = FindItem(id);
506 ::SendMessage( (HWND) GetClientWindow()->GetHWND(), WM_MDIACTIVATE, (WPARAM) (HWND) child->GetHWND(), 0);
515 void wxMDIParentFrame::MSWOnMenuHighlight(WXWORD nItem
, WXWORD nFlags
, WXHMENU hSysMenu
)
517 if (m_parentFrameActive
)
519 if (nFlags
== 0xFFFF && hSysMenu
== (WXHMENU
) NULL
)
521 wxMenuEvent
event(wxEVT_MENU_HIGHLIGHT
, -1);
522 event
.SetEventObject( this );
523 GetEventHandler()->ProcessEvent(event
);
525 else if (nFlags
!= MF_SEPARATOR
)
527 wxMenuEvent
event(wxEVT_MENU_HIGHLIGHT
, nItem
);
528 event
.SetEventObject( this );
529 GetEventHandler()->ProcessEvent(event
);
532 else if (m_currentChild
)
534 m_currentChild
->MSWOnMenuHighlight(nItem
, nFlags
, hSysMenu
);
538 long wxMDIParentFrame::MSWDefWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
541 if ( GetClientWindow() )
542 clientWnd
= GetClientWindow()->GetHWND();
546 return DefFrameProc((HWND
) GetHWND(), (HWND
) clientWnd
, message
, wParam
, lParam
);
549 bool wxMDIParentFrame::MSWProcessMessage(WXMSG
* msg
)
551 if ((m_currentChild
!= (wxWindow
*)NULL
) && (m_currentChild
->GetHWND() != (WXHWND
) NULL
) && m_currentChild
->MSWProcessMessage(msg
))
557 bool wxMDIParentFrame::MSWTranslateMessage(WXMSG
* msg
)
559 MSG
*pMsg
= (MSG
*)msg
;
561 if ((m_currentChild
!= (wxWindow
*)NULL
) && (m_currentChild
->GetHWND() != (WXHWND
) NULL
) && m_currentChild
->MSWTranslateMessage(msg
))
564 if (m_acceleratorTable
.Ok() &&
565 ::TranslateAccelerator((HWND
) GetHWND(), (HACCEL
) m_acceleratorTable
.GetHACCEL(), pMsg
))
568 if (pMsg
->message
== WM_KEYDOWN
|| pMsg
->message
== WM_SYSKEYDOWN
)
570 if (::TranslateMDISysAccel((HWND
) GetClientWindow()->GetHWND(), pMsg
))
578 bool wxMDIParentFrame::MSWOnEraseBkgnd(WXHDC
WXUNUSED(pDC
))
583 extern wxWindow
*wxWndHook
;
584 extern wxList
*wxWinHandleList
;
586 wxMDIChildFrame::wxMDIChildFrame(void)
591 bool wxMDIChildFrame::Create(wxMDIParentFrame
*parent
,
593 const wxString
& title
,
597 const wxString
& name
)
599 m_defaultIcon
= (WXHICON
) (wxSTD_MDICHILDFRAME_ICON
? wxSTD_MDICHILDFRAME_ICON
: wxDEFAULT_MDICHILDFRAME_ICON
);
606 m_windowId
= (int)NewControlId();
608 if (parent
) parent
->AddChild(this);
619 mcs
.szClass
= wxMDIChildFrameClassName
;
621 mcs
.hOwner
= wxGetInstance();
622 if (x
> -1) mcs
.x
= x
;
623 else mcs
.x
= CW_USEDEFAULT
;
625 if (y
> -1) mcs
.y
= y
;
626 else mcs
.y
= CW_USEDEFAULT
;
628 if (width
> -1) mcs
.cx
= width
;
629 else mcs
.cx
= CW_USEDEFAULT
;
631 if (height
> -1) mcs
.cy
= height
;
632 else mcs
.cy
= CW_USEDEFAULT
;
634 DWORD msflags
= WS_OVERLAPPED
| WS_CLIPCHILDREN
;
635 if (style
& wxMINIMIZE_BOX
)
636 msflags
|= WS_MINIMIZEBOX
;
637 if (style
& wxMAXIMIZE_BOX
)
638 msflags
|= WS_MAXIMIZEBOX
;
639 if (style
& wxTHICK_FRAME
)
640 msflags
|= WS_THICKFRAME
;
641 if (style
& wxSYSTEM_MENU
)
642 msflags
|= WS_SYSMENU
;
643 if ((style
& wxMINIMIZE
) || (style
& wxICONIZE
))
644 msflags
|= WS_MINIMIZE
;
645 if (style
& wxMAXIMIZE
)
646 msflags
|= WS_MAXIMIZE
;
647 if (style
& wxCAPTION
)
648 msflags
|= WS_CAPTION
;
654 DWORD Return
= SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(),
655 WM_MDICREATE
, 0, (LONG
)(LPSTR
)&mcs
);
657 //handle = (HWND)LOWORD(Return);
658 // Must be the DWORRD for WIN32. And in 16 bits, HIWORD=0 (says Microsoft)
659 m_hWnd
= (WXHWND
)Return
;
661 // This gets reassigned so can't be stored
662 // m_windowId = GetWindowLong((HWND) m_hWnd, GWL_ID);
665 wxWinHandleList
->Append((long)GetHWND(), this);
667 SetWindowLong((HWND
) GetHWND(), 0, (long)this);
669 wxModelessWindows
.Append(this);
673 wxMDIChildFrame::~wxMDIChildFrame(void)
677 ResetWindowStyle(NULL
);
680 // Set the client size (i.e. leave the calculation of borders etc.
682 void wxMDIChildFrame::SetClientSize(int width
, int height
)
684 HWND hWnd
= (HWND
) GetHWND();
687 ::GetClientRect(hWnd
, &rect
);
690 GetWindowRect(hWnd
, &rect2
);
692 // Find the difference between the entire window (title bar and all)
693 // and the client area; add this to the new client size to move the
695 int actual_width
= rect2
.right
- rect2
.left
- rect
.right
+ width
;
696 int actual_height
= rect2
.bottom
- rect2
.top
- rect
.bottom
+ height
;
701 GetStatusBar()->GetSize(&sx
, &sy
);
706 point
.x
= rect2
.left
;
709 // If there's an MDI parent, must subtract the parent's top left corner
710 // since MoveWindow moves relative to the parent
711 wxMDIParentFrame
*mdiParent
= (wxMDIParentFrame
*)GetParent();
712 ::ScreenToClient((HWND
) mdiParent
->GetClientWindow()->GetHWND(), &point
);
714 MoveWindow(hWnd
, point
.x
, point
.y
, actual_width
, actual_height
, (BOOL
)TRUE
);
716 wxSizeEvent
event(wxSize(width
, height
), m_windowId
);
717 event
.SetEventObject( this );
718 GetEventHandler()->ProcessEvent(event
);
721 void wxMDIChildFrame::GetPosition(int *x
, int *y
) const
724 GetWindowRect((HWND
) GetHWND(), &rect
);
729 // Since we now have the absolute screen coords,
730 // if there's a parent we must subtract its top left corner
731 wxMDIParentFrame
*mdiParent
= (wxMDIParentFrame
*)GetParent();
732 ::ScreenToClient((HWND
) mdiParent
->GetClientWindow()->GetHWND(), &point
);
738 void wxMDIChildFrame::SetMenuBar(wxMenuBar
*menu_bar
)
742 m_frameMenuBar
= NULL
;
746 if (menu_bar
->m_menuBarFrame
)
750 HMENU menu
= CreateMenu();
752 for (i
= 0; i
< menu_bar
->m_menuCount
; i
++)
754 HMENU popup
= (HMENU
)menu_bar
->m_menus
[i
]->m_hMenu
;
756 // After looking Bounds Checker result, it seems that all
757 // menus must be individually destroyed. So, don't reset m_hMenu,
758 // to allow ~wxMenu to do the job.
760 menu_bar
->m_menus
[i
]->m_savehMenu
= (WXHMENU
) popup
;
761 // Uncommenting for the moment... JACS
762 menu_bar
->m_menus
[i
]->m_hMenu
= 0;
763 ::AppendMenu((HMENU
) menu
, MF_POPUP
| MF_STRING
, (UINT
)popup
, menu_bar
->m_titles
[i
]);
766 menu_bar
->m_hMenu
= (WXHMENU
)menu
;
768 delete m_frameMenuBar
;
770 this->m_hMenu
= (WXHMENU
) menu
;
772 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
774 parent
->m_parentFrameActive
= FALSE
;
775 HMENU subMenu
= GetSubMenu((HMENU
) parent
->GetWindowMenu(), 0);
777 // Try to insert Window menu in front of Help, otherwise append it.
778 int N
= GetMenuItemCount(menu
);
779 bool success
= FALSE
;
780 for (i
= 0; i
< N
; i
++)
783 int chars
= GetMenuString(menu
, i
, buf
, 100, MF_BYPOSITION
);
784 if ((chars
> 0) && (strcmp(buf
, "&Help") == 0 ||
785 strcmp(buf
, "Help") == 0))
788 InsertMenu(menu
, i
, MF_BYPOSITION
| MF_POPUP
| MF_STRING
,
789 (UINT
)subMenu
, "&Window");
794 AppendMenu(menu
, MF_POPUP
,
798 SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
,
802 SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
, 0,
803 MAKELPARAM(menu
, subMenu
));
806 DrawMenuBar((HWND
) parent
->GetHWND());
807 m_frameMenuBar
= menu_bar
;
808 menu_bar
->m_menuBarFrame
= this;
812 void wxMDIChildFrame::Maximize(void)
814 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
815 if ( parent
&& parent
->GetClientWindow() )
816 ::SendMessage( (HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDIMAXIMIZE
, (WPARAM
) (HWND
) GetHWND(), 0);
819 void wxMDIChildFrame::Restore(void)
821 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
822 if ( parent
&& parent
->GetClientWindow() )
823 ::SendMessage( (HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDIRESTORE
, (WPARAM
) (HWND
) GetHWND(), 0);
826 void wxMDIChildFrame::Activate(void)
828 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
829 if ( parent
&& parent
->GetClientWindow() )
830 ::SendMessage( (HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDIACTIVATE
, (WPARAM
) (HWND
) GetHWND(), 0);
833 static HWND invalidHandle
= 0;
834 void wxMDIChildFrame::MSWOnSize(int x
, int y
, WXUINT id
)
836 if (!GetHWND()) return;
838 if (invalidHandle
== (HWND
) GetHWND())
843 (void)MSWDefWindowProc(m_lastMsg
, m_lastWParam
, m_lastLParam
);
858 // forward WM_SIZE to status bar control
859 #if wxUSE_NATIVE_STATUSBAR
860 if (m_frameStatusBar
&& m_frameStatusBar
->IsKindOf(CLASSINFO(wxStatusBar95
)))
862 wxSizeEvent
event(wxSize(x
, y
), m_frameStatusBar
->GetId());
863 event
.SetEventObject( m_frameStatusBar
);
865 ((wxStatusBar95
*)m_frameStatusBar
)->OnSize(event
);
872 wxWindow::MSWOnSize(x
, y
, id
);
876 bool wxMDIChildFrame::MSWOnCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
878 // if ((cmd == 0) && GetHWND())
881 // In case it's e.g. a toolbar.
882 wxWindow
*win
= wxFindWinFromHandle(control
);
884 return win
->MSWCommand(cmd
, id
);
886 if (wxCurrentPopupMenu
)
888 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
889 wxCurrentPopupMenu
= NULL
;
890 if (popupMenu
->MSWCommand(cmd
, id
))
894 if (GetMenuBar() && GetMenuBar()->FindItemForId(id
))
907 long wxMDIChildFrame::MSWDefWindowProc(WXUINT message
, WXUINT wParam
, WXLPARAM lParam
)
910 return DefMDIChildProc((HWND
) GetHWND(), (UINT
) message
, (WPARAM
) wParam
, (LPARAM
) lParam
);
914 bool wxMDIChildFrame::MSWProcessMessage(WXMSG
*msg
)
919 bool wxMDIChildFrame::MSWTranslateMessage(WXMSG
* msg
)
921 MSG
*pMsg
= (MSG
*)msg
;
922 if (m_acceleratorTable
.Ok())
924 wxFrame
*parent
= (wxFrame
*)GetParent();
925 HWND parent_hwnd
= (HWND
) parent
->GetHWND();
926 return (::TranslateAccelerator(parent_hwnd
, (HACCEL
) m_acceleratorTable
.GetHACCEL(), pMsg
) != 0);
932 long wxMDIChildFrame::MSWOnMDIActivate(long activate
, WXHWND
WXUNUSED(one
), WXHWND
WXUNUSED(two
))
934 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
935 HMENU parent_menu
= (HMENU
) parent
->GetWinMenu();
936 HMENU child_menu
= (HMENU
) GetWinMenu();
941 parent
->m_currentChild
= this;
944 parent
->m_parentFrameActive
= FALSE
;
945 HMENU subMenu
= GetSubMenu((HMENU
) parent
->GetWindowMenu(), 0);
947 ::SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
,
951 ::SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
, 0,
952 MAKELONG(child_menu
, subMenu
));
955 ::DrawMenuBar((HWND
) parent
->GetHWND());
957 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, m_windowId
);
958 event
.SetEventObject( this );
959 GetEventHandler()->ProcessEvent(event
);
963 if (parent
->m_currentChild
== this)
964 parent
->m_currentChild
= NULL
;
966 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, m_windowId
);
967 event
.SetEventObject( this );
968 GetEventHandler()->ProcessEvent(event
);
973 parent
->m_parentFrameActive
= TRUE
;
974 HMENU subMenu
= GetSubMenu((HMENU
) parent
->GetWindowMenu(), 0);
976 ::SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
,
980 ::SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
, 0,
981 MAKELONG(parent_menu
, subMenu
));
984 ::DrawMenuBar((HWND
) parent
->GetHWND());
987 bool flag
= (activate
!= 0);
988 wxActivateEvent
event(wxEVT_ACTIVATE
, flag
, m_windowId
);
989 event
.SetEventObject( this );
990 GetEventHandler()->ProcessEvent(event
);
994 void wxMDIChildFrame::MSWDestroyWindow(void)
996 MSWDetachWindowMenu();
997 invalidHandle
= (HWND
) GetHWND();
999 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
1001 // Must make sure this handle is invalidated (set to NULL)
1002 // since all sorts of things could happen after the
1003 // child client is destroyed, but before the wxFrame is
1006 HWND oldHandle
= (HWND
)GetHWND();
1008 SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDIDESTROY
, (WPARAM
)oldHandle
, (LPARAM
)0);
1010 SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDIDESTROY
, (HWND
)oldHandle
, 0);
1016 ::DestroyMenu((HMENU
) m_hMenu
);
1022 // Change the client window's extended style so we don't
1023 // get a client edge style when a child is maximised (a double
1024 // border looks silly.)
1025 bool wxMDIChildFrame::ResetWindowStyle(void *vrect
)
1027 #if defined(__WIN95__)
1028 RECT
*rect
= (RECT
*)vrect
;
1029 wxMDIParentFrame
* pFrameWnd
= (wxMDIParentFrame
*)GetParent();
1030 wxMDIChildFrame
* pChild
= pFrameWnd
->GetActiveChild();
1031 if (!pChild
|| (pChild
== this))
1033 DWORD dwStyle
= ::GetWindowLong((HWND
) pFrameWnd
->GetClientWindow()->GetHWND(), GWL_EXSTYLE
);
1034 DWORD dwThisStyle
= ::GetWindowLong((HWND
) GetHWND(), GWL_STYLE
);
1035 DWORD dwNewStyle
= dwStyle
;
1036 if (pChild
!= NULL
&& (dwThisStyle
& WS_MAXIMIZE
))
1037 dwNewStyle
&= ~(WS_EX_CLIENTEDGE
);
1039 dwNewStyle
|= WS_EX_CLIENTEDGE
;
1041 if (dwStyle
!= dwNewStyle
)
1043 ::RedrawWindow((HWND
) pFrameWnd
->GetClientWindow()->GetHWND(), NULL
, NULL
, RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1044 ::SetWindowLong((HWND
) pFrameWnd
->GetClientWindow()->GetHWND(), GWL_EXSTYLE
, dwNewStyle
);
1045 ::SetWindowPos((HWND
) pFrameWnd
->GetClientWindow()->GetHWND(), NULL
, 0, 0, 0, 0,
1046 SWP_FRAMECHANGED
| SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOCOPYBITS
);
1048 ::GetClientRect((HWND
) pFrameWnd
->GetClientWindow()->GetHWND(), rect
);
1058 void wxMDIChildFrame::MSWOnWindowPosChanging(void *pos
)
1060 WINDOWPOS
*lpPos
= (WINDOWPOS
*)pos
;
1061 #if defined(__WIN95__)
1062 if (!(lpPos
->flags
& SWP_NOSIZE
))
1065 DWORD dwExStyle
= ::GetWindowLong((HWND
) GetHWND(), GWL_EXSTYLE
);
1066 DWORD dwStyle
= ::GetWindowLong((HWND
) GetHWND(), GWL_STYLE
);
1067 if (ResetWindowStyle((void *) & rectClient
) && (dwStyle
& WS_MAXIMIZE
))
1069 ::AdjustWindowRectEx(&rectClient
, dwStyle
, FALSE
, dwExStyle
);
1070 lpPos
->x
= rectClient
.left
;
1071 lpPos
->y
= rectClient
.top
;
1072 lpPos
->cx
= rectClient
.right
- rectClient
.left
;
1073 lpPos
->cy
= rectClient
.bottom
- rectClient
.top
;
1075 wxMDIParentFrame
* pFrameWnd
= (wxMDIParentFrame
*)GetParent();
1076 if (pFrameWnd
&& pFrameWnd
->GetToolBar())
1078 pFrameWnd
->GetToolBar()->Refresh();
1086 wxMDIClientWindow::wxMDIClientWindow(void)
1092 wxMDIClientWindow::~wxMDIClientWindow(void)
1096 bool wxMDIClientWindow::CreateClient(wxMDIParentFrame
*parent
, long style
)
1098 m_backgroundColour
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
);
1100 CLIENTCREATESTRUCT ccs
;
1101 m_windowStyle
= style
;
1102 m_windowParent
= parent
;
1104 ccs
.hWindowMenu
= (HMENU
) parent
->GetWindowMenu();
1105 ccs
.idFirstChild
= wxFIRST_MDI_CHILD
;
1107 DWORD msStyle
= WS_VISIBLE
| WS_CHILD
| WS_CLIPCHILDREN
;
1108 if ( parent
->GetWindowStyleFlag() & wxHSCROLL
)
1109 msStyle
|= WS_HSCROLL
;
1110 if ( parent
->GetWindowStyleFlag() & wxVSCROLL
)
1111 msStyle
|= WS_VSCROLL
;
1113 #if defined(__WIN95__)
1114 DWORD exStyle
= WS_EX_CLIENTEDGE
;
1120 m_hWnd
= (WXHWND
) ::CreateWindowEx(exStyle
, "mdiclient", NULL
,
1121 msStyle
, 0, 0, 0, 0, (HWND
) parent
->GetHWND(), NULL
,
1122 wxGetInstance(), (LPSTR
)(LPCLIENTCREATESTRUCT
)&ccs
);
1123 SubclassWin(m_hWnd
);
1126 return (m_hWnd
!= 0) ;
1129 // Window procedure: here for debugging purposes
1130 long wxMDIClientWindow::MSWWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1132 return wxWindow::MSWWindowProc(nMsg
, wParam
, lParam
);
1133 // return MSWDefWindowProc(nMsg, wParam, lParam);
1136 long wxMDIClientWindow::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1138 if ( MSWGetOldWndProc() != 0)
1139 return ::CallWindowProc(CASTWNDPROC
MSWGetOldWndProc(), (HWND
) GetHWND(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1141 return ::DefWindowProc((HWND
) m_hWnd
, (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1144 // Explicitly call default scroll behaviour
1145 void wxMDIClientWindow::OnScroll(wxScrollEvent
& event
)
1147 // Note: for client windows, the scroll position is not set in
1148 // WM_HSCROLL, WM_VSCROLL, so we can't easily determine what
1149 // scroll position we're at.
1150 // This makes it hard to paint patterns or bitmaps in the background,
1151 // and have the client area scrollable as well.
1153 if ( event
.GetOrientation() == wxHORIZONTAL
)
1154 m_scrollX
= event
.GetPosition(); // Always returns zero!
1156 m_scrollY
= event
.GetPosition(); // Always returns zero!
1161 // Should hand the message to the default proc
1162 long wxMDIClientWindow::MSWOnMDIActivate(long bActivate
, WXHWND
, WXHWND
)