]> git.saurik.com Git - wxWidgets.git/blobdiff - src/os2/mdi.cpp
Use generic dirdlg, added generic mdi classes.
[wxWidgets.git] / src / os2 / mdi.cpp
index 4869697cd7ced1494032a5bafa462c6fdc8fd0ba..70dedddf641d33459a6b3eb62d5f60e9e64abd80 100644 (file)
 /////////////////////////////////////////////////////////////////////////////
 // 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;
 }