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
;
145 if (style
& wxCLIP_CHILDREN
)
146 msflags
|= WS_CLIPCHILDREN
;
148 wxWindow::MSWCreate(m_windowId
, parent
, wxMDIFrameClassName
, this, title
, x
, y
, width
, height
,
151 wxModelessWindows
.Append(this);
156 wxMDIParentFrame::~wxMDIParentFrame(void)
160 DestroyMenu((HMENU
) m_windowMenu
); // Destroy dummy "Window" menu
163 if (m_clientWindow
->MSWGetOldWndProc())
164 m_clientWindow
->UnsubclassWin();
166 m_clientWindow
->m_hWnd
= 0;
167 delete m_clientWindow
;
170 // Get size *available for subwindows* i.e. excluding menu bar.
171 void wxMDIParentFrame::GetClientSize(int *x
, int *y
) const
174 GetClientRect((HWND
) GetHWND(), &rect
);
176 int cwidth
= rect
.right
;
177 int cheight
= rect
.bottom
;
182 m_frameToolBar->GetSize(&tw, &th);
186 if ( GetStatusBar() )
189 GetStatusBar()->GetSize(&sw
, &sh
);
197 void wxMDIParentFrame::SetMenuBar(wxMenuBar
*menu_bar
)
201 m_frameMenuBar
= NULL
;
205 if (menu_bar
->m_menuBarFrame
)
209 HMENU menu
= CreateMenu();
211 for (i
= 0; i
< menu_bar
->m_menuCount
; i
++)
213 HMENU popup
= (HMENU
)menu_bar
->m_menus
[i
]->m_hMenu
;
215 // After looking Bounds Checker result, it seems that all
216 // menus must be individually destroyed. So, don't reset m_hMenu,
217 // to allow ~wxMenu to do the job.
219 menu_bar
->m_menus
[i
]->m_savehMenu
= (WXHMENU
) popup
;
220 // Uncommenting for the moment... JACS
221 menu_bar
->m_menus
[i
]->m_hMenu
= (WXHMENU
) NULL
;
222 AppendMenu(menu
, MF_POPUP
| MF_STRING
, (UINT
)popup
, menu_bar
->m_titles
[i
]);
225 menu_bar
->m_hMenu
= (WXHMENU
)menu
;
227 delete m_frameMenuBar
;
229 this->m_hMenu
= (WXHMENU
) menu
;
231 // MDI parent-specific code follows
233 HMENU subMenu
= GetSubMenu((HMENU
) m_windowMenu
, 0);
235 // Try to insert Window menu in front of Help, otherwise append it.
236 int N
= GetMenuItemCount(menu
);
237 bool success
= FALSE
;
238 for (i
= 0; i
< N
; i
++)
241 int chars
= GetMenuString(menu
, i
, buf
, 100, MF_BYPOSITION
);
242 if ((chars
> 0) && (strcmp(buf
, "&Help") == 0 ||
243 strcmp(buf
, "Help") == 0))
246 InsertMenu(menu
, i
, MF_BYPOSITION
| MF_POPUP
| MF_STRING
,
247 (UINT
)subMenu
, "&Window");
252 AppendMenu(menu
, MF_POPUP
,
255 m_parentFrameActive
= TRUE
;
257 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDISETMENU
,
261 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDISETMENU
, 0,
262 MAKELPARAM(menu
, subMenu
));
264 DrawMenuBar((HWND
) GetHWND());
266 m_frameMenuBar
= menu_bar
;
267 menu_bar
->m_menuBarFrame
= this;
270 void wxMDIParentFrame::OnSize(wxSizeEvent
& event
)
279 GetClientSize(&width
, &height
);
283 GetToolBar()->GetSize(&wt
, &ht
);
286 GetToolBar()->SetSize(0, 0, width
, ht
);
289 if ( GetClientWindow() )
290 GetClientWindow()->SetSize(x
, y
, width
, height
);
292 // forward WM_SIZE to status bar control
293 #if USE_NATIVE_STATUSBAR
294 if (m_frameStatusBar
&& m_frameStatusBar
->IsKindOf(CLASSINFO(wxStatusBar95
)))
295 ((wxStatusBar95
*)m_frameStatusBar
)->OnSize(event
);
299 void wxMDIParentFrame::OnActivate(wxActivateEvent
& event
)
304 #if WXWIN_COMPATIBILITY
305 void wxMDIParentFrame::OldOnSize(int x
, int y
)
307 #if WXWIN_COMPATIBILITY == 1
308 wxSizeEvent
event(wxSize(x
, y
), m_windowId
);
309 event
.SetEventObject( this );
310 GetEventHandler()->ProcessEvent(event
);
320 GetClientSize(&width
, &height
);
324 GetToolBar()->GetSize(&wt
, &ht
);
329 if ( GetClientWindow() )
330 GetClientWindow()->SetSize(x
, y
, width
, height
);
335 // Default activation behaviour - nothing.
336 // Default activation behaviour - override dedault wxFrame behaviour
337 void wxMDIParentFrame::OldOnActivate(bool flag
)
339 #if WXWIN_COMPATIBILITY == 1
340 wxActivateEvent
event(wxEVT_ACTIVATE
, flag
, m_windowId
);
341 event
.SetEventObject( this );
342 GetEventHandler()->ProcessEvent(event
);
349 // Returns the active MDI child window
350 wxMDIChildFrame
*wxMDIParentFrame::GetActiveChild(void) const
352 // HWND hWnd = (HWND)LOWORD(SendMessage((HWND) GetClientWindow()->GetHWND(), WM_MDIGETACTIVE, 0, 0L));
353 HWND hWnd
= (HWND
)SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDIGETACTIVE
, 0, 0L);
357 return (wxMDIChildFrame
*)wxFindWinFromHandle((WXHWND
) hWnd
);
360 // Create the client window class (don't Create the window,
361 // just return a new class)
362 wxMDIClientWindow
*wxMDIParentFrame::OnCreateClient(void)
364 return new wxMDIClientWindow
;
367 // Responds to colour changes, and passes event on to children.
368 void wxMDIParentFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
)
370 if ( m_clientWindow
)
372 m_clientWindow
->SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
));
373 m_clientWindow
->Refresh();
376 if ( m_frameToolBar )
378 wxSysColourChangedEvent event2;
379 event2.eventObject = m_frameToolBar;
380 m_frameToolBar->GetEventHandler()->ProcessEvent(event2);
384 // Propagate the event to the non-top-level children
385 wxFrame::OnSysColourChanged(event
);
389 void wxMDIParentFrame::Cascade(void)
391 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDICASCADE
, 0, 0);
394 void wxMDIParentFrame::Tile(void)
396 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDITILE
, MDITILE_HORIZONTAL
, 0);
399 void wxMDIParentFrame::ArrangeIcons(void)
401 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDIICONARRANGE
, 0, 0);
404 void wxMDIParentFrame::ActivateNext(void)
406 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDINEXT
, 0, 0);
409 void wxMDIParentFrame::ActivatePrevious(void)
411 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDINEXT
, 0, 1);
416 // Returns a style for the client window - usually 0
417 // or, for example, wxHSCROLL | wxVSCROLL
418 long wxMDIParentFrame::GetClientStyle(void) const
420 return wxHSCROLL | wxVSCROLL ;
424 bool wxMDIParentFrame::MSWOnDestroy(void)
429 void wxMDIParentFrame::MSWOnCreate(WXLPCREATESTRUCT
WXUNUSED(cs
))
431 m_clientWindow
= new wxMDIClientWindow
;
432 // Uses own style for client style
433 m_clientWindow
->CreateClient(this, GetWindowStyleFlag());
436 void wxMDIParentFrame::MSWOnSize(const int x
, const int y
, const WXUINT id
)
451 // forward WM_SIZE to status bar control
452 #if USE_NATIVE_STATUSBAR
453 if (m_frameStatusBar
&& m_frameStatusBar
->IsKindOf(CLASSINFO(wxStatusBar95
)))
455 wxSizeEvent
event(wxSize(x
, y
), m_frameStatusBar
->GetId());
456 event
.SetEventObject( m_frameStatusBar
);
458 ((wxStatusBar95
*)m_frameStatusBar
)->OnSize(event
);
464 GetEventHandler()->OldOnSize(x
, y
);
468 bool wxMDIParentFrame::MSWOnActivate(const int state
, const bool minimized
, const WXHWND activate
)
470 wxWindow::MSWOnActivate(state
, minimized
, activate
);
472 // If this window is an MDI parent, we must also send an OnActivate message
473 // to the current child.
474 if ((m_currentChild
!= NULL
) && ((state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
)))
476 #if WXWIN_COMPATIBILITY
477 m_currentChild
->GetEventHandler()->OldOnActivate(TRUE
);
479 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
,
480 m_currentChild
.m_windowId
);
481 event
.eventObject
= m_currentChild
;
482 m_currentChild
->GetEventHandler()->ProcessEvent(event
);
488 bool wxMDIParentFrame::MSWOnCommand(const WXWORD id
, const WXWORD cmd
, const WXHWND control
)
492 // In case it's e.g. a toolbar.
493 wxWindow
*win
= wxFindWinFromHandle(control
);
495 return win
->MSWCommand(cmd
, id
);
499 case IDM_WINDOWCASCADE
:
500 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDICASCADE
, MDITILE_SKIPDISABLED
, 0);
503 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDITILE
, MDITILE_HORIZONTAL
, 0);
505 case IDM_WINDOWICONS
:
506 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDIICONARRANGE
, 0, 0);
509 SendMessage((HWND
) GetClientWindow()->GetHWND(), WM_MDINEXT
, 0, 0);
517 wxDebugMsg("wxMDIFrame::OnCommand %d: system command: calling default window proc\n", GetHWND());
519 return FALSE
; // Get WndProc to call default proc
522 if (m_parentFrameActive
&& (id
< wxFIRST_MDI_CHILD
|| id
> wxLAST_MDI_CHILD
))
527 else if (m_currentChild
&& (id
< wxFIRST_MDI_CHILD
|| id
> wxLAST_MDI_CHILD
))
530 wxDebugMsg("wxMDIFrame::MSWOnCommand %d: calling child OnCommand\n", GetHWND());
532 return m_currentChild
->MSWOnCommand(id
, cmd
, control
);
535 if (id
>= wxFIRST_MDI_CHILD
&& id
<= wxLAST_MDI_CHILD
)
537 wxNode
* node
= GetChildren()->First();
540 wxWindow
* child
= (wxWindow
*) node
->Data();
541 if (child
->GetHWND())
544 long childId
= GetWindowLong((HWND
) child
->GetHWND(), GWL_ID
);
546 long childId
= GetWindowWord((HWND
) child
->GetHWND(), GWW_ID
);
550 ::SendMessage( (HWND
) GetClientWindow()->GetHWND(), WM_MDIACTIVATE
, (WPARAM
) (HWND
) child
->GetHWND(), 0);
557 wxWindow* child = FindItem(id);
560 ::SendMessage( (HWND) GetClientWindow()->GetHWND(), WM_MDIACTIVATE, (WPARAM) (HWND) child->GetHWND(), 0);
569 void wxMDIParentFrame::MSWOnMenuHighlight(const WXWORD nItem
, const WXWORD nFlags
, const WXHMENU hSysMenu
)
571 if (m_parentFrameActive
)
574 if (nFlags
== 0xFFFF && hSysMenu
== (WXHMENU
) NULL
)
575 GetEventHandler()->OldOnMenuSelect(-1);
576 else if (nFlags
!= MF_SEPARATOR
)
577 GetEventHandler()->OldOnMenuSelect(nItem
);
579 else if (m_currentChild
)
581 m_currentChild
->MSWOnMenuHighlight(nItem
, nFlags
, hSysMenu
);
585 long wxMDIParentFrame::MSWDefWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
588 if ( GetClientWindow() )
589 clientWnd
= GetClientWindow()->GetHWND();
593 return DefFrameProc((HWND
) GetHWND(), (HWND
) clientWnd
, message
, wParam
, lParam
);
596 bool wxMDIParentFrame::MSWProcessMessage(WXMSG
* msg
)
598 MSG
*pMsg
= (MSG
*)msg
;
600 if ((m_currentChild
!= (wxWindow
*)NULL
) && (m_currentChild
->GetHWND() != (WXHWND
) NULL
) && m_currentChild
->MSWProcessMessage(msg
))
603 if (m_acceleratorTable
!= (WXHANDLE
) NULL
&&
604 ::TranslateAccelerator((HWND
) GetHWND(), (HANDLE
) m_acceleratorTable
, pMsg
))
607 if (pMsg
->message
== WM_KEYDOWN
|| pMsg
->message
== WM_SYSKEYDOWN
)
609 if (::TranslateMDISysAccel((HWND
) GetClientWindow()->GetHWND(), pMsg
))
616 bool wxMDIParentFrame::MSWOnEraseBkgnd(const WXHDC
WXUNUSED(pDC
))
621 extern wxWindow
*wxWndHook
;
622 extern wxList
*wxWinHandleList
;
624 wxMDIChildFrame::wxMDIChildFrame(void)
629 bool wxMDIChildFrame::Create(wxMDIParentFrame
*parent
,
631 const wxString
& title
,
635 const wxString
& name
)
637 m_defaultIcon
= (WXHICON
) (wxSTD_MDICHILDFRAME_ICON
? wxSTD_MDICHILDFRAME_ICON
: wxDEFAULT_MDICHILDFRAME_ICON
);
644 m_windowId
= (int)NewControlId();
646 if (parent
) parent
->AddChild(this);
657 mcs
.szClass
= wxMDIChildFrameClassName
;
659 mcs
.hOwner
= wxGetInstance();
660 if (x
> -1) mcs
.x
= x
;
661 else mcs
.x
= CW_USEDEFAULT
;
663 if (y
> -1) mcs
.y
= y
;
664 else mcs
.y
= CW_USEDEFAULT
;
666 if (width
> -1) mcs
.cx
= width
;
667 else mcs
.cx
= CW_USEDEFAULT
;
669 if (height
> -1) mcs
.cy
= height
;
670 else mcs
.cy
= CW_USEDEFAULT
;
672 DWORD msflags
= WS_OVERLAPPED
| WS_CLIPCHILDREN
;
673 if (style
& wxMINIMIZE_BOX
)
674 msflags
|= WS_MINIMIZEBOX
;
675 if (style
& wxMAXIMIZE_BOX
)
676 msflags
|= WS_MAXIMIZEBOX
;
677 if (style
& wxTHICK_FRAME
)
678 msflags
|= WS_THICKFRAME
;
679 if (style
& wxSYSTEM_MENU
)
680 msflags
|= WS_SYSMENU
;
681 if ((style
& wxMINIMIZE
) || (style
& wxICONIZE
))
682 msflags
|= WS_MINIMIZE
;
683 if (style
& wxMAXIMIZE
)
684 msflags
|= WS_MAXIMIZE
;
685 if (style
& wxCAPTION
)
686 msflags
|= WS_CAPTION
;
692 DWORD Return
= SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(),
693 WM_MDICREATE
, 0, (LONG
)(LPSTR
)&mcs
);
695 //handle = (HWND)LOWORD(Return);
696 // Must be the DWORRD for WIN32. And in 16 bits, HIWORD=0 (says Microsoft)
697 m_hWnd
= (WXHWND
)Return
;
699 // This gets reassigned so can't be stored
700 // m_windowId = GetWindowLong((HWND) m_hWnd, GWL_ID);
703 wxWinHandleList
->Append((long)GetHWND(), this);
705 SetWindowLong((HWND
) GetHWND(), 0, (long)this);
707 wxModelessWindows
.Append(this);
711 wxMDIChildFrame::~wxMDIChildFrame(void)
715 ResetWindowStyle(NULL
);
718 // Set the client size (i.e. leave the calculation of borders etc.
720 void wxMDIChildFrame::SetClientSize(const int width
, const int height
)
722 HWND hWnd
= (HWND
) GetHWND();
725 GetClientRect(hWnd
, &rect
);
728 GetWindowRect(hWnd
, &rect2
);
730 // Find the difference between the entire window (title bar and all)
731 // and the client area; add this to the new client size to move the
733 int actual_width
= rect2
.right
- rect2
.left
- rect
.right
+ width
;
734 int actual_height
= rect2
.bottom
- rect2
.top
- rect
.bottom
+ height
;
739 GetStatusBar()->GetSize(&sx
, &sy
);
744 point
.x
= rect2
.left
;
747 // If there's an MDI parent, must subtract the parent's top left corner
748 // since MoveWindow moves relative to the parent
749 wxMDIParentFrame
*mdiParent
= (wxMDIParentFrame
*)GetParent();
750 ::ScreenToClient((HWND
) mdiParent
->GetClientWindow()->GetHWND(), &point
);
752 MoveWindow(hWnd
, point
.x
, point
.y
, actual_width
, actual_height
, (BOOL
)TRUE
);
753 #if WXWIN_COMPATIBILITY
754 GetEventHandler()->OldOnSize(width
, height
);
756 wxSizeEvent
event(wxSize(width
, height
), m_windowId
);
757 event
.eventObject
= this;
758 GetEventHandler()->ProcessEvent(event
);
762 void wxMDIChildFrame::GetPosition(int *x
, int *y
) const
765 GetWindowRect((HWND
) GetHWND(), &rect
);
770 // Since we now have the absolute screen coords,
771 // if there's a parent we must subtract its top left corner
772 wxMDIParentFrame
*mdiParent
= (wxMDIParentFrame
*)GetParent();
773 ::ScreenToClient((HWND
) mdiParent
->GetClientWindow()->GetHWND(), &point
);
779 void wxMDIChildFrame::SetMenuBar(wxMenuBar
*menu_bar
)
783 m_frameMenuBar
= NULL
;
787 if (menu_bar
->m_menuBarFrame
)
791 HMENU menu
= CreateMenu();
793 for (i
= 0; i
< menu_bar
->m_menuCount
; i
++)
795 HMENU popup
= (HMENU
)menu_bar
->m_menus
[i
]->m_hMenu
;
797 // After looking Bounds Checker result, it seems that all
798 // menus must be individually destroyed. So, don't reset m_hMenu,
799 // to allow ~wxMenu to do the job.
801 menu_bar
->m_menus
[i
]->m_savehMenu
= (WXHMENU
) popup
;
802 // Uncommenting for the moment... JACS
803 menu_bar
->m_menus
[i
]->m_hMenu
= 0;
804 ::AppendMenu((HMENU
) menu
, MF_POPUP
| MF_STRING
, (UINT
)popup
, menu_bar
->m_titles
[i
]);
807 menu_bar
->m_hMenu
= (WXHMENU
)menu
;
809 delete m_frameMenuBar
;
811 this->m_hMenu
= (WXHMENU
) menu
;
813 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
815 parent
->m_parentFrameActive
= FALSE
;
816 HMENU subMenu
= GetSubMenu((HWND
) parent
->GetWindowMenu(), 0);
818 // Try to insert Window menu in front of Help, otherwise append it.
819 int N
= GetMenuItemCount(menu
);
820 bool success
= FALSE
;
821 for (i
= 0; i
< N
; i
++)
824 int chars
= GetMenuString(menu
, i
, buf
, 100, MF_BYPOSITION
);
825 if ((chars
> 0) && (strcmp(buf
, "&Help") == 0 ||
826 strcmp(buf
, "Help") == 0))
829 InsertMenu(menu
, i
, MF_BYPOSITION
| MF_POPUP
| MF_STRING
,
830 (UINT
)subMenu
, "&Window");
835 AppendMenu(menu
, MF_POPUP
,
839 SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
,
843 SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
, 0,
844 MAKELPARAM(menu
, subMenu
));
847 DrawMenuBar((HWND
) parent
->GetHWND());
848 m_frameMenuBar
= menu_bar
;
849 menu_bar
->m_menuBarFrame
= this;
853 void wxMDIChildFrame::Maximize(void)
855 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
856 if ( parent
&& parent
->GetClientWindow() )
857 ::SendMessage( (HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDIMAXIMIZE
, (WPARAM
) (HWND
) GetHWND(), 0);
860 void wxMDIChildFrame::Restore(void)
862 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
863 if ( parent
&& parent
->GetClientWindow() )
864 ::SendMessage( (HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDIRESTORE
, (WPARAM
) (HWND
) GetHWND(), 0);
867 void wxMDIChildFrame::Activate(void)
869 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
870 if ( parent
&& parent
->GetClientWindow() )
871 ::SendMessage( (HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDIACTIVATE
, (WPARAM
) (HWND
) GetHWND(), 0);
874 static HWND invalidHandle
= 0;
875 void wxMDIChildFrame::MSWOnSize(const int x
, const int y
, const WXUINT id
)
877 if (!GetHWND()) return;
879 if (invalidHandle
== (HWND
) GetHWND())
882 wxDebugMsg("wxMDIChildFrame::OnSize %d: invalid, so returning.\n", GetHWND());
887 (void)MSWDefWindowProc(m_lastMsg
, m_lastWParam
, m_lastLParam
);
902 // forward WM_SIZE to status bar control
903 #if USE_NATIVE_STATUSBAR
904 if (m_frameStatusBar
&& m_frameStatusBar
->IsKindOf(CLASSINFO(wxStatusBar95
)))
906 wxSizeEvent
event(wxSize(x
, y
), m_frameStatusBar
->GetId());
907 event
.SetEventObject( m_frameStatusBar
);
909 ((wxStatusBar95
*)m_frameStatusBar
)->OnSize(event
);
915 wxWindow::MSWOnSize(x
, y
, id
);
919 bool wxMDIChildFrame::MSWOnCommand(const WXWORD id
, const WXWORD cmd
, const WXHWND control
)
922 wxDebugMsg("wxMDIChildFrame::MSWOnCommand %d\n", GetHWND());
924 if ((cmd
== 0) && GetHWND())
926 // In case it's e.g. a toolbar.
927 wxWindow
*win
= wxFindWinFromHandle(control
);
929 return win
->MSWCommand(cmd
, id
);
931 if (GetMenuBar() && GetMenuBar()->FindItemForId(id
))
944 long wxMDIChildFrame::MSWDefWindowProc(WXUINT message
, WXUINT wParam
, WXLPARAM lParam
)
947 return DefMDIChildProc((HWND
) GetHWND(), (UINT
) message
, (WPARAM
) wParam
, (LPARAM
) lParam
);
951 bool wxMDIChildFrame::MSWProcessMessage(WXMSG
*msg
)
953 MSG
*pMsg
= (MSG
*)msg
;
954 if (m_acceleratorTable
&& GetHWND())
956 wxFrame
*parent
= (wxFrame
*)GetParent();
957 HWND parent_hwnd
= (HWND
) parent
->GetHWND();
958 return (::TranslateAccelerator(parent_hwnd
, (HANDLE
) m_acceleratorTable
, pMsg
) != 0);
963 long wxMDIChildFrame::MSWOnMDIActivate(const long activate
, const WXHWND
WXUNUSED(one
), const WXHWND
WXUNUSED(two
))
965 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
966 HMENU parent_menu
= (HMENU
) parent
->GetWinMenu();
968 wxDebugMsg("Parent menu is %d\n", parent_menu
);
970 HMENU child_menu
= (HMENU
) GetWinMenu();
972 wxDebugMsg("Child menu is %d\n", child_menu
);
978 parent
->m_currentChild
= this;
981 parent
->m_parentFrameActive
= FALSE
;
982 HMENU subMenu
= GetSubMenu((HMENU
) parent
->GetWindowMenu(), 0);
984 wxDebugMsg("Window submenu is %d\n", subMenu
);
986 // HMENU subMenu = 0;
988 ::SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
,
992 ::SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
, 0,
993 MAKELONG(child_menu
, subMenu
));
996 ::DrawMenuBar((HWND
) parent
->GetHWND());
998 GetEventHandler()->OldOnActivate(TRUE
);
1002 if (parent
->m_currentChild
== this)
1003 parent
->m_currentChild
= NULL
;
1004 GetEventHandler()->OldOnActivate(FALSE
);
1006 // m_active = FALSE;
1009 parent
->m_parentFrameActive
= TRUE
;
1010 HMENU subMenu
= GetSubMenu((HMENU
) parent
->GetWindowMenu(), 0);
1012 wxDebugMsg("Window submenu is %d\n", subMenu
);
1014 // HMENU subMenu = 0;
1016 ::SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
,
1017 (WPARAM
)parent_menu
,
1020 ::SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDISETMENU
, 0,
1021 MAKELONG(parent_menu
, subMenu
));
1024 ::DrawMenuBar((HWND
) parent
->GetHWND());
1028 bool flag
= (activate
!= 0);
1029 GetEventHandler()->OldOnActivate(flag
);
1031 wxDebugMsg("Finished (de)activating\n");
1036 void wxMDIChildFrame::MSWDestroyWindow(void)
1038 MSWDetachWindowMenu();
1039 invalidHandle
= (HWND
) GetHWND();
1041 wxMDIParentFrame
*parent
= (wxMDIParentFrame
*)GetParent();
1043 // Must make sure this handle is invalidated (set to NULL)
1044 // since all sorts of things could happen after the
1045 // child client is destroyed, but before the wxFrame is
1048 HWND oldHandle
= (HWND
)GetHWND();
1050 wxDebugMsg("*** About to DestroyWindow MDI child %d\n", oldHandle
);
1053 SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDIDESTROY
, (WPARAM
)oldHandle
, (LPARAM
)0);
1055 SendMessage((HWND
) parent
->GetClientWindow()->GetHWND(), WM_MDIDESTROY
, (HWND
)oldHandle
, 0);
1058 wxDebugMsg("*** Finished DestroyWindow MDI child %d\n", oldHandle
);
1064 ::DestroyMenu((HMENU
) m_hMenu
);
1070 // Change the client window's extended style so we don't
1071 // get a client edge style when a child is maximised (a double
1072 // border looks silly.)
1073 bool wxMDIChildFrame::ResetWindowStyle(void *vrect
)
1075 #if defined(__WIN95__)
1076 RECT
*rect
= (RECT
*)vrect
;
1077 wxMDIParentFrame
* pFrameWnd
= (wxMDIParentFrame
*)GetParent();
1078 wxMDIChildFrame
* pChild
= pFrameWnd
->GetActiveChild();
1079 if (!pChild
|| (pChild
== this))
1081 DWORD dwStyle
= ::GetWindowLong((HWND
) pFrameWnd
->GetClientWindow()->GetHWND(), GWL_EXSTYLE
);
1082 DWORD dwThisStyle
= ::GetWindowLong((HWND
) GetHWND(), GWL_STYLE
);
1083 DWORD dwNewStyle
= dwStyle
;
1084 if (pChild
!= NULL
&& (dwThisStyle
& WS_MAXIMIZE
))
1085 dwNewStyle
&= ~(WS_EX_CLIENTEDGE
);
1087 dwNewStyle
|= WS_EX_CLIENTEDGE
;
1089 if (dwStyle
!= dwNewStyle
)
1091 ::RedrawWindow((HWND
) pFrameWnd
->GetClientWindow()->GetHWND(), NULL
, NULL
, RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1092 ::SetWindowLong((HWND
) pFrameWnd
->GetClientWindow()->GetHWND(), GWL_EXSTYLE
, dwNewStyle
);
1093 ::SetWindowPos((HWND
) pFrameWnd
->GetClientWindow()->GetHWND(), NULL
, 0, 0, 0, 0,
1094 SWP_FRAMECHANGED
| SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOCOPYBITS
);
1096 ::GetClientRect((HWND
) pFrameWnd
->GetClientWindow()->GetHWND(), rect
);
1106 void wxMDIChildFrame::MSWOnWindowPosChanging(void *pos
)
1108 WINDOWPOS
*lpPos
= (WINDOWPOS
*)pos
;
1109 #if defined(__WIN95__)
1110 if (!(lpPos
->flags
& SWP_NOSIZE
))
1113 DWORD dwExStyle
= ::GetWindowLong((HWND
) GetHWND(), GWL_EXSTYLE
);
1114 DWORD dwStyle
= ::GetWindowLong((HWND
) GetHWND(), GWL_STYLE
);
1115 if (ResetWindowStyle((void *) & rectClient
) && (dwStyle
& WS_MAXIMIZE
))
1117 ::AdjustWindowRectEx(&rectClient
, dwStyle
, FALSE
, dwExStyle
);
1118 lpPos
->x
= rectClient
.left
;
1119 lpPos
->y
= rectClient
.top
;
1120 lpPos
->cx
= rectClient
.right
- rectClient
.left
;
1121 lpPos
->cy
= rectClient
.bottom
- rectClient
.top
;
1123 wxMDIParentFrame
* pFrameWnd
= (wxMDIParentFrame
*)GetParent();
1124 if (pFrameWnd
&& pFrameWnd
->GetToolBar())
1126 pFrameWnd
->GetToolBar()->Refresh();
1134 wxMDIClientWindow::wxMDIClientWindow(void)
1140 wxMDIClientWindow::~wxMDIClientWindow(void)
1144 bool wxMDIClientWindow::CreateClient(wxMDIParentFrame
*parent
, const long style
)
1146 m_backgroundColour
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
);
1148 CLIENTCREATESTRUCT ccs
;
1149 m_windowStyle
= style
;
1150 m_windowParent
= parent
;
1152 ccs
.hWindowMenu
= (HMENU
) parent
->GetWindowMenu();
1153 ccs
.idFirstChild
= wxFIRST_MDI_CHILD
;
1155 DWORD msStyle
= WS_VISIBLE
| WS_CHILD
| WS_CLIPCHILDREN
;
1156 if ( parent
->GetWindowStyleFlag() & wxHSCROLL
)
1157 msStyle
|= WS_HSCROLL
;
1158 if ( parent
->GetWindowStyleFlag() & wxVSCROLL
)
1159 msStyle
|= WS_VSCROLL
;
1161 #if defined(__WIN95__)
1162 DWORD exStyle
= WS_EX_CLIENTEDGE
;
1168 m_hWnd
= (WXHWND
) ::CreateWindowEx(exStyle
, "mdiclient", NULL
,
1169 msStyle
, 0, 0, 0, 0, (HWND
) parent
->GetHWND(), NULL
,
1170 wxGetInstance(), (LPSTR
)(LPCLIENTCREATESTRUCT
)&ccs
);
1171 SubclassWin(m_hWnd
);
1174 return (m_hWnd
!= 0) ;
1177 // Window procedure: here for debugging purposes
1178 long wxMDIClientWindow::MSWWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1180 return wxWindow::MSWWindowProc(nMsg
, wParam
, lParam
);
1181 // return MSWDefWindowProc(nMsg, wParam, lParam);
1184 long wxMDIClientWindow::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1186 if ( MSWGetOldWndProc() != 0)
1187 return ::CallWindowProc(CASTWNDPROC (FARPROC
) MSWGetOldWndProc(), (HWND
) GetHWND(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1189 return ::DefWindowProc((HWND
) m_hWnd
, (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1192 // Explicitly call default scroll behaviour
1193 void wxMDIClientWindow::OnScroll(wxScrollEvent
& event
)
1195 // Note: for client windows, the scroll position is not set in
1196 // WM_HSCROLL, WM_VSCROLL, so we can't easily determine what
1197 // scroll position we're at.
1198 // This makes it hard to paint patterns or bitmaps in the background,
1199 // and have the client area scrollable as well.
1201 if ( event
.GetOrientation() == wxHORIZONTAL
)
1202 m_scrollX
= event
.GetPosition(); // Always returns zero!
1204 m_scrollY
= event
.GetPosition(); // Always returns zero!
1209 // Should hand the message to the default proc
1210 long wxMDIClientWindow::MSWOnMDIActivate(const long bActivate
, const WXHWND
, const WXHWND
)