/////////////////////////////////////////////////////////////////////////////
// Name: mdi.cpp
// Purpose: MDI classes
-// Author: AUTHOR
+// Author: David Webster
// Modified by:
-// Created: ??/??/98
+// Created: 10/10/99
// RCS-ID: $Id$
-// Copyright: (c) AUTHOR
-// Licence: wxWindows licence
+// Copyright: (c) David Webster
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
-#ifdef __GNUG__
-#pragma implementation "mdi.h"
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/setup.h"
+ #include "wx/frame.h"
+ #include "wx/menu.h"
+ #include "wx/app.h"
+ #include "wx/utils.h"
+ #include "wx/dialog.h"
+ #include "wx/statusbr.h"
+ #include "wx/settings.h"
+ #include "wx/intl.h"
+ #include "wx/log.h"
#endif
#include "wx/mdi.h"
-#include "wx/menu.h"
-#include "wx/settings.h"
+#include "wx/os2/private.h"
+
+#include <string.h>
+
+// ---------------------------------------------------------------------------
+// global variables
+// ---------------------------------------------------------------------------
+
+extern wxWindowList wxModelessWindows; // from dialog.cpp
+extern wxMenu *wxCurrentPopupMenu;
+
+extern wxWindow *wxWndHook; // from window.cpp
+
+extern void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win);
+
+static HWND invalidHandle = 0;
+
+// ---------------------------------------------------------------------------
+// constants
+// ---------------------------------------------------------------------------
+
+static const int IDM_WINDOWTILE = 4001;
+static const int IDM_WINDOWTILEHOR = 4001;
+static const int IDM_WINDOWCASCADE = 4002;
+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;
+static const int wxLAST_MDI_CHILD = 4600;
-extern wxList wxModelessWindows;
+// Status border dimensions
+static const int wxTHICK_LINE_BORDER = 3;
+static const int wxTHICK_LINE_WIDTH = 1;
+
+// ---------------------------------------------------------------------------
+// private functions
+// ---------------------------------------------------------------------------
+
+// set the MDI menus (by sending the WM_MDISETMENU message) and update the menu
+// of the parent of win (which is supposed to be the MDI client window)
+static void MDISetMenu(wxWindow *win, HMENU hmenuFrame, HMENU hmenuWindow);
+
+// insert the window menu (subMenu) into menu just before "Help" submenu or at
+// the very end if not found
+static void InsertWindowMenu(wxWindow *win, WXHMENU menu, HMENU subMenu);
+
+// is this an id of an MDI child?
+inline bool IsMdiCommandId(int id)
+{
+ 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;
+}
-#if !USE_SHARED_LIBRARY
-IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame, wxFrame)
-IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame, wxFrame)
-IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxWindow)
+// ===========================================================================
+// implementation
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// wxWin macros
+// ---------------------------------------------------------------------------
+
+ IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame, wxFrame)
+ IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame, wxFrame)
+ IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxWindow)
BEGIN_EVENT_TABLE(wxMDIParentFrame, wxFrame)
- EVT_SIZE(wxMDIParentFrame::OnSize)
- EVT_ACTIVATE(wxMDIParentFrame::OnActivate)
- EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged)
+ EVT_SIZE(wxMDIParentFrame::OnSize)
+ EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged)
END_EVENT_TABLE()
BEGIN_EVENT_TABLE(wxMDIClientWindow, wxWindow)
- EVT_SCROLL(wxMDIClientWindow::OnScroll)
+ EVT_SCROLL(wxMDIClientWindow::OnScroll)
END_EVENT_TABLE()
-#endif
-
-// Parent frame
+// ===========================================================================
+// wxMDIParentFrame: the frame which contains the client window which manages
+// the children
+// ===========================================================================
wxMDIParentFrame::wxMDIParentFrame()
{
+ m_clientWindow = NULL;
+ m_currentChild = NULL;
+ m_windowMenu = 0;
+ m_parentFrameActive = TRUE;
}
bool wxMDIParentFrame::Create(wxWindow *parent,
- wxWindowID id,
- const wxString& title,
- const wxPoint& pos,
- const wxSize& size,
- long style,
- const wxString& name)
+ wxWindowID id,
+ const wxString& title,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxString& name)
{
- if (!parent)
- wxTopLevelWindows.Append(this);
+ m_hDefaultIcon = (WXHICON) (wxSTD_MDIPARENTFRAME_ICON ? wxSTD_MDIPARENTFRAME_ICON : wxDEFAULT_MDIPARENTFRAME_ICON);
- SetName(name);
- m_windowStyle = style;
+ m_clientWindow = NULL;
+ m_currentChild = NULL;
+ m_windowMenu = 0;
+ m_parentFrameActive = TRUE;
- if (parent) parent->AddChild(this);
+ if (!parent)
+ wxTopLevelWindows.Append(this);
- if ( id > -1 )
- m_windowId = id;
- else
- m_windowId = (int)NewControlId();
+ SetName(name);
+ wxWindowBase::Show(TRUE); // MDI child frame starts off shown
+ m_windowStyle = style;
- // TODO: create MDI parent frame
+ if (parent) parent->AddChild(this);
- wxModelessWindows.Append(this);
+ if ( id > -1 )
+ m_windowId = id;
+ else
+ m_windowId = (int)NewControlId();
- return TRUE;
+ int x = pos.x;
+ int y = pos.y;
+ int width = size.x;
+ int height = size.y;
+
+// TODO: m_windowMenu = (WXHMENU) ::LoadMenu(wxGetInstance(), wxT("wxWindowMenu"));
+/*
+ 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;
+
+ if (style & wxCLIP_CHILDREN)
+ msflags |= WS_CLIPCHILDREN;
+
+ wxWindow::MSWCreate(m_windowId, parent, wxMDIFrameClassName, this, title, x, y, width, height,
+ msflags);
+*/
+ wxModelessWindows.Append(this);
+
+ return TRUE;
}
wxMDIParentFrame::~wxMDIParentFrame()
{
-}
+ DestroyChildren();
-// Get size *available for subwindows* i.e. excluding menu bar.
-void wxMDIParentFrame::GetClientSize(int *x, int *y) const
-{
- // TODO
-}
+// TODO: ::DestroyMenu((HMENU)m_windowMenu);
+ m_windowMenu = 0;
-void wxMDIParentFrame::SetMenuBar(wxMenuBar *menu_bar)
-{
- // TODO
- if (!menu_bar)
+ if ( m_clientWindow )
{
- m_frameMenuBar = NULL;
- return;
- }
-
- if (menu_bar->m_menuBarFrame)
- return;
+ if ( m_clientWindow->OS2GetOldWndProc() )
+ m_clientWindow->UnsubclassWin();
- m_frameMenuBar = menu_bar;
+ m_clientWindow->SetHWND(0);
+ delete m_clientWindow;
+ }
}
-void wxMDIParentFrame::OnSize(wxSizeEvent& event)
+void wxMDIParentFrame::InternalSetMenuBar()
{
-#if wxUSE_CONSTRAINTS
- if (GetAutoLayout())
- Layout();
-#endif
- int x = 0;
- int y = 0;
- int width, height;
- GetClientSize(&width, &height);
+ // TODO:
+/*
+ HMENU subMenu = GetSubMenu((HMENU) m_windowMenu, 0);
- if ( GetClientWindow() )
- GetClientWindow()->SetSize(x, y, width, height);
+ m_parentFrameActive = TRUE;
+
+ InsertWindowMenu(GetClientWindow(), m_hMenu, subMenu);
+*/
}
-void wxMDIParentFrame::OnActivate(wxActivateEvent& event)
+void wxMDIParentFrame::OnSize(wxSizeEvent& event)
{
- // Do nothing
+ // TODO:
+/*
+ if ( GetClientWindow() )
+ {
+ int width, height;
+ GetClientSize(&width, &height);
+
+ GetClientWindow()->SetSize(0, 0, width, height);
+ }
+*/
}
// Returns the active MDI child window
wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const
{
- // TODO
- return NULL;
+ HWND hWnd = 0; // TODO: (HWND)::SendMessage(GetWinHwnd(GetClientWindow()),
+// WM_MDIGETACTIVE, 0, 0L);
+ if ( hWnd == 0 )
+ return NULL;
+ else
+ return (wxMDIChildFrame *)wxFindWinFromHandle((WXHWND) hWnd);
}
-// Create the client window class (don't Create the window,
-// just return a new class)
+// Create the client window class (don't Create the window, just return a new
+// class)
wxMDIClientWindow *wxMDIParentFrame::OnCreateClient()
{
- return new wxMDIClientWindow ;
+ return new wxMDIClientWindow;
}
// Responds to colour changes, and passes event on to children.
void wxMDIParentFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
{
- // TODO
+ if ( m_clientWindow )
+ {
+ m_clientWindow->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
+ m_clientWindow->Refresh();
+ }
- // Propagate the event to the non-top-level children
- wxFrame::OnSysColourChanged(event);
+ event.Skip();
}
+// ---------------------------------------------------------------------------
// MDI operations
+// ---------------------------------------------------------------------------
+
void wxMDIParentFrame::Cascade()
{
- // TODO
+// TODO: ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDICASCADE, 0, 0);
}
+// TODO: add a direction argument (hor/vert)
void wxMDIParentFrame::Tile()
{
- // TODO
+// TODO: ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDITILE, MDITILE_HORIZONTAL, 0);
}
void wxMDIParentFrame::ArrangeIcons()
{
- // TODO
+// TODO: ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDIICONARRANGE, 0, 0);
}
void wxMDIParentFrame::ActivateNext()
{
- // TODO
+// TODO: ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDINEXT, 0, 0);
}
void wxMDIParentFrame::ActivatePrevious()
{
- // TODO
+// TODO: ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDINEXT, 0, 1);
}
-// Child frame
+// ---------------------------------------------------------------------------
+// the MDI parent frame window proc
+// ---------------------------------------------------------------------------
-wxMDIChildFrame::wxMDIChildFrame()
+MRESULT wxMDIParentFrame::OS2WindowProc(WXUINT message,
+ WXWPARAM wParam,
+ WXLPARAM lParam)
{
+ MRESULT rc = 0;
+ bool processed = FALSE;
+
+ // TODO:
+/*
+ switch ( message )
+ {
+ case WM_ACTIVATE:
+ {
+ WXWORD state, minimized;
+ WXHWND hwnd;
+ UnpackActivate(wParam, lParam, &state, &minimized, &hwnd);
+
+ processed = HandleActivate(state, minimized != 0, hwnd);
+ }
+ break;
+
+ case WM_COMMAND:
+ {
+ WXWORD id, cmd;
+ WXHWND hwnd;
+ UnpackCommand(wParam, lParam, &id, &hwnd, &cmd);
+
+ (void)HandleCommand(id, cmd, hwnd);
+
+ // even if the frame didn't process it, there is no need to try it
+ // once again (i.e. call wxFrame::HandleCommand()) - we just dud it,
+ // so pretend we processed the message anyhow
+ processed = TRUE;
+ }
+
+ // always pass this message DefFrameProc(), otherwise MDI menu
+ // commands (and sys commands - more surprizingly!) won't work
+ MSWDefWindowProc(message, wParam, lParam);
+ break;
+
+ case WM_CREATE:
+ m_clientWindow = OnCreateClient();
+ // Uses own style for client style
+ if ( !m_clientWindow->CreateClient(this, GetWindowStyleFlag()) )
+ {
+ wxLogMessage(_("Failed to create MDI parent frame."));
+
+ rc = -1;
+ }
+
+ processed = TRUE;
+ break;
+
+ case WM_ERASEBKGND:
+ processed = TRUE;
+
+ // we erase background ourselves
+ rc = TRUE;
+ break;
+
+ case WM_MENUSELECT:
+ {
+ WXWORD item, flags;
+ WXHMENU hmenu;
+ UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu);
+
+ if ( m_parentFrameActive )
+ {
+ processed = HandleMenuSelect(item, flags, hmenu);
+ }
+ else if (m_currentChild)
+ {
+ processed = m_currentChild->
+ HandleMenuSelect(item, flags, hmenu);
+ }
+ }
+ break;
+
+ case WM_SIZE:
+ // as we don't (usually) resize the MDI client to exactly fit the
+ // client area (we put it below the toolbar, above statusbar &c),
+ // we should not pass this one to DefFrameProc
+ break;
+ }
+*/
+ if ( !processed )
+ rc = wxFrame::OS2WindowProc(message, wParam, lParam);
+
+ return rc;
}
-bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
- wxWindowID id,
- const wxString& title,
- const wxPoint& pos,
- const wxSize& size,
- long style,
- const wxString& name)
+bool wxMDIParentFrame::HandleActivate(int state, bool minimized, WXHWND activate)
{
- SetName(name);
+ bool processed = FALSE;
- if ( id > -1 )
- m_windowId = id;
+ // TODO:
+/*
+ if ( wxWindow::HandleActivate(state, minimized, activate) )
+ {
+ // already processed
+ processed = TRUE;
+ }
+
+ // If this window is an MDI parent, we must also send an OnActivate message
+ // to the current child.
+ if ( (m_currentChild != NULL) &&
+ ((state == WA_ACTIVE) || (state == WA_CLICKACTIVE)) )
+ {
+ wxActivateEvent event(wxEVT_ACTIVATE, TRUE, m_currentChild->GetId());
+ event.SetEventObject( m_currentChild );
+ if ( m_currentChild->GetEventHandler()->ProcessEvent(event) )
+ processed = TRUE;
+ }
+*/
+ return processed;
+}
+
+bool wxMDIParentFrame::HandleCommand(WXWORD id, WXWORD cmd, WXHWND hwnd)
+{
+ // In case it's e.g. a toolbar.
+ if ( hwnd )
+ {
+ wxWindow *win = wxFindWinFromHandle(hwnd);
+ if ( win )
+ return FALSE; // Need to get wxWindow for OS/2 up to date: win->OS2Command(cmd, id);
+ }
+
+ // is it one of standard MDI commands?
+ WXWPARAM wParam = 0;
+ int msg = 0;
+
+ // TODO:
+/*
+ switch ( id )
+ {
+ case IDM_WINDOWCASCADE:
+ msg = WM_MDICASCADE;
+ wParam = MDITILE_SKIPDISABLED;
+ break;
+
+ case IDM_WINDOWTILEHOR:
+ wParam |= MDITILE_HORIZONTAL;
+ // fall through
+
+ case IDM_WINDOWTILEVERT:
+ if ( !wParam )
+ wParam = MDITILE_VERTICAL;
+ msg = WM_MDITILE;
+ wParam |= MDITILE_SKIPDISABLED;
+ break;
+
+ case IDM_WINDOWICONS:
+ msg = WM_MDIICONARRANGE;
+ break;
+
+ case IDM_WINDOWNEXT:
+ msg = WM_MDINEXT;
+ break;
+
+ default:
+ msg = 0;
+ }
+*/
+ if ( msg )
+ {
+// TODO: ::SendMessage(GetWinHwnd(GetClientWindow()), msg, wParam, 0);
+
+ return TRUE;
+ }
+
+ // FIXME VZ: what does this test do??
+ if (id >= 0xF000)
+ {
+ return FALSE; // Get WndProc to call default proc
+ }
+
+ if ( IsMdiCommandId(id) )
+ {
+ wxWindowList::Node* node = GetChildren().GetFirst();
+ while ( node )
+ {
+ wxWindow* child = node->GetData();
+ if ( child->GetHWND() )
+ {
+ long childId = wxGetWindowId(child->GetHWND());
+ if (childId == (long)id)
+ {
+// TODO: ::SendMessage( GetWinHwnd(GetClientWindow()),
+// WM_MDIACTIVATE,
+// (WPARAM)child->GetHWND(), 0);
+ return TRUE;
+ }
+ }
+ node = node->GetNext();
+ }
+ }
+ else if ( m_parentFrameActive )
+ {
+ return ProcessCommand(id);
+ }
+ else if ( m_currentChild )
+ {
+ return m_currentChild->HandleCommand(id, cmd, hwnd);
+ }
else
- m_windowId = (int)NewControlId();
+ {
+ // this shouldn't happen because it means that our messages are being
+ // lost (they're not sent to the parent frame nor to the children)
+ wxFAIL_MSG(wxT("MDI parent frame is not active, "
+ "yet there is no active MDI child?"));
+ }
- if (parent) parent->AddChild(this);
+ return FALSE;
+}
- // TODO: create child frame
+MRESULT wxMDIParentFrame::OS2DefWindowProc(WXUINT message,
+ WXWPARAM wParam,
+ WXLPARAM lParam)
+{
+ WXHWND clientWnd;
+ if ( GetClientWindow() )
+ clientWnd = GetClientWindow()->GetHWND();
+ else
+ clientWnd = 0;
- wxModelessWindows.Append(this);
+// TODO: return DefFrameProc(GetHwnd(), (HWND)clientWnd, message, wParam, lParam);
+ return((MRESULT)0);
+}
+
+bool wxMDIParentFrame::OS2TranslateMessage(WXMSG* msg)
+{
+ // TODO:
+/*
+ if ( m_currentChild && m_currentChild->GetHWND() &&
+ m_currentChild->OS2TranslateMessage(msg) )
+ {
+ return TRUE;
+ }
+
+ if ( m_acceleratorTable.Translate(this, msg) )
+ {
+ return TRUE;
+ }
+
+ if ( pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN )
+ {
+ if ( ::TranslateMDISysAccel(GetWinHwnd(GetClientWindow()), pMsg))
+ return TRUE;
+ }
+*/
return FALSE;
}
+// ===========================================================================
+// wxMDIChildFrame
+// ===========================================================================
+
+wxMDIChildFrame::wxMDIChildFrame()
+{
+}
+
+bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
+ wxWindowID id,
+ const wxString& title,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxString& name)
+{
+ m_hDefaultIcon = (WXHICON)(wxSTD_MDICHILDFRAME_ICON ? wxSTD_MDICHILDFRAME_ICON
+ : wxDEFAULT_MDICHILDFRAME_ICON);
+
+ SetName(name);
+
+ if ( id > -1 )
+ m_windowId = id;
+ else
+ m_windowId = (int)NewControlId();
+
+ if ( parent )
+ {
+ parent->AddChild(this);
+ }
+
+ wxWndHook = this;
+
+ int x = pos.x;
+ int y = pos.y;
+ int width = size.x;
+ int height = size.y;
+
+ // TODO:
+/*
+ MDICREATESTRUCT mcs;
+
+ mcs.szClass = wxMDIChildFrameClassName;
+ mcs.szTitle = title;
+ mcs.hOwner = wxGetInstance();
+ if (x > -1)
+ mcs.x = x;
+ else
+ mcs.x = CW_USEDEFAULT;
+
+ if (y > -1)
+ mcs.y = y;
+ else
+ mcs.y = CW_USEDEFAULT;
+
+ if (width > -1)
+ mcs.cx = width;
+ else
+ mcs.cx = CW_USEDEFAULT;
+
+ if (height > -1)
+ mcs.cy = height;
+ else
+ mcs.cy = CW_USEDEFAULT;
+
+ DWORD msflags = WS_OVERLAPPED | WS_CLIPCHILDREN;
+ 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;
+
+ mcs.style = msflags;
+
+ mcs.lParam = 0;
+*/
+ DWORD Return = 0; // SendMessage(GetWinHwnd(parent->GetClientWindow()),
+// WM_MDICREATE, 0, (LONG)(LPSTR)&mcs);
+ m_hWnd = (WXHWND)Return;
+
+ wxWndHook = NULL;
+ wxAssociateWinWithHandle((HWND) GetHWND(), this);
+
+ // VZ: what's this? an act of piracy?
+ //SetWindowLong(GetHwnd(), 0, (long)this);
+
+ wxModelessWindows.Append(this);
+ return TRUE;
+}
+
wxMDIChildFrame::~wxMDIChildFrame()
{
+ OS2DestroyWindow();
}
// Set the client size (i.e. leave the calculation of borders etc.
// to wxWindows)
-void wxMDIChildFrame::SetClientSize(int width, int height)
+void wxMDIChildFrame::DoSetClientSize(int width, int height)
{
- // TODO
+ HWND hWnd = GetHwnd();
+
+ // TODO:
+/*
+ RECT rect;
+ ::GetClientRect(hWnd, &rect);
+
+ RECT rect2;
+ GetWindowRect(hWnd, &rect2);
+
+ // Find the difference between the entire window (title bar and all)
+ // and the client area; add this to the new client size to move the
+ // window
+ int actual_width = rect2.right - rect2.left - rect.right + width;
+ int actual_height = rect2.bottom - rect2.top - rect.bottom + height;
+
+ if (GetStatusBar())
+ {
+ int sx, sy;
+ GetStatusBar()->GetSize(&sx, &sy);
+ actual_height += sy;
+ }
+
+ POINT point;
+ point.x = rect2.left;
+ point.y = rect2.top;
+
+ // If there's an MDI parent, must subtract the parent's top left corner
+ // since MoveWindow moves relative to the parent
+ wxMDIParentFrame *mdiParent = (wxMDIParentFrame *)GetParent();
+ ::ScreenToClient((HWND) mdiParent->GetClientWindow()->GetHWND(), &point);
+
+ MoveWindow(hWnd, point.x, point.y, actual_width, actual_height, (BOOL)TRUE);
+
+ wxSizeEvent event(wxSize(width, height), m_windowId);
+ event.SetEventObject( this );
+ GetEventHandler()->ProcessEvent(event);
+*/
}
-void wxMDIChildFrame::GetPosition(int *x, int *y) const
+void wxMDIChildFrame::DoGetPosition(int *x, int *y) const
{
- // TODO
+ // TODO:
+/*
+ RECT rect;
+ GetWindowRect(GetHwnd(), &rect);
+ POINT point;
+ point.x = rect.left;
+ point.y = rect.top;
+
+ // Since we now have the absolute screen coords,
+ // if there's a parent we must subtract its top left corner
+ wxMDIParentFrame *mdiParent = (wxMDIParentFrame *)GetParent();
+ ::ScreenToClient((HWND) mdiParent->GetClientWindow()->GetHWND(), &point);
+
+ *x = point.x;
+ *y = point.y;
+*/
}
-void wxMDIChildFrame::SetMenuBar(wxMenuBar *menu_bar)
+void wxMDIChildFrame::InternalSetMenuBar()
{
- // TODO
- if (!menu_bar)
- {
- m_frameMenuBar = NULL;
- return;
- }
-
- if (menu_bar->m_menuBarFrame)
- return;
- m_frameMenuBar = menu_bar;
+ // TODO:
+/*
+
+ wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
+
+ HMENU subMenu = GetSubMenu((HMENU)parent->GetWindowMenu(), 0);
+
+ InsertWindowMenu(parent->GetClientWindow(), m_hMenu, subMenu);
+
+ parent->m_parentFrameActive = FALSE;
+*/
}
+// ---------------------------------------------------------------------------
// MDI operations
-void wxMDIChildFrame::Maximize()
+// ---------------------------------------------------------------------------
+
+void wxMDIChildFrame::Maximize(bool maximize)
{
- // TODO
+ wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
+ // TODO:
+/*
+ if ( parent && parent->GetClientWindow() )
+ {
+ ::SendMessage(GetWinHwnd(parent->GetClientWindow()),
+ maximize ? WM_MDIMAXIMIZE : WM_MDIRESTORE,
+ (WPARAM)GetHwnd(), 0);
+ }
+*/
}
void wxMDIChildFrame::Restore()
{
- // TODO
+ // TODO:
+/*
+ wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
+ if ( parent && parent->GetClientWindow() )
+ {
+ ::SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDIRESTORE,
+ (WPARAM) GetHwnd(), 0);
+ }
+*/
}
void wxMDIChildFrame::Activate()
+{
+ // TODO:
+/*
+ wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
+ if ( parent && parent->GetClientWindow() )
+ {
+ ::SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDIACTIVATE,
+ (WPARAM) GetHwnd(), 0);
+ }
+*/
+}
+
+// ---------------------------------------------------------------------------
+// MDI window proc and message handlers
+// ---------------------------------------------------------------------------
+
+MRESULT wxMDIChildFrame::OS2WindowProc(WXUINT message,
+ WXWPARAM wParam,
+ WXLPARAM lParam)
+{
+ MRESULT rc = 0;
+ bool processed = FALSE;
+
+ // TODO:
+/*
+ switch ( message )
+ {
+ case WM_COMMAND:
+ {
+ WORD id, cmd;
+ WXHWND hwnd;
+ UnpackCommand((WXWPARAM)wParam, (WXLPARAM)lParam,
+ &id, &hwnd, &cmd);
+
+ processed = HandleCommand(id, cmd, (WXHWND)hwnd);
+ }
+ 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);
+
+ case WM_MDIACTIVATE:
+ {
+ WXWORD act;
+ WXHWND hwndAct, hwndDeact;
+ UnpackMDIActivate(wParam, lParam, &act, &hwndAct, &hwndDeact);
+
+ processed = HandleMDIActivate(act, hwndAct, hwndDeact);
+ }
+ // fall through
+
+ case WM_MOVE:
+ // must pass WM_MOVE to DefMDIChildProc() to recalculate MDI client
+ // scrollbars if necessary
+
+ // fall through
+
+ case WM_SIZE:
+ // must pass WM_SIZE to DefMDIChildProc(), otherwise many weird
+ // things happen
+ MSWDefWindowProc(message, wParam, lParam);
+ break;
+
+ case WM_SYSCOMMAND:
+ // DefMDIChildProc handles SC_{NEXT/PREV}WINDOW here, so pass it
+ // the message (the base class version does not)
+ return MSWDefWindowProc(message, wParam, lParam);
+
+ case WM_WINDOWPOSCHANGING:
+ processed = HandleWindowPosChanging((LPWINDOWPOS)lParam);
+ break;
+ }
+*/
+ if ( !processed )
+ rc = wxFrame::OS2WindowProc(message, wParam, lParam);
+
+ return rc;
+}
+
+bool wxMDIChildFrame::HandleSize(int x, int y, WXUINT id)
+{
+ HWND hwnd = GetHwnd();
+
+ if ( !hwnd || hwnd == invalidHandle )
+ {
+ return FALSE;
+ }
+
+ // TODO:
+/*
+ switch (id)
+ {
+ case SIZEFULLSCREEN:
+ case SIZENORMAL:
+ m_iconized = FALSE;
+ break;
+
+ case SIZEICONIC:
+ m_iconized = TRUE;
+ break;
+ }
+
+ if ( !m_iconized )
+ {
+ // forward WM_SIZE to status bar control
+#if wxUSE_NATIVE_STATUSBAR
+ if (m_frameStatusBar && m_frameStatusBar->IsKindOf(CLASSINFO(wxStatusBar95)))
+ {
+ wxSizeEvent event(wxSize(x, y), m_frameStatusBar->GetId());
+ event.SetEventObject( m_frameStatusBar );
+
+ ((wxStatusBar95 *)m_frameStatusBar)->OnSize(event);
+ }
+#endif // wxUSE_NATIVE_STATUSBAR
+
+ PositionStatusBar();
+ PositionToolBar();
+
+ return wxWindow::HandleSize(x, y, id);
+ }
+ else
+ {
+ return FALSE;
+ }
+*/
+ return TRUE;
+}
+
+bool wxMDIChildFrame::HandleCommand(WXWORD id, WXWORD cmd, WXHWND hwnd)
+{
+ // In case it's e.g. a toolbar.
+ if ( hwnd )
+ {
+ wxWindow *win = wxFindWinFromHandle(hwnd);
+// if (win)
+// Fix dependent stuff return win->OS2Command(cmd, id);
+ }
+
+ if (wxCurrentPopupMenu)
+ {
+ wxMenu *popupMenu = wxCurrentPopupMenu;
+ wxCurrentPopupMenu = NULL;
+// Fix dependent stuff if (popupMenu->OS2Command(cmd, id))
+// return TRUE;
+ }
+
+ if (GetMenuBar() && GetMenuBar()->FindItem(id))
+ {
+ ProcessCommand(id);
+ return TRUE;
+ }
+ else
+ return FALSE;
+
+ return TRUE;
+}
+
+bool wxMDIChildFrame::HandleMDIActivate(long WXUNUSED(activate),
+ WXHWND hwndAct,
+ WXHWND hwndDeact)
+{
+ wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
+
+ HMENU menuToSet = 0;
+
+ bool activated;
+
+ if ( m_hWnd == hwndAct )
+ {
+ activated = TRUE;
+ parent->m_currentChild = this;
+
+ HMENU child_menu = (HMENU)GetWinMenu();
+ if ( child_menu )
+ {
+ parent->m_parentFrameActive = FALSE;
+
+ menuToSet = child_menu;
+ }
+ }
+ else if ( m_hWnd == hwndDeact )
+ {
+ wxASSERT_MSG( parent->m_currentChild == this,
+ wxT("can't deactivate MDI child which wasn't active!") );
+
+ activated = FALSE;
+ parent->m_currentChild = NULL;
+
+ HMENU parent_menu = (HMENU)parent->GetWinMenu();
+ if ( parent_menu )
+ {
+ parent->m_parentFrameActive = TRUE;
+
+ menuToSet = parent_menu;
+ }
+ }
+ else
+ {
+ // we have nothing to with it
+ return FALSE;
+ }
+
+ if ( menuToSet )
+ {
+ HMENU subMenu = 0; // TODO: GetSubMenu((HMENU) parent->GetWindowMenu(), 0);
+
+ MDISetMenu(parent->GetClientWindow(), menuToSet, subMenu);
+ }
+
+ wxActivateEvent event(wxEVT_ACTIVATE, activated, m_windowId);
+ event.SetEventObject( this );
+
+ return GetEventHandler()->ProcessEvent(event);
+}
+
+bool wxMDIChildFrame::HandleWindowPosChanging(void *pos)
+{
+// WINDOWPOS *lpPos = (WINDOWPOS *)pos;
+ return FALSE;
+}
+
+// ---------------------------------------------------------------------------
+// MDI specific message translation/preprocessing
+// ---------------------------------------------------------------------------
+
+MRESULT wxMDIChildFrame::OS2DefWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
{
// TODO
+/*
+ return DefMDIChildProc(GetHwnd(),
+ (UINT)message, (WPARAM)wParam, (LPARAM)lParam);
+*/
+ return (MRESULT)0;
}
-// Client window
+bool wxMDIChildFrame::OS2TranslateMessage(WXMSG* msg)
+{
+#if wxUSE_ACCEL
+ return m_acceleratorTable.Translate(GetParent()->GetHWND(), msg);
+#else
+ return FALSE;
+#endif //wxUSE_ACCEL
+
+}
-wxMDIClientWindow::wxMDIClientWindow()
+// ---------------------------------------------------------------------------
+// misc
+// ---------------------------------------------------------------------------
+
+void wxMDIChildFrame::OS2DestroyWindow()
{
+// get wxWindow up to date OS2DetachWindowMenu();
+ invalidHandle = GetHwnd();
+
+ wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
+
+ // Must make sure this handle is invalidated (set to NULL) since all sorts
+ // of things could happen after the child client is destroyed, but before
+ // the wxFrame is destroyed.
+
+ HWND oldHandle = (HWND)GetHWND();
+// TODO: SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDIDESTROY,
+// (WPARAM)oldHandle, 0);
+ invalidHandle = 0;
+
+ if (m_hMenu)
+ {
+// TODO: ::DestroyMenu((HMENU) m_hMenu);
+ m_hMenu = 0;
+ }
+ m_hWnd = 0;
}
-wxMDIClientWindow::~wxMDIClientWindow()
+// Change the client window's extended style so we don't get a client edge
+// style when a child is maximised (a double border looks silly.)
+bool wxMDIChildFrame::ResetWindowStyle(void *vrect)
{
+ return FALSE;
}
+// ===========================================================================
+// wxMDIClientWindow: the window of predefined (by Windows) class which
+// contains the child frames
+// ===========================================================================
+
bool wxMDIClientWindow::CreateClient(wxMDIParentFrame *parent, long style)
{
- // TODO create client window
- m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE);
+ m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE);
- return FALSE;
+ // TODO:
+/*
+ CLIENTCREATESTRUCT ccs;
+ m_windowStyle = style;
+ m_parent = parent;
+
+ ccs.hWindowMenu = (HMENU)parent->GetWindowMenu();
+ ccs.idFirstChild = wxFIRST_MDI_CHILD;
+
+ DWORD msStyle = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN;
+ if ( style & wxHSCROLL )
+ msStyle |= WS_HSCROLL;
+ if ( style & wxVSCROLL )
+ msStyle |= WS_VSCROLL;
+
+#if defined(__WIN95__)
+ DWORD exStyle = WS_EX_CLIENTEDGE;
+#else
+ DWORD exStyle = 0;
+#endif
+
+ wxWndHook = this;
+ m_hWnd = (WXHWND)::CreateWindowEx
+ (
+ exStyle,
+ wxT("MDICLIENT"),
+ NULL,
+ msStyle,
+ 0, 0, 0, 0,
+ GetWinHwnd(parent),
+ NULL,
+ wxGetInstance(),
+ (LPSTR)(LPCLIENTCREATESTRUCT)&ccs);
+ if ( !m_hWnd )
+ {
+ wxLogLastError("CreateWindowEx(MDI client)");
+
+ return FALSE;
+ }
+
+ SubclassWin(m_hWnd);
+ wxWndHook = NULL;
+*/
+ return TRUE;
}
// Explicitly call default scroll behaviour
void wxMDIClientWindow::OnScroll(wxScrollEvent& event)
{
- Default(); // Default processing
+ // Note: for client windows, the scroll position is not set in
+ // WM_HSCROLL, WM_VSCROLL, so we can't easily determine what
+ // scroll position we're at.
+ // This makes it hard to paint patterns or bitmaps in the background,
+ // and have the client area scrollable as well.
+
+ if ( event.GetOrientation() == wxHORIZONTAL )
+ m_scrollX = event.GetPosition(); // Always returns zero!
+ else
+ m_scrollY = event.GetPosition(); // Always returns zero!
+
+ event.Skip();
+}
+
+// ---------------------------------------------------------------------------
+// non member functions
+// ---------------------------------------------------------------------------
+
+static void MDISetMenu(wxWindow *win, HMENU hmenuFrame, HMENU hmenuWindow)
+{
+ // TODO:
+/*
+ ::SendMessage(GetWinHwnd(win), WM_MDISETMENU,
+ (WPARAM)hmenuFrame, (LPARAM)hmenuWindow);
+ // update menu bar of the parent window
+ wxWindow *parent = win->GetParent();
+ wxCHECK_RET( parent, wxT("MDI client without parent frame? weird...") );
+
+ ::DrawMenuBar(GetWinHwnd(parent));
+*/
+}
+
+static void InsertWindowMenu(wxWindow *win, WXHMENU menu, HMENU subMenu)
+{
+/*
+ // 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++ )
+ {
+ wxChar buf[256];
+ int chars = GetMenuString(hmenu, i, buf, WXSIZEOF(buf), MF_BYPOSITION);
+ if ( chars == 0 )
+ {
+ wxLogLastError(wxT("GetMenuString"));
+
+ continue;
+ }
+
+ if ( wxStripMenuCodes(wxString(buf)).IsSameAs(wxT("Help")) )
+ {
+ success = TRUE;
+ ::InsertMenu(hmenu, i, MF_BYPOSITION | MF_POPUP | MF_STRING,
+ (UINT)subMenu, wxT("&Window"));
+ break;
+ }
+ }
+
+ if ( !success )
+ {
+ ::AppendMenu(hmenu, MF_POPUP, (UINT)subMenu, wxT("&Window"));
+ }
+ MDISetMenu(win, hmenu, subMenu);
+*/
+}
+
+static void UnpackMDIActivate(WXWPARAM wParam, WXLPARAM lParam,
+ WXWORD *activate, WXHWND *hwndAct, WXHWND *hwndDeact)
+{
+ *activate = TRUE;
+ *hwndAct = (WXHWND)lParam;
+ *hwndDeact = (WXHWND)wParam;
}