/////////////////////////////////////////////////////////////////////////////
-// Name: mdi.cpp
-// Purpose: MDI classes
+// Name: src/msw/mdi.cpp
+// Purpose: MDI classes for wxMSW
// Author: Julian Smart
// Modified by:
// Created: 04/01/98
#include "wx/log.h"
#endif
+#if wxUSE_MDI_ARCHITECTURE && !defined(__WXUNIVERSAL__)
+
#include "wx/mdi.h"
#include "wx/msw/private.h"
extern const wxChar *wxMDIChildFrameClassName;
extern const wxChar *wxMDIChildFrameClassNameNoRedraw;
-extern wxWindow *wxWndHook; // from window.cpp
-
extern void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win);
extern void wxRemoveHandleAssociation(wxWindow *win);
static const int IDM_WINDOWICONS = 4003;
static const int IDM_WINDOWNEXT = 4004;
static const int IDM_WINDOWTILEVERT = 4005;
+static const int IDM_WINDOWPREV = 4006;
// This range gives a maximum of 500 MDI children. Should be enough :-)
static const int wxFIRST_MDI_CHILD = 4100;
return (id >= wxFIRST_MDI_CHILD) && (id <= wxLAST_MDI_CHILD);
}
+// unpack the parameters of WM_MDIACTIVATE message
static void UnpackMDIActivate(WXWPARAM wParam, WXLPARAM lParam,
WXWORD *activate, WXHWND *hwndAct, WXHWND *hwndDeact);
+// return the HMENU of the MDI menu
+static inline HMENU GetMDIWindowMenu(wxMDIParentFrame *frame)
+{
+ wxMenu *menu = frame->GetWindowMenu();
+ return menu ? GetHmenuOf(menu) : 0;
+}
+
// ===========================================================================
// implementation
// ===========================================================================
long style,
const wxString& name)
{
- m_defaultIcon = (WXHICON) (wxSTD_MDIPARENTFRAME_ICON
- ? wxSTD_MDIPARENTFRAME_ICON
- : wxDEFAULT_MDIPARENTFRAME_ICON);
-
m_clientWindow = NULL;
m_currentChild = NULL;
{
m_windowMenu = new wxMenu;
- m_windowMenu->Append(IDM_WINDOWCASCADE, wxT("&Cascade"));
- m_windowMenu->Append(IDM_WINDOWTILEHOR, wxT("Tile &Horizontally"));
- m_windowMenu->Append(IDM_WINDOWTILEVERT, wxT("Tile &Vertically"));
+ m_windowMenu->Append(IDM_WINDOWCASCADE, _("&Cascade"));
+ m_windowMenu->Append(IDM_WINDOWTILEHOR, _("Tile &Horizontally"));
+ m_windowMenu->Append(IDM_WINDOWTILEVERT, _("Tile &Vertically"));
m_windowMenu->AppendSeparator();
- m_windowMenu->Append(IDM_WINDOWICONS, wxT("&Arrange Icons"));
- m_windowMenu->Append(IDM_WINDOWNEXT, wxT("&Next"));
+ m_windowMenu->Append(IDM_WINDOWICONS, _("&Arrange Icons"));
+ m_windowMenu->Append(IDM_WINDOWNEXT, _("&Next"));
+ m_windowMenu->Append(IDM_WINDOWPREV, _("&Previous"));
}
m_parentFrameActive = TRUE;
SetName(name);
m_windowStyle = style;
- if (parent) parent->AddChild(this);
+ if ( parent )
+ parent->AddChild(this);
if ( id > -1 )
m_windowId = id;
else
- m_windowId = (int)NewControlId();
-
- int x = pos.x;
- int y = pos.y;
- int width = size.x;
- int height = size.y;
-
- DWORD msflags = WS_OVERLAPPED;
- if (style & wxMINIMIZE_BOX)
- msflags |= WS_MINIMIZEBOX;
- if (style & wxMAXIMIZE_BOX)
- msflags |= WS_MAXIMIZEBOX;
- if (style & wxTHICK_FRAME)
- msflags |= WS_THICKFRAME;
- if (style & wxSYSTEM_MENU)
- msflags |= WS_SYSMENU;
- if ((style & wxMINIMIZE) || (style & wxICONIZE))
- msflags |= WS_MINIMIZE;
- if (style & wxMAXIMIZE)
- msflags |= WS_MAXIMIZE;
- if (style & wxCAPTION)
- msflags |= WS_CAPTION;
+ m_windowId = NewControlId();
- if (style & wxCLIP_CHILDREN)
- msflags |= WS_CLIPCHILDREN;
+ WXDWORD exflags;
+ WXDWORD msflags = MSWGetCreateWindowFlags(&exflags);
- if ( !wxWindow::MSWCreate(m_windowId,
- parent,
- wxMDIFrameClassName,
- this,
+ if ( !wxWindow::MSWCreate(wxMDIFrameClassName,
title,
- x, y, width, height,
- msflags) )
+ pos, size,
+ msflags,
+ exflags) )
{
return FALSE;
}
wxMDIParentFrame::~wxMDIParentFrame()
{
DestroyChildren();
+
// already delete by DestroyChildren()
m_frameToolBar = NULL;
m_frameStatusBar = NULL;
- // ::DestroyMenu((HMENU)m_windowMenu);
if (m_windowMenu)
{
delete m_windowMenu;
m_windowMenu = (wxMenu*) NULL;
}
+ // the MDI frame menubar is not automatically deleted by Windows unlike for
+ // the normal frames
+ if ( m_hMenu )
+ {
+ ::DestroyMenu((HMENU)m_hMenu);
+ m_hMenu = (WXHMENU)NULL;
+ }
+
if ( m_clientWindow )
{
if ( m_clientWindow->MSWGetOldWndProc() )
}
}
+#if wxUSE_MENUS_NATIVE
+
void wxMDIParentFrame::InternalSetMenuBar()
{
-// HMENU subMenu = GetSubMenu((HMENU) m_windowMenu, 0);
-
m_parentFrameActive = TRUE;
- HMENU subMenu = (HMENU) 0;
- if (GetWindowMenu())
- subMenu = (HMENU) GetWindowMenu()->GetHMenu();
-
- InsertWindowMenu(GetClientWindow(), m_hMenu, subMenu);
+ InsertWindowMenu(GetClientWindow(), m_hMenu, GetMDIWindowMenu(this));
}
+#endif // wxUSE_MENUS_NATIVE
+
void wxMDIParentFrame::SetWindowMenu(wxMenu* menu)
{
if (m_windowMenu)
delete m_windowMenu;
m_windowMenu = (wxMenu*) NULL;
}
+
if (menu)
{
m_windowMenu = menu;
if (GetMenuBar())
- InsertWindowMenu(GetClientWindow(), m_hMenu, (HMENU) m_windowMenu->GetHMenu());
+ {
+ InsertWindowMenu(GetClientWindow(), m_hMenu,
+ GetHmenuOf(m_windowMenu));
+ }
}
}
-void wxMDIParentFrame::OnSize(wxSizeEvent& event)
+void wxMDIParentFrame::OnSize(wxSizeEvent&)
{
if ( GetClientWindow() )
{
{
if ( m_clientWindow )
{
- m_clientWindow->SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
+ m_clientWindow->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
m_clientWindow->Refresh();
}
event.Skip();
}
+WXHICON wxMDIParentFrame::GetDefaultIcon() const
+{
+ return (WXHICON)(wxSTD_MDIPARENTFRAME_ICON ? wxSTD_MDIPARENTFRAME_ICON
+ : wxDEFAULT_MDIPARENTFRAME_ICON);
+}
+
// ---------------------------------------------------------------------------
// MDI operations
// ---------------------------------------------------------------------------
// is it one of standard MDI commands?
WXWPARAM wParam = 0;
+ WXLPARAM lParam = 0;
int msg;
switch ( id )
{
case IDM_WINDOWNEXT:
msg = WM_MDINEXT;
+ lParam = 0; // next child
+ break;
+
+ case IDM_WINDOWPREV:
+ msg = WM_MDINEXT;
+ lParam = 1; // previous child
break;
default:
if ( msg )
{
- ::SendMessage(GetWinHwnd(GetClientWindow()), msg, wParam, 0);
+ ::SendMessage(GetWinHwnd(GetClientWindow()), msg, wParam, lParam);
return TRUE;
}
long style,
const wxString& name)
{
- m_defaultIcon = (WXHICON)(wxSTD_MDICHILDFRAME_ICON ? wxSTD_MDICHILDFRAME_ICON
- : wxDEFAULT_MDICHILDFRAME_ICON);
-
SetName(name);
+ wxWindowBase::Show(TRUE); // MDI child frame starts off shown
if ( id > -1 )
m_windowId = id;
parent->AddChild(this);
}
- wxWndHook = this;
-
int x = pos.x;
int y = pos.y;
int width = size.x;
else
mcs.cy = CW_USEDEFAULT;
- DWORD msflags = WS_OVERLAPPED | WS_CLIPCHILDREN;
+ DWORD msflags = WS_OVERLAPPED | WS_CLIPCHILDREN | WS_THICKFRAME | WS_VISIBLE ;
if (style & wxMINIMIZE_BOX)
msflags |= WS_MINIMIZEBOX;
if (style & wxMAXIMIZE_BOX)
mcs.lParam = 0;
+ wxWindowCreationHook hook(this);
+
m_hWnd = (WXHWND)::SendMessage(GetWinHwnd(parent->GetClientWindow()),
WM_MDICREATE, 0, (LONG)(LPSTR)&mcs);
- wxWndHook = NULL;
wxAssociateWinWithHandle((HWND) GetHWND(), this);
- // VZ: what's this? an act of piracy?
- //SetWindowLong(GetHwnd(), 0, (long)this);
-
wxModelessWindows.Append(this);
+
return TRUE;
}
{
DestroyChildren();
- // already delete by DestroyChildren()
+ // already deleted by DestroyChildren()
m_frameToolBar = NULL;
m_frameStatusBar = NULL;
+ RemoveWindowMenu(NULL, m_hMenu);
+
MSWDestroyWindow();
}
{
wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
- // HMENU subMenu = GetSubMenu((HMENU)parent->GetWindowMenu(), 0);
- HMENU subMenu = (HMENU) 0;
- if (parent->GetWindowMenu())
- subMenu = (HMENU) parent->GetWindowMenu()->GetHMenu();
-
- InsertWindowMenu(parent->GetClientWindow(), m_hMenu, subMenu);
+ InsertWindowMenu(parent->GetClientWindow(),
+ m_hMenu, GetMDIWindowMenu(parent));
parent->m_parentFrameActive = FALSE;
}
+WXHICON wxMDIChildFrame::GetDefaultIcon() const
+{
+ return (WXHICON)(wxSTD_MDICHILDFRAME_ICON ? wxSTD_MDICHILDFRAME_ICON
+ : wxDEFAULT_MDICHILDFRAME_ICON);
+}
+
// ---------------------------------------------------------------------------
// MDI operations
// ---------------------------------------------------------------------------
break;
case WM_GETMINMAXINFO:
- // let the default window proc calculate the size of MDI children
- // frames because it is based on the size of the MDI client window,
- // not on the values specified in wxWindow m_min/max variables
- return MSWDefWindowProc(message, wParam, lParam);
+ processed = HandleGetMinMaxInfo((MINMAXINFO *)lParam);
+ break;
case WM_MDIACTIVATE:
{
parent->m_currentChild = NULL;
HMENU parent_menu = (HMENU)parent->GetWinMenu();
- if ( parent_menu )
+
+ // activate the the parent menu only when there is no other child
+ // that has been activated
+ if ( parent_menu && !hwndAct )
{
parent->m_parentFrameActive = TRUE;
if ( menuToSet )
{
- HMENU subMenu = (HMENU) 0;
- if (parent->GetWindowMenu())
- subMenu = (HMENU) parent->GetWindowMenu()->GetHMenu();
-
- MDISetMenu(parent->GetClientWindow(), menuToSet, subMenu);
+ MDISetMenu(parent->GetClientWindow(),
+ menuToSet, GetMDIWindowMenu(parent));
}
wxActivateEvent event(wxEVT_ACTIVATE, activated, m_windowId);
event.SetEventObject( this );
+ ResetWindowStyle((void *)NULL);
+
return GetEventHandler()->ProcessEvent(event);
}
return FALSE;
}
+bool wxMDIChildFrame::HandleGetMinMaxInfo(void *mmInfo)
+{
+ MINMAXINFO *info = (MINMAXINFO *)mmInfo;
+
+ // let the default window proc calculate the size of MDI children
+ // frames because it is based on the size of the MDI client window,
+ // not on the values specified in wxWindow m_max variables
+ bool processed = MSWDefWindowProc(WM_GETMINMAXINFO, 0, (LPARAM)mmInfo) != 0;
+
+ int minWidth = GetMinWidth(),
+ minHeight = GetMinHeight();
+
+ // but allow GetSizeHints() to set the min size
+ if ( minWidth != -1 )
+ {
+ info->ptMinTrackSize.x = minWidth;
+
+ processed = TRUE;
+ }
+
+ if ( minHeight != -1 )
+ {
+ info->ptMinTrackSize.y = minHeight;
+
+ processed = TRUE;
+ }
+
+ return TRUE;
+}
+
// ---------------------------------------------------------------------------
// MDI specific message translation/preprocessing
// ---------------------------------------------------------------------------
void wxMDIChildFrame::MSWDestroyWindow()
{
- MSWDetachWindowMenu();
invalidHandle = GetHwnd();
wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
wxMDIChildFrame* pChild = pFrameWnd->GetActiveChild();
if (!pChild || (pChild == this))
{
- DWORD dwStyle = ::GetWindowLong(GetWinHwnd(pFrameWnd->GetClientWindow()), GWL_EXSTYLE);
- DWORD dwThisStyle = ::GetWindowLong(GetHwnd(), GWL_STYLE);
+ HWND hwndClient = GetWinHwnd(pFrameWnd->GetClientWindow());
+ DWORD dwStyle = ::GetWindowLong(hwndClient, GWL_EXSTYLE);
+
+ // we want to test whether there is a maximized child, so just set
+ // dwThisStyle to 0 if there is no child at all
+ DWORD dwThisStyle = pChild
+ ? ::GetWindowLong(GetWinHwnd(pChild), GWL_STYLE) : 0;
DWORD dwNewStyle = dwStyle;
- if (pChild != NULL && (dwThisStyle & WS_MAXIMIZE))
+ if ( dwThisStyle & WS_MAXIMIZE )
dwNewStyle &= ~(WS_EX_CLIENTEDGE);
else
dwNewStyle |= WS_EX_CLIENTEDGE;
if (dwStyle != dwNewStyle)
{
- HWND hwnd = GetWinHwnd(pFrameWnd->GetClientWindow());
- ::RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
- ::SetWindowLong(hwnd, GWL_EXSTYLE, dwNewStyle);
- ::SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
+ // force update of everything
+ ::RedrawWindow(hwndClient, NULL, NULL,
+ RDW_INVALIDATE | RDW_ALLCHILDREN);
+ ::SetWindowLong(hwndClient, GWL_EXSTYLE, dwNewStyle);
+ ::SetWindowPos(hwndClient, NULL, 0, 0, 0, 0,
SWP_FRAMECHANGED | SWP_NOACTIVATE |
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
SWP_NOCOPYBITS);
if (rect)
- ::GetClientRect(hwnd, rect);
+ ::GetClientRect(hwndClient, rect);
return TRUE;
}
bool wxMDIClientWindow::CreateClient(wxMDIParentFrame *parent, long style)
{
- m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE);
+ m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE);
CLIENTCREATESTRUCT ccs;
m_windowStyle = style;
m_parent = parent;
- ccs.hWindowMenu = (HMENU) 0;
- if (parent->GetWindowMenu())
- ccs.hWindowMenu = (HMENU) parent->GetWindowMenu()->GetHMenu();
+ ccs.hWindowMenu = GetMDIWindowMenu(parent);
ccs.idFirstChild = wxFIRST_MDI_CHILD;
- DWORD msStyle = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN;
+ DWORD msStyle = MDIS_ALLCHILDSTYLES | WS_VISIBLE | WS_CHILD |
+ WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+
if ( style & wxHSCROLL )
msStyle |= WS_HSCROLL;
if ( style & wxVSCROLL )
DWORD exStyle = 0;
#endif
- wxWndHook = this;
+ wxWindowCreationHook hook(this);
m_hWnd = (WXHWND)::CreateWindowEx
(
exStyle,
}
SubclassWin(m_hWnd);
- wxWndHook = NULL;
return TRUE;
}
wxWindow *parent = win->GetParent();
wxCHECK_RET( parent, wxT("MDI client without parent frame? weird...") );
+#ifndef __WIN16__
+ ::SendMessage(GetWinHwnd(win), WM_MDIREFRESHMENU, 0, 0L);
+#endif
+
::DrawMenuBar(GetWinHwnd(parent));
}
if (subMenu)
{
- int N = GetMenuItemCount(hmenu);
- bool success = FALSE;
- for ( int i = 0; i < N; i++ )
- {
- wxChar buf[256];
- int chars = GetMenuString(hmenu, i, buf, WXSIZEOF(buf), MF_BYPOSITION);
- if ( chars == 0 )
+ int N = GetMenuItemCount(hmenu);
+ bool success = FALSE;
+ for ( int i = 0; i < N; i++ )
{
- wxLogLastError(wxT("GetMenuString"));
+ wxChar buf[256];
+ int chars = GetMenuString(hmenu, i, buf, WXSIZEOF(buf), MF_BYPOSITION);
+ if ( chars == 0 )
+ {
+ wxLogLastError(wxT("GetMenuString"));
- continue;
+ continue;
+ }
+
+ if ( wxStripMenuCodes(wxString(buf)).IsSameAs(_("Help")) )
+ {
+ success = TRUE;
+ ::InsertMenu(hmenu, i, MF_BYPOSITION | MF_POPUP | MF_STRING,
+ (UINT)subMenu, _("&Window"));
+ break;
+ }
}
- if ( wxStripMenuCodes(wxString(buf)).IsSameAs(_("Help")) )
+ if ( !success )
{
- success = TRUE;
- ::InsertMenu(hmenu, i, MF_BYPOSITION | MF_POPUP | MF_STRING,
- (UINT)subMenu, _("&Window"));
- break;
+ ::AppendMenu(hmenu, MF_POPUP, (UINT)subMenu, _("&Window"));
}
}
- if ( !success )
- {
- ::AppendMenu(hmenu, MF_POPUP, (UINT)subMenu, _("&Window"));
- }
- }
-
MDISetMenu(win, hmenu, subMenu);
}
static void RemoveWindowMenu(wxWindow *win, WXHMENU menu)
{
- // Try to insert Window menu in front of Help, otherwise append it.
- HMENU hmenu = (HMENU)menu;
- int N = GetMenuItemCount(hmenu);
- bool success = FALSE;
- for ( int i = 0; i < N; i++ )
+ HMENU hMenu = (HMENU)menu;
+
+ if ( hMenu )
{
- wxChar buf[256];
- int chars = GetMenuString(hmenu, i, buf, WXSIZEOF(buf), MF_BYPOSITION);
- if ( chars == 0 )
+ wxChar buf[1024];
+
+ int N = ::GetMenuItemCount(hMenu);
+ for ( int i = 0; i < N; i++ )
{
- wxLogLastError(wxT("GetMenuString"));
+ if ( !::GetMenuString(hMenu, i, buf, WXSIZEOF(buf), MF_BYPOSITION) )
+ {
+ wxLogLastError(wxT("GetMenuString"));
- continue;
- }
+ continue;
+ }
- if ( wxStripMenuCodes(wxString(buf)).IsSameAs(_("Window")) )
- {
- success = TRUE;
- ::RemoveMenu(hmenu, i, MF_BYPOSITION);
- break;
+ if ( wxStrcmp(buf, _("&Window")) == 0 )
+ {
+ if ( !::RemoveMenu(hMenu, i, MF_BYPOSITION) )
+ {
+ wxLogLastError(wxT("RemoveMenu"));
+ }
+
+ break;
+ }
}
}
- // Does passing 0 for the window menu really work with WM_MDISETMENU?
- MDISetMenu(win, hmenu, 0);
+ if ( win )
+ {
+ // we don't change the windows menu, but we update the main one
+ MDISetMenu(win, hMenu, NULL);
+ }
}
static void UnpackMDIActivate(WXWPARAM wParam, WXLPARAM lParam,
*hwndDeact = (WXHWND)HIWORD(lParam);
#endif // Win32/Win16
}
+
+#endif
+// wxUSE_MDI_ARCHITECTURE && !defined(__WXUNIVERSAL__)
+