+// ---------------------------------------------------------------------------
+// drag and drop
+// ---------------------------------------------------------------------------
+
+#if wxUSE_DRAG_AND_DROP
+void wxWindowOS2::SetDropTarget(
+  wxDropTarget*                     pDropTarget
+)
+{
+    m_dropTarget = pDropTarget;
+} // end of wxWindowOS2::SetDropTarget
+#endif
+
+//
+// old style file-manager drag&drop support: we retain the old-style
+// DragAcceptFiles in parallel with SetDropTarget.
+//
+void wxWindowOS2::DragAcceptFiles(
+  bool                              bAccept
+)
+{
+    HWND                            hWnd = GetHwnd();
+
+    if (hWnd && bAccept)
+        ::DrgAcceptDroppedFiles(hWnd, NULL, NULL, DO_COPY, 0L);
+} // end of wxWindowOS2::DragAcceptFiles
+
+// ----------------------------------------------------------------------------
+// tooltips
+// ----------------------------------------------------------------------------
+
+#if wxUSE_TOOLTIPS
+
+void wxWindowOS2::DoSetToolTip(
+  wxToolTip*                        pTooltip
+)
+{
+    wxWindowBase::DoSetToolTip(pTooltip);
+
+    if (m_tooltip)
+        m_tooltip->SetWindow(this);
+} // end of wxWindowOS2::DoSetToolTip
+
+#endif // wxUSE_TOOLTIPS
+
+// ---------------------------------------------------------------------------
+// moving and resizing
+// ---------------------------------------------------------------------------
+
+// Get total size
+void wxWindowOS2::DoGetSize(
+  int*                              pWidth
+, int*                              pHeight
+) const
+{
+    HWND                            hWnd;
+    RECTL                           vRect;
+
+    if (IsKindOf(CLASSINFO(wxFrame)))
+    {
+        wxFrame*                    pFrame = wxDynamicCast(this, wxFrame);
+        hWnd = pFrame->GetFrame();
+    }
+    else
+        hWnd = GetHwnd();
+
+    ::WinQueryWindowRect(hWnd, &vRect);
+
+    if (pWidth)
+        *pWidth = vRect.xRight - vRect.xLeft;
+    if (pHeight )
+        // OS/2 PM is backwards from windows
+        *pHeight = vRect.yTop - vRect.yBottom;
+} // end of wxWindowOS2::DoGetSize
+
+void wxWindowOS2::DoGetPosition(
+  int*                              pX
+, int*                              pY
+) const
+{
+    //
+    // Return parameters assume wxWidgets coordinate system
+    //
+    HWND                            hWnd;
+    SWP                             vSwp;
+    POINTL                          vPoint;
+    wxWindow*                       pParent = GetParent();
+
+    //
+    // It would seem that WinQueryWindowRect would be the correlary to
+    // the WIN32 WinGetRect, but unlike WinGetRect which returns the window
+    // origin position in screen coordinates, WinQueryWindowRect returns it
+    // relative to itself, i.e. (0,0).  To get the same under PM we must
+    // use WinQueryWindowPos.  This call, unlike the WIN32 call, however,
+    // returns a position relative to it's parent, so no parent adujstments
+    // are needed under OS/2.  Also, windows should be created using
+    // wxWindow coordinates, i.e 0,0 is the TOP left.
+    //
+    if (IsKindOf(CLASSINFO(wxFrame)))
+    {
+        wxFrame*                    pFrame = wxDynamicCast(this, wxFrame);
+        hWnd = pFrame->GetFrame();
+    }
+    else
+        hWnd = GetHwnd();
+
+    ::WinQueryWindowPos(hWnd, &vSwp);
+
+    vPoint.x = vSwp.x;
+    vPoint.y = vSwp.y;
+
+    // We need to convert to wxWidgets coordinates
+    int vHeight;
+    DoGetSize(NULL,&vHeight);
+    wxWindow* pWindow = wxDynamicCast(this,wxWindow);
+    vPoint.y = pWindow->GetOS2ParentHeight(pParent) - vPoint.y - vHeight;
+
+    //
+    // We may be faking the client origin. So a window that's really at (0,
+    // 30) may appear (to wxWin apps) to be at (0, 0).
+    //
+    if (pParent)
+    {
+        wxPoint                     vPt(pParent->GetClientAreaOrigin());
+
+        vPoint.x -= vPt.x;
+        vPoint.y -= vPt.y;
+    }
+
+    if (pX)
+        *pX = vPoint.x;
+    if  (pY)
+        *pY = vPoint.y;
+} // end of wxWindowOS2::DoGetPosition
+
+void wxWindowOS2::DoScreenToClient(
+  int*                              pX
+, int*                              pY
+) const
+{
+    HWND                            hWnd = GetHwnd();
+    SWP                             vSwp;
+
+    ::WinQueryWindowPos(hWnd, &vSwp);
+
+    if (pX)
+        *pX += vSwp.x;
+    if (pY)
+        *pY += vSwp.y;
+} // end of wxWindowOS2::DoScreenToClient
+
+void wxWindowOS2::DoClientToScreen(
+  int*                              pX
+, int*                              pY
+) const
+{
+    HWND                            hWnd = GetHwnd();
+    SWP                             vSwp;
+
+    ::WinQueryWindowPos(hWnd, &vSwp);
+
+    if (pX)
+        *pX += vSwp.x;
+    if (pY)
+        *pY += vSwp.y;
+} // end of wxWindowOS2::DoClientToScreen
+
+//
+// Get size *available for subwindows* i.e. excluding menu bar etc.
+// Must be a frame type window
+//
+void wxWindowOS2::DoGetClientSize(
+  int*                              pWidth
+, int*                              pHeight
+) const
+{
+    HWND                            hWnd = GetHwnd();
+    RECTL                           vRect;
+
+   ::WinQueryWindowRect(hWnd, &vRect);
+    if (IsKindOf(CLASSINFO(wxDialog)))
+    {
+        RECTL                       vTitle;
+        HWND                        hWndTitle;
+        //
+        // For a Dialog we have to explicitly request the client portion.
+        // For a Frame the hWnd IS the client window
+        //
+        hWndTitle = ::WinWindowFromID(hWnd, FID_TITLEBAR);
+        if (::WinQueryWindowRect(hWndTitle, &vTitle))
+        {
+            if (vTitle.yTop - vTitle.yBottom == 0)
+            {
+                //
+                // Dialog has not been created yet, use a default
+                //
+                vTitle.yTop = 20;
+            }
+            vRect.yTop -= (vTitle.yTop - vTitle.yBottom);
+        }
+
+        ULONG                       uStyle = ::WinQueryWindowULong(hWnd, QWL_STYLE);
+
+        //
+        // Deal with borders
+        //
+        if (uStyle & FCF_DLGBORDER)
+        {
+            vRect.xLeft += 4;
+            vRect.xRight -= 4;
+            vRect.yTop -= 4;
+            vRect.yBottom += 4;
+        }
+        else if (uStyle & FCF_SIZEBORDER)
+        {
+            vRect.xLeft += 4;
+            vRect.xRight -= 4;
+            vRect.yTop -= 4;
+            vRect.yBottom += 4;
+        }
+        else if (uStyle & FCF_BORDER)
+        {
+            vRect.xLeft += 2;
+            vRect.xRight -= 2;
+            vRect.yTop -= 2;
+            vRect.yBottom += 2;
+        }
+        else // make some kind of adjustment or top sizers ram into the titlebar!
+        {
+            vRect.xLeft += 3;
+            vRect.xRight -= 3;
+            vRect.yTop -= 3;
+            vRect.yBottom += 3;
+        }
+    }
+    if (pWidth)
+        *pWidth  = vRect.xRight - vRect.xLeft;
+    if (pHeight)
+        *pHeight = vRect.yTop - vRect.yBottom;
+} // end of wxWindowOS2::DoGetClientSize
+
+void wxWindowOS2::DoMoveWindow(
+  int                               nX
+, int                               nY
+, int                               nWidth
+, int                               nHeight
+)
+{
+    //
+    // Input parameters assume wxWidgets coordinate system
+    //
+    RECTL                           vRect;
+    wxWindow*                       pParent = GetParent();
+    HWND                            hWnd = GetHwnd();
+
+    if (pParent && !IsKindOf(CLASSINFO(wxDialog)))
+    {
+        int                         nOS2Height = GetOS2ParentHeight(pParent);
+
+        nY = nOS2Height - (nY + nHeight);
+    }
+    else
+    {
+        RECTL                       vRect;
+
+        ::WinQueryWindowRect(HWND_DESKTOP, &vRect);
+        nY = vRect.yTop - (nY + nHeight);
+    }
+
+    //
+    // In the case of a frame whose client is sized, the client cannot be
+    // large than its parent frame minus its borders! This usually happens
+    // when using an autosizer to size a frame to precisely hold client
+    // controls as in the notebook sample.
+    //
+    // In this case, we may need to resize both a frame and its client so we
+    // need a quick calc of the frame border size, then if the frame
+    // (less its borders) is smaller than the client, size the frame to
+    // encompass the client with the appropriate border size.
+    //
+    if (IsKindOf(CLASSINFO(wxFrame)))
+    {
+        RECTL                       vFRect;
+        int                         nWidthFrameDelta = 0;
+        int                         nHeightFrameDelta = 0;
+        wxFrame*                    pFrame;
+
+        pFrame = wxDynamicCast(this, wxFrame);
+        hWnd = pFrame->GetFrame();
+        ::WinQueryWindowRect(hWnd, &vRect);
+        ::WinMapWindowPoints(hWnd, HWND_DESKTOP, (PPOINTL)&vRect, 2);
+        vFRect = vRect;
+        ::WinCalcFrameRect(hWnd, &vRect, TRUE);
+        nWidthFrameDelta = ((vRect.xLeft - vFRect.xLeft) + (vFRect.xRight - vRect.xRight));
+        nHeightFrameDelta = ((vRect.yBottom - vFRect.yBottom) + (vFRect.yTop - vRect.yTop));
+        // Input values refer to the window position relative to its parent
+        // which may be the Desktop so we need to calculate
+        // the new frame values to keep the wxWidgets frame origin constant
+        nY -= nHeightFrameDelta;
+        nWidth += nWidthFrameDelta;
+        nHeight += nHeightFrameDelta;
+    }
+    ::WinSetWindowPos( hWnd
+                      ,HWND_TOP
+                      ,(LONG)nX
+                      ,(LONG)nY
+                      ,(LONG)nWidth
+                      ,(LONG)nHeight
+                      ,SWP_SIZE | SWP_MOVE
+                     );
+    if (m_vWinSwp.cx == 0 && m_vWinSwp.cy == 0 && m_vWinSwp.fl == 0)
+        //
+        // Uninitialized
+        //
+        ::WinQueryWindowPos(hWnd, &m_vWinSwp);
+    else
+    {
+        //
+        // Handle resizing of scrolled windows.  The target or window to
+        // be scrolled is the owner (gets the scroll notifications).  The
+        // parent is usually the parent frame of the scrolled panel window.
+        // In order to show the scrollbars the target window will be shrunk
+        // by the size of the scroll bar widths and moved in the X and Y
+        // directon.  That value will be computed as part of the diff for
+        // moving the children.  Everytime the window is sized the
+        // toplevel OnSize is going to resize the panel to fit the client
+        // or the whole sizer and will need to me resized. This will send
+        // a WM_SIZE out which will be intercepted by the ScrollHelper
+        // which will cause the scrollbars to be displayed via the SetScrollbar
+        // call in CWindow.
+        //
+        if (IsKindOf(CLASSINFO(wxScrolledWindow)))
+        {
+            int                     nAdjustWidth  = 0;
+            int                     nAdjustHeight = 0;
+            int nHSBHeight = wxSystemSettingsNative::GetMetric(wxSYS_HSCROLL_Y,
+                                                               this);
+            int nVSBWidth  = wxSystemSettingsNative::GetMetric(wxSYS_VSCROLL_X,
+                                                               this);
+            SWP                     vSwpScroll;
+
+            if (GetScrollBarHorz() == NULLHANDLE ||
+                !WinIsWindowShowing(GetScrollBarHorz()))
+                nAdjustHeight = 0L;
+            else
+                nAdjustHeight = nHSBHeight;
+            if (GetScrollBarVert() == NULLHANDLE ||
+                !WinIsWindowShowing(GetScrollBarVert()))
+                nAdjustWidth = 0L;
+            else
+                nAdjustWidth = nVSBWidth;
+            ::WinQueryWindowPos(hWnd, &vSwpScroll);
+            ::WinSetWindowPos( hWnd
+                              ,HWND_TOP
+                              ,vSwpScroll.x
+                              ,vSwpScroll.y + nAdjustHeight
+                              ,vSwpScroll.cx - nAdjustWidth
+                              ,vSwpScroll.cy - nAdjustHeight
+                              ,SWP_MOVE | SWP_SIZE
+                             );
+        }
+        ::WinQueryWindowPos(hWnd, &m_vWinSwp);
+    }
+} // end of wxWindowOS2::DoMoveWindow
+
+//
+// Set the size of the window: if the dimensions are positive, just use them,
+// but if any of them is equal to -1, it means that we must find the value for
+// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
+// which case -1 is a valid value for x and y)
+//
+// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
+// the width/height to best suit our contents, otherwise we reuse the current
+// width/height
+//
+void wxWindowOS2::DoSetSize( int nX,
+                             int nY,
+                             int nWidth,
+                             int nHeight,
+                             int nSizeFlags )
+{
+    //
+    // Input & output parameters assume wxWidgets coordinate system
+    //
+
+    //
+    // Get the current size and position...
+    //
+    int    nCurrentX;
+    int    nCurrentY;
+    int    nCurrentWidth;
+    int    nCurrentHeight;
+    wxSize vSize = wxDefaultSize;
+
+    GetPosition(&nCurrentX, &nCurrentY);
+    GetSize(&nCurrentWidth, &nCurrentHeight);
+
+    //
+    // ... and don't do anything (avoiding flicker) if it's already ok
+    //
+    if (nX == nCurrentX && nY == nCurrentY &&
+        nWidth == nCurrentWidth && nHeight == nCurrentHeight)
+    {
+        return;
+    }
+
+    if (nX == wxDefaultCoord && !(nSizeFlags & wxSIZE_ALLOW_MINUS_ONE))
+        nX = nCurrentX;
+    if (nY == wxDefaultCoord && !(nSizeFlags & wxSIZE_ALLOW_MINUS_ONE))
+        nY = nCurrentY;
+
+    AdjustForParentClientOrigin(nX, nY, nSizeFlags);
+
+    if (nWidth == wxDefaultCoord)
+    {
+        if (nSizeFlags & wxSIZE_AUTO_WIDTH)
+        {
+            vSize  = DoGetBestSize();
+            nWidth = vSize.x;
+        }
+        else
+        {
+            //
+            // Just take the current one
+            //
+            nWidth = nCurrentWidth;
+        }
+    }
+
+    if (nHeight == wxDefaultCoord)
+    {
+        if (nSizeFlags & wxSIZE_AUTO_HEIGHT)
+        {
+            if (vSize.x == wxDefaultCoord)
+            {
+                vSize = DoGetBestSize();
+            }
+            nHeight = vSize.y;
+        }
+        else
+        {
+            // just take the current one
+            nHeight = nCurrentHeight;
+        }
+    }
+
+    DoMoveWindow( nX, nY, nWidth, nHeight );
+} // end of wxWindowOS2::DoSetSize
+
+void wxWindowOS2::DoSetClientSize( int nWidth,
+                                   int nHeight )
+{
+    //
+    // nX & nY assume wxWidgets coordinate system
+    //
+    int nX;
+    int nY;
+
+    GetPosition(&nX, &nY);
+
+    DoMoveWindow( nX, nY, nWidth, nHeight );
+
+    wxSize size( nWidth, nHeight );
+    wxSizeEvent vEvent( size, m_windowId );
+    vEvent.SetEventObject(this);
+    HandleWindowEvent(vEvent);
+} // end of wxWindowOS2::DoSetClientSize
+
+// ---------------------------------------------------------------------------
+// text metrics
+// ---------------------------------------------------------------------------
+
+int wxWindowOS2::GetCharHeight() const
+{
+    HPS                             hPs;
+    FONTMETRICS                     vFontMetrics;
+
+    hPs = ::WinGetPS(GetHwnd());
+
+    if(!GpiQueryFontMetrics(hPs, sizeof(FONTMETRICS), &vFontMetrics))
+    {
+        ::WinReleasePS(hPs);
+        return (0);
+    }
+    ::WinReleasePS(hPs);
+    return(vFontMetrics.lMaxAscender + vFontMetrics.lMaxDescender);
+} // end of wxWindowOS2::GetCharHeight
+
+int wxWindowOS2::GetCharWidth() const
+{
+    HPS                             hPs;
+    FONTMETRICS                     vFontMetrics;
+
+    hPs = ::WinGetPS(GetHwnd());
+
+    if(!GpiQueryFontMetrics(hPs, sizeof(FONTMETRICS), &vFontMetrics))
+    {
+        ::WinReleasePS(hPs);
+        return (0);
+    }
+    ::WinReleasePS(hPs);
+    return(vFontMetrics.lAveCharWidth);
+} // end of wxWindowOS2::GetCharWidth
+
+void wxWindowOS2::GetTextExtent( const wxString& rString,
+                                 int* pX,
+                                 int* pY,
+                                 int* pDescent,
+                                 int* pExternalLeading,
+                                 const wxFont* WXUNUSED(pTheFont) ) const
+{
+    POINTL      avPoint[TXTBOX_COUNT];
+    POINTL      vPtMin;
+    POINTL      vPtMax;
+    int         i;
+    int         l;
+    FONTMETRICS vFM; // metrics structure
+    BOOL        bRc = FALSE;
+    HPS         hPS;
+
+    hPS = ::WinGetPS(GetHwnd());
+
+    l = rString.length();
+    if (l > 0L)
+    {
+        //
+        // In world coordinates.
+        //
+        bRc = ::GpiQueryTextBox( hPS,
+                                 l,
+                                 (char*) rString.wx_str(),
+                                 TXTBOX_COUNT,// return maximum information
+                                 avPoint      // array of coordinates points
+                                );
+        if (bRc)
+        {
+            vPtMin.x = avPoint[0].x;
+            vPtMax.x = avPoint[0].x;
+            vPtMin.y = avPoint[0].y;
+            vPtMax.y = avPoint[0].y;
+            for (i = 1; i < 4; i++)
+            {
+                if(vPtMin.x > avPoint[i].x) vPtMin.x = avPoint[i].x;
+                if(vPtMin.y > avPoint[i].y) vPtMin.y = avPoint[i].y;
+                if(vPtMax.x < avPoint[i].x) vPtMax.x = avPoint[i].x;
+                if(vPtMax.y < avPoint[i].y) vPtMax.y = avPoint[i].y;
+            }
+            bRc = ::GpiQueryFontMetrics( hPS
+                                        ,sizeof(FONTMETRICS)
+                                        ,&vFM
+                                       );
+            if (!bRc)
+            {
+                vPtMin.x = 0;
+                vPtMin.y = 0;
+                vPtMax.x = 0;
+                vPtMax.y = 0;
+            }
+        }
+        else
+        {
+            vPtMin.x = 0;
+            vPtMin.y = 0;
+            vPtMax.x = 0;
+            vPtMax.y = 0;
+        }
+    }
+    else
+    {
+        vPtMin.x = 0;
+        vPtMin.y = 0;
+        vPtMax.x = 0;
+        vPtMax.y = 0;
+    }
+    if (pX)
+        *pX = (vPtMax.x - vPtMin.x + 1);
+    if (pY)
+        *pY = (vPtMax.y - vPtMin.y + 1);
+    if (pDescent)
+    {
+        if (bRc)
+            *pDescent = vFM.lMaxDescender;
+        else
+            *pDescent = 0;
+    }
+    if (pExternalLeading)
+    {
+        if (bRc)
+            *pExternalLeading = vFM.lExternalLeading;
+        else
+            *pExternalLeading = 0;
+    }
+    ::WinReleasePS(hPS);
+} // end of wxWindow::GetTextExtent
+
+bool wxWindowOS2::IsMouseInWindow() const
+{
+    //
+    // Get the mouse position
+    POINTL vPt;
+
+    ::WinQueryPointerPos(HWND_DESKTOP, &vPt);
+
+    //
+    // Find the window which currently has the cursor and go up the window
+    // chain until we find this window - or exhaust it
+    //
+    HWND hWnd = ::WinWindowFromPoint(HWND_DESKTOP, &vPt, TRUE);
+
+    while (hWnd && (hWnd != GetHwnd()))
+        hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
+
+    return hWnd != NULL;
+} // end of wxWindowOS2::IsMouseInWindow
+
+
+// ---------------------------------------------------------------------------
+// popup menu
+// ---------------------------------------------------------------------------
+//
+#if wxUSE_MENUS_NATIVE
+bool wxWindowOS2::DoPopupMenu( wxMenu* pMenu, int nX, int nY )
+{
+    HWND hWndOwner = GetHwnd();
+    HWND hWndParent = GetHwnd();
+    HWND hMenu = GetHmenuOf(pMenu);
+    bool bIsWaiting = true;
+    int nHeight;
+
+    pMenu->SetInvokingWindow(this);
+    pMenu->UpdateUI();
+
+    if ( nX == -1 && nY == -1 )
+    {
+        wxPoint mouse = wxGetMousePosition();
+        nX = mouse.x; nY = mouse.y;
+    }
+    else
+    {
+        DoClientToScreen( &nX
+                         ,&nY
+                        );
+        DoGetSize(0,&nHeight);
+        nY = nHeight - nY;
+    }
+
+    ::WinPopupMenu( hWndParent
+                   ,hWndOwner
+                   ,hMenu
+                   ,nX
+                   ,nY
+                   ,0L
+                   ,PU_HCONSTRAIN | PU_VCONSTRAIN | PU_MOUSEBUTTON1 | PU_KEYBOARD
+                  );
+
+    while(bIsWaiting)
+    {
+        QMSG                            vMsg;
+
+        ::WinGetMsg(vHabmain,&vMsg, (HWND)0, 0, 0);
+        if (vMsg.msg == WM_COMMAND)
+            bIsWaiting = false;
+        ::WinDispatchMsg(vHabmain, (PQMSG)&vMsg);
+    }
+
+    pMenu->SetInvokingWindow(NULL);
+    return true;
+} // end of wxWindowOS2::DoPopupMenu
+#endif // wxUSE_MENUS_NATIVE
+
+// ===========================================================================
+// pre/post message processing
+// ===========================================================================
+
+MRESULT wxWindowOS2::OS2DefWindowProc( WXUINT uMsg,
+                                       WXWPARAM wParam,
+                                       WXLPARAM lParam )
+{
+    if (m_fnOldWndProc)
+        return (MRESULT)m_fnOldWndProc(GetHWND(), uMsg, (MPARAM)wParam, (MPARAM)lParam);
+    else
+        return ::WinDefWindowProc(GetHWND(), uMsg, (MPARAM)wParam, (MPARAM)lParam);
+} // end of wxWindowOS2::OS2DefWindowProc
+
+bool wxWindowOS2::OS2ProcessMessage( WXMSG* pMsg )
+{
+// wxUniversal implements tab traversal itself
+#ifndef __WXUNIVERSAL__
+    QMSG*                           pQMsg = (QMSG*)pMsg;
+
+    if (m_hWnd != 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL))
+    {
+        //
+        // Intercept dialog navigation keys
+        //
+        bool   bProcess = true;
+        USHORT uKeyFlags = SHORT1FROMMP(pQMsg->mp1);
+
+        if (uKeyFlags & KC_KEYUP)
+            bProcess = false;
+
+        if (uKeyFlags & KC_ALT)
+            bProcess = false;
+
+        if (!(uKeyFlags & KC_VIRTUALKEY))
+            bProcess = false;
+
+        if (bProcess)
+        {
+            bool                    bCtrlDown = IsCtrlDown();
+            bool                    bShiftDown = IsShiftDown();
+
+            //
+            // WM_QUERYDLGCODE: ask the control if it wants the key for itself,
+            // don't process it if it's the case (except for Ctrl-Tab/Enter
+            // combinations which are always processed)
+            //
+            ULONG                   ulDlgCode = 0;
+
+            if (!bCtrlDown)
+            {
+                ulDlgCode = (ULONG)::WinSendMsg(pQMsg->hwnd, WM_QUERYDLGCODE, pQMsg, 0);
+            }
+
+            bool bForward = true;
+            bool bWindowChange = false;
+
+            switch (SHORT2FROMMP(pQMsg->mp2))
+            {
+                //
+                // Going to make certain assumptions about specific types of controls
+                // here, so we may have to alter some things later if they prove invalid
+                //
+                case VK_TAB:
+                    //
+                    // Shift tabl will always be a nav-key but tabs may be wanted
+                    //
+                    if (!bShiftDown)
+                    {
+                        bProcess = false;
+                    }
+                    else
+                    {
+                        //
+                        // Entry Fields want tabs for themselve usually
+                        //
+                        switch (ulDlgCode)
+                        {
+                            case DLGC_ENTRYFIELD:
+                            case DLGC_MLE:
+                                bProcess = true;
+                                break;
+
+                            default:
+                                bProcess = false;
+                        }
+
+                        //
+                        // Ctrl-Tab cycles thru notebook pages
+                        //
+                        bWindowChange = bCtrlDown;
+                        bForward = !bShiftDown;
+                    }
+                    break;
+
+                case VK_UP:
+                case VK_LEFT:
+                    if (bCtrlDown)
+                        bProcess = false;
+                    else
+                        bForward = false;
+                    break;
+
+                case VK_DOWN:
+                case VK_RIGHT:
+                    if (bCtrlDown)
+                        bProcess = false;
+                    break;
+
+                case VK_ENTER:
+                    {
+                        if (bCtrlDown)
+                        {
+                            //
+                            // ctrl-enter is not processed
+                            //
+                            return false;
+                        }
+                        else if (ulDlgCode & DLGC_BUTTON)
+                        {
+                            //
+                            // buttons want process Enter themselevs
+                            //
+                            bProcess = false;
+                        }
+                        else
+                        {
+                            wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow);
+                            wxButton*   pBtn = NULL;
+
+                            if (tlw)
+                            {
+                                pBtn = wxDynamicCast(tlw->GetDefaultItem(), wxButton);
+                            }
+
+                            if (pBtn && pBtn->IsEnabled())
+                            {
+                                //
+                                // If we do have a default button, do press it
+                                //
+                                pBtn->OS2Command(BN_CLICKED, 0 /* unused */);
+                                return true;
+                            }
+                            else if (!IsTopLevel())
+                            {
+                                //
+                                // if not a top level window, let parent
+                                // handle it
+                                //
+                                return false;
+                            }
+                            // else: but if it does not it makes sense to make
+                            //       it work like a TAB - and that's what we do.
+                            //       Note that Ctrl-Enter always works this way.
+                        }
+                    }
+                    break;
+
+                default:
+                    bProcess = false;
+            }
+
+            if (bProcess)
+            {
+                wxNavigationKeyEvent    vEvent;
+
+                vEvent.SetDirection(bForward);
+                vEvent.SetWindowChange(bWindowChange);
+                vEvent.SetEventObject(this);
+
+                if (HandleWindowEvent(vEvent))
+                {
+                    wxButton*       pBtn = wxDynamicCast(FindFocus(), wxButton);
+
+                    if (pBtn)
+                    {
+                        //
+                        // The button which has focus should be default
+                        //
+                        pBtn->SetDefault();
+                    }
+                    return true;
+                }
+            }
+        }
+        //
+        // Let Dialogs process
+        //
+        if (::WinSendMsg(pQMsg->hwnd, WM_QUERYDLGCODE, pQMsg, 0));
+            return true;
+    }
+#else
+    pMsg = pMsg; // just shut up the compiler
+#endif // __WXUNIVERSAL__
+
+    return false;
+} // end of wxWindowOS2::OS2ProcessMessage
+
+bool wxWindowOS2::OS2TranslateMessage( WXMSG* pMsg )
+{
+#if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
+    return m_acceleratorTable.Translate(m_hWnd, pMsg);
+#else
+    pMsg = pMsg;
+    return false;
+#endif //wxUSE_ACCEL
+} // end of wxWindowOS2::OS2TranslateMessage
+
+bool wxWindowOS2::OS2ShouldPreProcessMessage( WXMSG* WXUNUSED(pMsg) )
+{
+    // preprocess all messages by default
+    return true;
+} // end of wxWindowOS2::OS2ShouldPreProcessMessage
+
+// ---------------------------------------------------------------------------
+// message params unpackers
+// ---------------------------------------------------------------------------
+
+void wxWindowOS2::UnpackCommand(
+  WXWPARAM                          wParam
+, WXLPARAM                          lParam
+, WORD*                             pId
+, WXHWND*                           phWnd
+, WORD*                             pCmd
+)
+{
+    *pId = LOWORD(wParam);
+    *phWnd = NULL;  // or may be GetHWND() ?
+    *pCmd = LOWORD(lParam);
+} // end of wxWindowOS2::UnpackCommand
+
+void wxWindowOS2::UnpackActivate(
+  WXWPARAM                          wParam
+, WXLPARAM                          lParam
+, WXWORD*                           pState
+, WXHWND*                           phWnd
+)
+{
+    *pState     = LOWORD(wParam);
+    *phWnd      = (WXHWND)lParam;
+} // end of wxWindowOS2::UnpackActivate
+
+void wxWindowOS2::UnpackScroll(
+  WXWPARAM                          wParam
+, WXLPARAM                          lParam
+, WXWORD*                           pCode
+, WXWORD*                           pPos
+, WXHWND*                           phWnd
+)
+{
+    ULONG                           ulId;
+    HWND                            hWnd;
+
+    ulId    = (ULONG)LONGFROMMP(wParam);
+    hWnd = ::WinWindowFromID(GetHwnd(), ulId);
+    if (hWnd == m_hWndScrollBarHorz || hWnd == m_hWndScrollBarVert)
+        *phWnd = NULLHANDLE;
+    else
+        *phWnd = hWnd;
+
+    *pPos  = SHORT1FROMMP(lParam);
+    *pCode = SHORT2FROMMP(lParam);
+} // end of wxWindowOS2::UnpackScroll
+
+void wxWindowOS2::UnpackMenuSelect(
+  WXWPARAM                          wParam
+, WXLPARAM                          lParam
+, WXWORD*                           pItem
+, WXWORD*                           pFlags
+, WXHMENU*                          phMenu
+)
+{
+    *pItem = (WXWORD)LOWORD(wParam);
+    *pFlags = HIWORD(wParam);
+    *phMenu = (WXHMENU)lParam;
+} // end of wxWindowOS2::UnpackMenuSelect
+
+// ---------------------------------------------------------------------------
+// Main wxWidgets window proc and the window proc for wxWindow
+// ---------------------------------------------------------------------------
+
+//
+// Hook for new window just as it's being created, when the window isn't yet
+// associated with the handle
+//
+wxWindowOS2*                         wxWndHook = NULL;
+
+//
+// Main window proc
+//
+MRESULT EXPENTRY wxWndProc(
+  HWND                              hWnd
+, ULONG                             ulMsg
+, MPARAM                            wParam
+, MPARAM                            lParam
+)
+{
+    wxWindowOS2*                    pWnd = wxFindWinFromHandle((WXHWND)hWnd);
+
+    //
+    // When we get the first message for the HWND we just created, we associate
+    // it with wxWindow stored in wxWndHook
+    //
+    if (!pWnd && wxWndHook)
+    {
+        wxAssociateWinWithHandle(hWnd, wxWndHook);
+        pWnd = wxWndHook;
+        wxWndHook = NULL;
+        pWnd->SetHWND((WXHWND)hWnd);
+    }
+
+    MRESULT                         rc = (MRESULT)0;
+
+
+    //
+    // Stop right here if we don't have a valid handle in our wxWindow object.
+    //
+    if (pWnd && !pWnd->GetHWND())
+    {
+        pWnd->SetHWND((WXHWND) hWnd);
+        rc = pWnd->OS2DefWindowProc(ulMsg, wParam, lParam );
+        pWnd->SetHWND(0);
+    }
+    else
+    {
+        if (pWnd)
+        {
+            rc = pWnd->OS2WindowProc(ulMsg, wParam, lParam);
+            if ( (pWnd->GetScrollBarHorz() != NULLHANDLE ||
+                  pWnd->GetScrollBarVert() != NULLHANDLE) &&
+                  ulMsg == WM_PAINT)
+            {
+                if (pWnd->GetScrollBarHorz() != NULLHANDLE)
+                    ::WinInvalidateRect(pWnd->GetScrollBarHorz(), NULL, TRUE);
+                if (pWnd->GetScrollBarVert() != NULLHANDLE)
+                    ::WinInvalidateRect(pWnd->GetScrollBarVert(), NULL, TRUE);
+            }
+        }
+        else
+            rc = ::WinDefWindowProc(hWnd, ulMsg, wParam, lParam);
+    }
+
+    return rc;
+} // end of wxWndProc
+
+//
+// We will add (or delete) messages we need to handle at this default
+// level as we go
+//
+MRESULT wxWindowOS2::OS2WindowProc( WXUINT uMsg,
+                                    WXWPARAM wParam,
+                                    WXLPARAM lParam )
+{
+    //
+    // Did we process the uMsg?
+    //
+    bool bProcessed = false;
+    MRESULT mResult;
+
+    //
+    // For most messages we should return 0 when we do process the message
+    //
+    mResult = (MRESULT)0;
+
+    switch (uMsg)
+    {
+        case WM_CREATE:
+            {
+                bool                bMayCreate;
+
+                bProcessed = HandleCreate( (WXLPCREATESTRUCT)lParam
+                                          ,&bMayCreate
+                                         );
+                if (bProcessed)
+                {
+                    //
+                    // Return 0 to bAllow window creation
+                    //
+                    mResult = (MRESULT)(bMayCreate ? 0 : -1);
+                }
+            }
+            break;
+
+        case WM_DESTROY:
+             HandleDestroy();
+             bProcessed = true;
+             break;
+
+        case WM_MOVE:
+            bProcessed = HandleMove( LOWORD(lParam)
+                                    ,HIWORD(lParam)
+                                   );
+            break;
+
+        case WM_SIZE:
+            bProcessed = HandleSize( LOWORD(lParam)
+                                    ,HIWORD(lParam)
+                                    ,(WXUINT)wParam
+                                   );
+            break;
+
+        case WM_WINDOWPOSCHANGED:
+
+            //
+            // Dialogs under OS/2 do not get WM_SIZE events at all.
+            // Instead they get this, which can function much like WM_SIZE
+            // PSWP contains the new sizes and positioning, PSWP+1 the old
+            // We use this because ADJUSTWINDOWPOS comes BEFORE the new
+            // position is added and our auto layout does a WinQueryWindowRect
+            // to get the CURRENT client size.  That is the size used to position
+            // child controls, so we need to already be sized
+            // in order to get the child controls positoned properly.
+            //
+            if (IsKindOf(CLASSINFO(wxDialog)) || IsKindOf(CLASSINFO(wxFrame)))
+            {
+                PSWP                pSwp = (PSWP)PVOIDFROMMP(wParam);
+                PSWP                pSwp2 = pSwp++;
+
+                if (!(pSwp->cx == pSwp2->cx &&
+                      pSwp->cy == pSwp2->cy))
+                    bProcessed = HandleSize( pSwp->cx
+                                            ,pSwp->cy
+                                            ,(WXUINT)lParam
+                                           );
+                if (IsKindOf(CLASSINFO(wxFrame)))
+                {
+                    wxFrame*            pFrame = wxDynamicCast(this, wxFrame);
+
+                    if (pFrame)
+                    {
+                        if (pFrame->GetStatusBar())
+                            pFrame->PositionStatusBar();
+                        if (pFrame->GetToolBar())
+                            pFrame->PositionToolBar();
+                    }
+                }
+            }
+            break;
+
+        case WM_ACTIVATE:
+            {
+                WXWORD              wState;
+                WXHWND              hWnd;
+
+                UnpackActivate( wParam
+                               ,lParam
+                               ,&wState
+                               ,&hWnd
+                              );
+
+                bProcessed = HandleActivate( wState
+                                            ,(WXHWND)hWnd
+                                           );
+                bProcessed = false;
+            }
+            break;
+
+        case WM_SETFOCUS:
+            if (SHORT1FROMMP((MPARAM)lParam) == TRUE)
+                bProcessed = HandleSetFocus((WXHWND)(HWND)wParam);
+            else
+                bProcessed = HandleKillFocus((WXHWND)(HWND)wParam);
+            break;
+
+        case WM_PAINT:
+            bProcessed = HandlePaint();
+            break;
+
+        case WM_CLOSE:
+            //
+            // Don't let the DefWindowProc() destroy our window - we'll do it
+            // ourselves in ~wxWindow
+            //
+            bProcessed = true;
+            mResult = (MRESULT)TRUE;
+            break;
+
+        case WM_SHOW:
+            bProcessed = HandleShow(wParam != 0, (int)lParam);
+            break;
+
+        //
+        // Under OS2 PM Joysticks are treated just like mouse events
+        // The "Motion" events will be prevelent in joysticks
+        //
+        case WM_MOUSEMOVE:
+        case WM_BUTTON1DOWN:
+        case WM_BUTTON1UP:
+        case WM_BUTTON1DBLCLK:
+        case WM_BUTTON1MOTIONEND:
+        case WM_BUTTON1MOTIONSTART:
+        case WM_BUTTON2DOWN:
+        case WM_BUTTON2UP:
+        case WM_BUTTON2DBLCLK:
+        case WM_BUTTON2MOTIONEND:
+        case WM_BUTTON2MOTIONSTART:
+        case WM_BUTTON3DOWN:
+        case WM_BUTTON3UP:
+        case WM_BUTTON3DBLCLK:
+        case WM_BUTTON3MOTIONEND:
+        case WM_BUTTON3MOTIONSTART:
+            {
+                short               nX = LOWORD(wParam);
+                short               nY = HIWORD(wParam);
+
+                //
+                // Redirect the event to a static control if necessary
+                //
+                if (this == GetCapture())
+                {
+                    bProcessed = HandleMouseEvent( uMsg
+                                                  ,nX
+                                                  ,nY
+                                                  ,(WXUINT)SHORT2FROMMP(lParam)
+                                                 );
+                }
+                else
+                {
+                    wxWindow*       pWin = FindWindowForMouseEvent( this
+                                                                   ,&nX
+                                                                   ,&nY
+                                                                  );
+                    if (!pWin->IsOfStandardClass())
+                    {
+                        if (uMsg == WM_BUTTON1DOWN && pWin->CanAcceptFocus() )
+                            pWin->SetFocus();
+                    }
+                    bProcessed = pWin->HandleMouseEvent( uMsg
+                                                        ,nX
+                                                        ,nY
+                                                        ,(WXUINT)SHORT2FROMMP(lParam)
+                                                       );
+                }
+            }
+            break;
+
+        case WM_SYSCOMMAND:
+            bProcessed = HandleSysCommand(wParam, lParam);
+            break;
+
+        case WM_COMMAND:
+            {
+                WORD id, cmd;
+                WXHWND hwnd;
+                UnpackCommand(wParam, lParam, &id, &hwnd, &cmd);
+
+                bProcessed = HandleCommand(id, cmd, hwnd);
+            }
+            break;
+
+            //
+            // For these messages we must return TRUE if process the message
+            //
+        case WM_DRAWITEM:
+        case WM_MEASUREITEM:
+            {
+                int                 nIdCtrl = (UINT)wParam;
+
+                if ( uMsg == WM_DRAWITEM )
+                {
+                    bProcessed = OS2OnDrawItem(nIdCtrl,
+                                              (WXDRAWITEMSTRUCT *)lParam);
+                }
+                else
+                {
+                    return MRFROMLONG(OS2OnMeasureItem( nIdCtrl
+                                                       ,(WXMEASUREITEMSTRUCT *)lParam
+                                                      ));
+                }
+
+                if ( bProcessed )
+                    mResult = (MRESULT)TRUE;
+            }
+            break;
+
+        case WM_QUERYDLGCODE:
+            if (!IsOfStandardClass())
+            {
+                if ( m_lDlgCode )
+                {
+                    mResult = (MRESULT)m_lDlgCode;
+                    bProcessed = true;
+                }
+            }
+            //
+            //else: get the dlg code from the DefWindowProc()
+            //
+            break;
+
+        //
+        // In OS/2 PM all keyboard events are of the WM_CHAR type.  Virtual key and key-up
+        // and key-down events are obtained from the WM_CHAR params.
+        //
+        case WM_CHAR:
+            {
+                USHORT                  uKeyFlags = SHORT1FROMMP((MPARAM)wParam);
+
+                if (uKeyFlags & KC_KEYUP)
+                {
+                    //TODO: check if the cast to WXWORD isn't causing trouble
+                    bProcessed = HandleKeyUp(wParam, lParam);
+                    break;
+                }
+                else // keydown event
+                {
+                    m_bLastKeydownProcessed = false;
+                    //
+                    // If this has been processed by an event handler,
+                    // return 0 now (we've handled it). DON't RETURN
+                    // we still need to process further
+                    //
+                    m_bLastKeydownProcessed = HandleKeyDown(wParam, lParam);
+                    if (uKeyFlags & KC_VIRTUALKEY)
+                    {
+                        USHORT          uVk = SHORT2FROMMP((MPARAM)lParam);
+
+                        //
+                        // We consider these message "not interesting" to OnChar
+                        //
+                        switch(uVk)
+                        {
+                            case VK_SHIFT:
+                            case VK_CTRL:
+                            case VK_MENU:
+                            case VK_CAPSLOCK:
+                            case VK_NUMLOCK:
+                            case VK_SCRLLOCK:
+                                bProcessed = true;
+                                break;
+
+                            // Avoid duplicate messages to OnChar for these ASCII keys: they
+                            // will be translated by TranslateMessage() and received in WM_CHAR
+                            case VK_ESC:
+                            case VK_ENTER:
+                            case VK_BACKSPACE:
+                            case VK_TAB:
+                                // But set processed to false, not true to still pass them to
+                                // the control's default window proc - otherwise built-in
+                                // keyboard handling won't work
+                                bProcessed = false;
+                                break;
+
+                            default:
+                                bProcessed = HandleChar(wParam, lParam);
+                         }
+                         break;
+                    }
+                    else // WM_CHAR -- Always an ASCII character
+                    {
+                        if (m_bLastKeydownProcessed)
+                        {
+                            //
+                            // The key was handled in the EVT_KEY_DOWN and handling
+                            // a key in an EVT_KEY_DOWN handler is meant, by
+                            // design, to prevent EVT_CHARs from happening
+                            //
+                            m_bLastKeydownProcessed = false;
+                            bProcessed = true;
+                        }
+                        else // do generate a CHAR event
+                        {
+                            bProcessed = HandleChar(wParam, lParam, true);
+                            break;
+                        }
+                    }
+                }
+            }
+
+        case WM_HSCROLL:
+        case WM_VSCROLL:
+            {
+                WXWORD              wCode;
+                WXWORD              wPos;
+                WXHWND              hWnd;
+                UnpackScroll( wParam
+                             ,lParam
+                             ,&wCode
+                             ,&wPos
+                             ,&hWnd
+                            );
+
+                bProcessed = OS2OnScroll( uMsg == WM_HSCROLL ? wxHORIZONTAL
+                                                             : wxVERTICAL
+                                         ,wCode
+                                         ,wPos
+                                         ,hWnd
+                                        );
+            }
+            break;
+
+        case WM_CONTROL:
+            switch(SHORT2FROMMP(wParam))
+            {
+                case BN_PAINT:
+                    {
+                        HWND                hWnd = ::WinWindowFromID((HWND)GetHwnd(), SHORT1FROMMP(wParam));
+                        wxWindowOS2*        pWin = wxFindWinFromHandle(hWnd);
+
+                        if (!pWin)
+                        {
+                            bProcessed = false;
+                            break;
+                        }
+                        if (pWin->IsKindOf(CLASSINFO(wxBitmapButton)))
+                        {
+                            wxBitmapButton*     pBitmapButton = wxDynamicCast(pWin, wxBitmapButton);
+
+                            pBitmapButton->OS2OnDraw((WXDRAWITEMSTRUCT *)lParam);
+                        }
+                        return 0;
+                    }
+                    // break;
+
+                case BKN_PAGESELECTEDPENDING:
+                    {
+                        PPAGESELECTNOTIFY  pPage = (PPAGESELECTNOTIFY)lParam;
+
+                        if ((pPage->ulPageIdNew != pPage->ulPageIdCur) &&
+                            (pPage->ulPageIdNew > 0L && pPage->ulPageIdCur > 0L))
+                        {
+                            wxWindowOS2*        pWin = wxFindWinFromHandle(pPage->hwndBook);
+                            wxNotebookEvent     vEvent( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED
+                                                       ,(int)SHORT1FROMMP(wParam)
+                                                       ,(int)pPage->ulPageIdNew
+                                                       ,(int)pPage->ulPageIdCur
+                                                      );
+                            if (!pWin)
+                            {
+                                bProcessed = false;
+                                break;
+                            }
+                            if (pWin->IsKindOf(CLASSINFO(wxNotebook)))
+                            {
+                                wxNotebook*         pNotebook = wxDynamicCast(pWin, wxNotebook);
+
+                                vEvent.SetEventObject(pWin);
+                                pNotebook->OnSelChange(vEvent);
+                                bProcessed = true;
+                            }
+                            else
+                                bProcessed = false;
+                        }
+                        else
+                            bProcessed = false;
+                    }
+                    break;
+
+                case CBN_LBSELECT:
+                case BN_CLICKED: // Dups as LN_SELECT and CBN_LBSELECT
+                    {
+                        HWND                hWnd = ::WinWindowFromID((HWND)GetHwnd(), SHORT1FROMMP(wParam));
+                        wxWindowOS2*        pWin = wxFindWinFromHandle(hWnd);
+
+                        if (!pWin)
+                        {
+                            bProcessed = false;
+                            break;
+                        }
+                        //
+                        // Simulate a WM_COMMAND here, as wxWidgets expects all control
+                        // button clicks to generate WM_COMMAND msgs, not WM_CONTROL
+                        //
+                        if (pWin->IsKindOf(CLASSINFO(wxRadioBox)))
+                        {
+                            wxRadioBox*         pRadioBox = wxDynamicCast(pWin, wxRadioBox);
+
+                            pRadioBox->OS2Command( (WXUINT)SHORT2FROMMP(wParam)
+                                                  ,(WXWORD)SHORT1FROMMP(wParam)
+                                                 );
+                        }
+                        if (pWin->IsKindOf(CLASSINFO(wxRadioButton)))
+                        {
+                            wxRadioButton*      pRadioButton = wxDynamicCast(pWin, wxRadioButton);
+
+                            pRadioButton->OS2Command( (WXUINT)SHORT2FROMMP(wParam)
+                                                     ,(WXWORD)SHORT1FROMMP(wParam)
+                                                    );
+                        }
+                        if (pWin->IsKindOf(CLASSINFO(wxCheckBox)))
+                        {
+                            wxCheckBox*         pCheckBox = wxDynamicCast(pWin, wxCheckBox);
+
+                            pCheckBox->OS2Command( (WXUINT)SHORT2FROMMP(wParam)
+                                                  ,(WXWORD)SHORT1FROMMP(wParam)
+                                                 );
+                        }
+                        if (pWin->IsKindOf(CLASSINFO(wxListBox)))
+                        {
+                            wxListBox*          pListBox = wxDynamicCast(pWin, wxListBox);
+
+                            pListBox->OS2Command( (WXUINT)SHORT2FROMMP(wParam)
+                                                 ,(WXWORD)SHORT1FROMMP(wParam)
+                                                );
+                            if (pListBox->GetWindowStyle() & wxLB_OWNERDRAW)
+                                Refresh();
+                        }
+                        if (pWin->IsKindOf(CLASSINFO(wxComboBox)))
+                        {
+                            wxComboBox*          pComboBox = wxDynamicCast(pWin, wxComboBox);
+
+                            pComboBox->OS2Command( (WXUINT)SHORT2FROMMP(wParam)
+                                                  ,(WXWORD)SHORT1FROMMP(wParam)
+                                                 );
+                        }
+                        if (pWin->IsKindOf(CLASSINFO(wxChoice)))
+                        {
+                            wxChoice*           pChoice = wxDynamicCast(pWin, wxChoice);
+
+                            pChoice->OS2Command( (WXUINT)SHORT2FROMMP(wParam)
+                                                ,(WXWORD)SHORT1FROMMP(wParam)
+                                               );
+                        }
+                        return 0;
+                    }
+                    // break;
+
+                case LN_ENTER:
+                    {
+                        HWND                hWnd = HWNDFROMMP(lParam);
+                        wxWindowOS2*        pWin = wxFindWinFromHandle(hWnd);
+
+                        if (!pWin)
+                        {
+                            bProcessed = false;
+                            break;
+                        }
+                        //
+                        // Simulate a WM_COMMAND here, as wxWidgets expects all control
+                        // button clicks to generate WM_COMMAND msgs, not WM_CONTROL
+                        //
+                        if (pWin->IsKindOf(CLASSINFO(wxListBox)))
+                        {
+                            wxListBox*          pListBox = wxDynamicCast(pWin, wxListBox);
+
+                            pListBox->OS2Command( (WXUINT)SHORT2FROMMP(wParam)
+                                                 ,(WXWORD)SHORT1FROMMP(wParam)
+                                                );
+                            if (pListBox->GetWindowStyle() & wxLB_OWNERDRAW)
+                                Refresh();
+
+                        }
+                        if (pWin->IsKindOf(CLASSINFO(wxComboBox)))
+                        {
+                            wxComboBox*          pComboBox = wxDynamicCast(pWin, wxComboBox);
+
+                            pComboBox->OS2Command( (WXUINT)SHORT2FROMMP(wParam)
+                                                  ,(WXWORD)SHORT1FROMMP(wParam)
+                                                 );
+                        }
+                        return 0;
+                    }
+                    // break;
+
+                case SPBN_UPARROW:
+                case SPBN_DOWNARROW:
+                case SPBN_CHANGE:
+                    {
+                        char zVal[10];
+                        long lVal;
+
+                        ::WinSendMsg( HWNDFROMMP(lParam)
+                                     ,SPBM_QUERYVALUE
+                                     ,&zVal[0]
+                                     ,MPFROM2SHORT( (USHORT)10
+                                                   ,(USHORT)SPBQ_UPDATEIFVALID
+                                                  )
+                                    );
+                        lVal = atol(zVal);
+                        bProcessed = OS2OnScroll( wxVERTICAL
+                                                 ,(WXWORD)SHORT2FROMMP(wParam)
+                                                 ,(WXWORD)lVal
+                                                 ,HWNDFROMMP(lParam)
+                                                );
+                    }
+                    break;
+
+                case SLN_SLIDERTRACK:
+                    {
+                        HWND         hWnd = ::WinWindowFromID(GetHWND(), SHORT1FROMMP(wParam));
+                        wxWindowOS2* pChild = wxFindWinFromHandle(hWnd);
+
+                        if (!pChild)
+                        {
+                            bProcessed = false;
+                            break;
+                        }
+                        if (pChild->IsKindOf(CLASSINFO(wxSlider)))
+                            bProcessed = OS2OnScroll( wxVERTICAL
+                                                     ,(WXWORD)SHORT2FROMMP(wParam)
+                                                     ,(WXWORD)LONGFROMMP(lParam)
+                                                     ,hWnd
+                                                    );
+                    }
+                    break;
+            }
+            break;
+
+#if defined(__VISAGECPP__) && (__IBMCPP__ >= 400)
+        case WM_CTLCOLORCHANGE:
+            {
+                bProcessed = HandleCtlColor(&hBrush);
+            }
+            break;
+#endif
+        case WM_ERASEBACKGROUND:
+            //
+            // Returning TRUE to requestw PM to paint the window background
+            // in SYSCLR_WINDOW. We don't really want that
+            //
+            bProcessed = HandleEraseBkgnd((WXHDC)(HPS)wParam);
+            mResult = (MRESULT)(FALSE);
+            break;
+
+            // the return value for this message is ignored
+        case WM_SYSCOLORCHANGE:
+            bProcessed = HandleSysColorChange();
+            break;
+
+        case WM_REALIZEPALETTE:
+            bProcessed = HandlePaletteChanged();
+            break;
+
+        // move all drag and drops to wxDrg
+        case WM_ENDDRAG:
+            bProcessed = HandleEndDrag(wParam);
+            break;
+
+        case WM_INITDLG:
+            bProcessed = HandleInitDialog((WXHWND)(HWND)wParam);
+
+            if ( bProcessed )
+            {
+                // we never set focus from here
+                mResult = (MRESULT)FALSE;
+            }
+            break;
+
+        // wxFrame specific message
+        case WM_MINMAXFRAME:
+            bProcessed = HandleGetMinMaxInfo((PSWP)wParam);
+            break;
+
+        case WM_SYSVALUECHANGED:
+            // TODO: do something
+            mResult = (MRESULT)TRUE;
+            break;
+
+        //
+        // Comparable to WM_SETPOINTER for windows, only for just controls
+        //
+        case WM_CONTROLPOINTER:
+            bProcessed = HandleSetCursor( SHORT1FROMMP(wParam) // Control ID
+                                         ,(HWND)lParam         // Cursor Handle
+                                        );
+            if (bProcessed )
+            {
+                //
+                // Returning TRUE stops the DefWindowProc() from further
+                // processing this message - exactly what we need because we've
+                // just set the cursor.
+                //
+                mResult = (MRESULT)TRUE;
+            }
+            break;
+
+#if wxUSE_MENUS_NATIVE
+         case WM_MENUEND:
+            if (wxCurrentPopupMenu)
+            {
+                if (GetHmenuOf(wxCurrentPopupMenu) == (HWND)lParam)
+                {
+                    // Break out of msg loop in DoPopupMenu
+                    ::WinPostMsg((HWND)lParam,WM_COMMAND,wParam,0);
+                }
+            }
+            break;
+#endif // wxUSE_MENUS_NATIVE
+
+    }
+    if (!bProcessed)
+    {
+#ifdef __WXDEBUG__
+        wxLogTrace(wxTraceMessages, wxT("Forwarding %s to DefWindowProc."),
+                   wxGetMessageName(uMsg));
+#endif // __WXDEBUG__
+        if (IsKindOf(CLASSINFO(wxFrame)))
+            mResult = ::WinDefWindowProc(m_hWnd, uMsg, wParam, lParam);
+        else if (IsKindOf(CLASSINFO(wxDialog)))
+            mResult = ::WinDefDlgProc( m_hWnd, uMsg, wParam, lParam);
+        else
+            mResult = OS2DefWindowProc(uMsg, wParam, lParam);
+    }
+    return mResult;
+} // end of wxWindowOS2::OS2WindowProc
+
+// ----------------------------------------------------------------------------
+// wxWindow <-> HWND map
+// ----------------------------------------------------------------------------
+
+wxWinHashTable *wxWinHandleHash = NULL;
+
+wxWindow* wxFindWinFromHandle(
+  WXHWND                            hWnd
+)
+{
+    return (wxWindow *)wxWinHandleHash->Get((long)hWnd);
+} // end of wxFindWinFromHandle
+
+void wxAssociateWinWithHandle(
+  HWND                              hWnd
+, wxWindowOS2*                      pWin
+)
+{
+    //
+    // Adding NULL hWnd is (first) surely a result of an error and
+    // (secondly) breaks menu command processing
+    //
+    wxCHECK_RET( hWnd != (HWND)NULL,
+                 wxT("attempt to add a NULL hWnd to window list ignored") );
+
+    wxWindow*                       pOldWin = wxFindWinFromHandle((WXHWND) hWnd);
+
+    if (pOldWin && (pOldWin != pWin))
+    {
+        wxString  Newstr(pWin->GetClassInfo()->GetClassName());
+        wxString Oldstr(pOldWin->GetClassInfo()->GetClassName());
+        wxLogError( _T("Bug! New window of class %s has same HWND %X as old window of class %s"),
+                    Newstr.c_str(),
+                    (int)hWnd,
+                    Oldstr.c_str()
+                  );
+    }
+    else if (!pOldWin)
+    {
+        wxWinHandleHash->Put( (long)hWnd
+                             ,(wxWindow *)pWin
+                            );
+    }
+} // end of wxAssociateWinWithHandle
+
+void wxRemoveHandleAssociation( wxWindowOS2* pWin )
+{
+    wxWinHandleHash->Delete((long)pWin->GetHWND());
+} // end of wxRemoveHandleAssociation
+
+//
+// Default destroyer - override if you destroy it in some other way
+// (e.g. with MDI child windows)
+//
+void wxWindowOS2::OS2DestroyWindow()
+{
+}
+
+bool wxWindowOS2::OS2GetCreateWindowCoords( const wxPoint& rPos,
+                                            const wxSize&  rSize,
+                                            int& rnX,
+                                            int& rnY,
+                                            int& rnWidth,
+                                            int& rnHeight ) const
+{
+    bool bNonDefault = false;
+    static const int DEFAULT_Y = 200;
+    static const int DEFAULT_H = 250;
+
+    if (rPos.x == wxDefaultCoord)
+    {
+        rnX = rnY = CW_USEDEFAULT;
+    }
+    else
+    {
+        rnX = rPos.x;
+        rnY = rPos.y == wxDefaultCoord ? DEFAULT_Y : rPos.y;
+        bNonDefault = true;
+    }
+    if (rSize.x == wxDefaultCoord)
+    {
+        rnWidth = rnHeight = CW_USEDEFAULT;
+    }
+    else
+    {
+        rnWidth  = rSize.x;
+        rnHeight = rSize.y == wxDefaultCoord ? DEFAULT_H : rSize.y;
+        bNonDefault = true;
+    }
+    return bNonDefault;
+} // end of wxWindowOS2::OS2GetCreateWindowCoords
+
+WXHWND wxWindowOS2::OS2GetParent() const
+{
+    return m_parent ? m_parent->GetHWND() : NULL;
+}
+
+bool wxWindowOS2::OS2Create( PSZ            zClass,
+                             const wxChar*  zTitle,
+                             WXDWORD        dwStyle,
+                             const wxPoint& rPos,
+                             const wxSize&  rSize,
+                             void*          pCtlData,
+                             WXDWORD        WXUNUSED(dwExStyle),
+                             bool           bIsChild )
+{
+    ERRORID              vError;
+    wxString             sError;
+    int                  nX      = 0L;
+    int                  nY      = 0L;
+    int                  nWidth  = 0L;
+    int                  nHeight = 0L;
+    long                 lControlId = 0L;
+    wxWindowCreationHook vHook(this);
+    wxString             sClassName((wxChar*)zClass);
+    wxString             sTitle(zTitle ? zTitle : wxEmptyString);
+
+    OS2GetCreateWindowCoords( rPos
+                             ,rSize
+                             ,nX
+                             ,nY
+                             ,nWidth
+                             ,nHeight
+                            );
+
+    if (bIsChild)
+    {
+        lControlId = GetId();
+        if (GetWindowStyleFlag() & wxCLIP_SIBLINGS)
+        {
+            dwStyle |= WS_CLIPSIBLINGS;
+        }
+    }
+    //
+    // For each class "Foo" we have we also have "FooNR" ("no repaint") class
+    // which is the same but without CS_[HV]REDRAW class styles so using it
+    // ensures that the window is not fully repainted on each resize
+    //
+    if (!HasFlag(wxFULL_REPAINT_ON_RESIZE))
+    {
+        sClassName += wxT("NR");
+    }
+    m_hWnd = (WXHWND)::WinCreateWindow( (HWND)OS2GetParent()
+                                       ,sClassName.c_str()
+                                       ,sTitle.c_str()
+                                       ,(ULONG)dwStyle
+                                       ,(LONG)0L
+                                       ,(LONG)0L
+                                       ,(LONG)0L
+                                       ,(LONG)0L
+                                       ,NULLHANDLE
+                                       ,HWND_TOP
+                                       ,(ULONG)lControlId
+                                       ,pCtlData
+                                       ,NULL
+                                      );
+    if (!m_hWnd)
+    {
+        vError = ::WinGetLastError(wxGetInstance());
+        sError = wxPMErrorToStr(vError);
+        return false;
+    }
+    SubclassWin(m_hWnd);
+    SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
+
+    SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
+
+    LONG lColor = (LONG)m_backgroundColour.GetPixel();
+
+    if (!::WinSetPresParam( m_hWnd
+                           ,PP_BACKGROUNDCOLOR
+                           ,sizeof(LONG)
+                           ,(PVOID)&lColor
+                          ))
+    {
+        vError = ::WinGetLastError(vHabmain);
+        sError = wxPMErrorToStr(vError);
+        wxLogError(_T("Error creating frame. Error: %s\n"), sError.c_str());
+        return false;
+    }
+    SetSize( nX
+            ,nY
+            ,nWidth
+            ,nHeight
+           );
+    return true;
+} // end of wxWindowOS2::OS2Create
+
+// ===========================================================================
+// OS2 PM message handlers
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// window creation/destruction
+// ---------------------------------------------------------------------------
+
+bool wxWindowOS2::HandleCreate( WXLPCREATESTRUCT WXUNUSED(vCs),
+                                bool* pbMayCreate )
+{
+    wxWindowCreateEvent             vEvent((wxWindow*)this);
+
+    (void)HandleWindowEvent(vEvent);
+    *pbMayCreate = true;
+    return true;
+} // end of wxWindowOS2::HandleCreate
+
+bool wxWindowOS2::HandleDestroy()
+{
+    wxWindowDestroyEvent            vEvent((wxWindow*)this);
+    vEvent.SetId(GetId());
+    (void)HandleWindowEvent(vEvent);
+
+    //
+    // Delete our drop target if we've got one
+    //
+#if wxUSE_DRAG_AND_DROP
+    if (m_dropTarget != NULL)
+    {
+        delete m_dropTarget;
+        m_dropTarget = NULL;
+    }
+#endif // wxUSE_DRAG_AND_DROP
+
+    //
+    // WM_DESTROY handled
+    //
+    return true;
+} // end of wxWindowOS2::HandleDestroy
+
+// ---------------------------------------------------------------------------
+// activation/focus
+// ---------------------------------------------------------------------------
+void wxWindowOS2::OnSetFocus(
+  wxFocusEvent&                     rEvent
+)
+{
+    rEvent.Skip();
+} // end of wxWindowOS2::OnSetFocus
+
+bool wxWindowOS2::HandleActivate(
+  int                               nState
+, WXHWND                            WXUNUSED(hActivate)
+)
+{
+    wxActivateEvent                 vEvent( wxEVT_ACTIVATE
+                                           ,(bool)nState
+                                           ,m_windowId
+                                          );
+    vEvent.SetEventObject(this);
+    return HandleWindowEvent(vEvent);
+} // end of wxWindowOS2::HandleActivate
+
+bool wxWindowOS2::HandleSetFocus( WXHWND WXUNUSED(hWnd) )
+{
+    //
+    // Notify the parent keeping track of focus for the kbd navigation
+    // purposes that we got it
+    //
+    wxChildFocusEvent               vEventFocus((wxWindow *)this);
+    (void)HandleWindowEvent(vEventFocus);
+
+#if wxUSE_CARET
+    //
+    // Deal with caret
+    //
+    if (m_caret)
+    {
+        m_caret->OnSetFocus();
+    }
+#endif // wxUSE_CARET
+
+#if wxUSE_TEXTCTRL
+    // If it's a wxTextCtrl don't send the event as it will be done
+    // after the control gets to process it from EN_FOCUS handler
+    if ( wxDynamicCastThis(wxTextCtrl) )
+    {
+        return false;
+    }
+#endif // wxUSE_TEXTCTRL
+
+    wxFocusEvent                    vEvent(wxEVT_SET_FOCUS, m_windowId);
+
+    vEvent.SetEventObject(this);
+    return HandleWindowEvent(vEvent);
+} // end of wxWindowOS2::HandleSetFocus
+
+bool wxWindowOS2::HandleKillFocus( WXHWND hWnd )
+{
+#if wxUSE_CARET
+    //
+    // Deal with caret
+    //
+    if (m_caret)
+    {
+        m_caret->OnKillFocus();
+    }
+#endif // wxUSE_CARET
+
+#if wxUSE_TEXTCTRL
+    //
+    // If it's a wxTextCtrl don't send the event as it will be done
+    // after the control gets to process it.
+    //
+    wxTextCtrl*                     pCtrl = wxDynamicCastThis(wxTextCtrl);
+
+    if (pCtrl)
+    {
+        return false;
+    }
+#endif
+
+    //
+    // Don't send the event when in the process of being deleted.  This can
+    // only cause problems if the event handler tries to access the object.
+    //
+    if ( m_isBeingDeleted )
+    {
+        return false;
+    }
+
+    wxFocusEvent                    vEvent( wxEVT_KILL_FOCUS
+                                           ,m_windowId
+                                          );
+
+    vEvent.SetEventObject(this);
+
+    //
+    // wxFindWinFromHandle() may return NULL, it is ok
+    //
+    vEvent.SetWindow(wxFindWinFromHandle(hWnd));
+    return HandleWindowEvent(vEvent);
+} // end of wxWindowOS2::HandleKillFocus
+
+// ---------------------------------------------------------------------------
+// miscellaneous
+// ---------------------------------------------------------------------------
+
+bool wxWindowOS2::HandleShow(
+  bool                              bShow
+, int                               WXUNUSED(nStatus)
+)
+{
+    wxShowEvent                     vEvent(GetId(), bShow);
+
+    vEvent.SetEventObject(this);
+    return HandleWindowEvent(vEvent);
+} // end of wxWindowOS2::HandleShow
+
+bool wxWindowOS2::HandleInitDialog( WXHWND WXUNUSED(hWndFocus) )
+{
+    wxInitDialogEvent               vEvent(GetId());
+
+    vEvent.SetEventObject(this);
+    return HandleWindowEvent(vEvent);
+} // end of wxWindowOS2::HandleInitDialog
+
+bool wxWindowOS2::HandleEndDrag(WXWPARAM WXUNUSED(wParam))
+{
+   // TODO: We'll handle drag and drop later
+    return false;
+}
+
+bool wxWindowOS2::HandleSetCursor( USHORT WXUNUSED(vId),
+                                   WXHWND hPointer )
+{
+    //
+    // Under OS/2 PM this allows the pointer to be changed
+    // as it passes over a control
+    //
+    ::WinSetPointer(HWND_DESKTOP, (HPOINTER)hPointer);
+    return true;
+} // end of wxWindowOS2::HandleSetCursor
+
+// ---------------------------------------------------------------------------
+// owner drawn stuff
+// ---------------------------------------------------------------------------
+bool wxWindowOS2::OS2OnDrawItem( int vId,
+                                 WXDRAWITEMSTRUCT* pItemStruct )
+{
+#if wxUSE_OWNER_DRAWN
+    wxClientDC                      vDc(this);
+
+#if wxUSE_MENUS_NATIVE
+    //
+    // Is it a menu item?
+    //
+    if (vId == 0)
+    {
+        ERRORID                     vError;
+        wxString                    sError;
+        POWNERITEM                  pMeasureStruct = (POWNERITEM)pItemStruct;
+        wxFrame*                    pFrame = (wxFrame*)this;
+        wxMenuItem*                 pMenuItem = pFrame->GetMenuBar()->FindItem(pMeasureStruct->idItem, pMeasureStruct->hItem);
+        HDC                         hDC = ::GpiQueryDevice(pMeasureStruct->hps);
+        wxRect                      vRect( pMeasureStruct->rclItem.xLeft
+                                          ,pMeasureStruct->rclItem.yBottom
+                                          ,pMeasureStruct->rclItem.xRight - pMeasureStruct->rclItem.xLeft
+                                          ,pMeasureStruct->rclItem.yTop - pMeasureStruct->rclItem.yBottom
+                                         );
+
+       wxPMDCImpl *impl = (wxPMDCImpl*) vDc.GetImpl();
+        impl->SetHDC( hDC, false );
+        impl->SetHPS( pMeasureStruct->hps );
+        //
+        // Load the wxWidgets Pallete and set to RGB mode
+        //
+        if (!::GpiCreateLogColorTable( pMeasureStruct->hps
+                                      ,0L
+                                      ,LCOLF_CONSECRGB
+                                      ,0L
+                                      ,(LONG)wxTheColourDatabase->m_nSize
+                                      ,(PLONG)wxTheColourDatabase->m_palTable
+                                     ))
+        {
+            vError = ::WinGetLastError(vHabmain);
+            sError = wxPMErrorToStr(vError);
+            wxLogError(_T("Unable to set current color table (1). Error: %s\n"), sError.c_str());
+        }
+        //
+        // Set the color table to RGB mode
+        //
+        if (!::GpiCreateLogColorTable( pMeasureStruct->hps
+                                      ,0L
+                                      ,LCOLF_RGB
+                                      ,0L
+                                      ,0L
+                                      ,NULL
+                                     ))
+        {
+            vError = ::WinGetLastError(vHabmain);
+            sError = wxPMErrorToStr(vError);
+            wxLogError(_T("Unable to set current color table (2). Error: %s\n"), sError.c_str());
+        }
+
+        wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE );
+
+        int eAction = 0;
+        int eStatus = 0;
+
+        if (pMeasureStruct->fsAttribute == pMeasureStruct->fsAttributeOld)
+        {
+            //
+            // Entire Item needs to be redrawn (either it has reappeared from
+            // behind another window or is being displayed for the first time
+            //
+            eAction = wxOwnerDrawn::wxODDrawAll;
+
+            if (pMeasureStruct->fsAttribute & MIA_HILITED)
+            {
+                //
+                // If it is currently selected we let the system handle it
+                //
+                eStatus |= wxOwnerDrawn::wxODSelected;
+            }
+            if (pMeasureStruct->fsAttribute & MIA_CHECKED)
+            {
+                //
+                // If it is currently checked we draw our own
+                //
+                eStatus |= wxOwnerDrawn::wxODChecked;
+                pMeasureStruct->fsAttributeOld = pMeasureStruct->fsAttribute &= ~MIA_CHECKED;
+            }
+            if (pMeasureStruct->fsAttribute & MIA_DISABLED)
+            {
+                //
+                // If it is currently disabled we let the system handle it
+                //
+                eStatus |= wxOwnerDrawn::wxODDisabled;
+            }
+            //
+            // Don't really care about framed (indicationg focus) or NoDismiss
+            //
+        }
+        else
+        {
+            if (pMeasureStruct->fsAttribute & MIA_HILITED)
+            {
+                eAction = wxOwnerDrawn::wxODDrawAll;
+                eStatus |= wxOwnerDrawn::wxODSelected;
+                //
+                // Keep the system from trying to highlight with its bogus colors
+                //
+                pMeasureStruct->fsAttributeOld = pMeasureStruct->fsAttribute &= ~MIA_HILITED;
+            }
+            else if (!(pMeasureStruct->fsAttribute & MIA_HILITED))
+            {
+                eAction = wxOwnerDrawn::wxODDrawAll;
+                eStatus = 0;
+                //
+                // Keep the system from trying to highlight with its bogus colors
+                //
+                pMeasureStruct->fsAttribute = pMeasureStruct->fsAttributeOld &= ~MIA_HILITED;
+            }
+            else
+            {
+                //
+                // For now we don't care about anything else
+                // just ignore the entire message!
+                //
+                return true;
+            }
+        }
+        //
+        // Now redraw the item
+        //
+        return(pMenuItem->OnDrawItem( vDc
+                                     ,vRect
+                                     ,(wxOwnerDrawn::wxODAction)eAction
+                                     ,(wxOwnerDrawn::wxODStatus)eStatus
+                                    ));
+        //
+        // leave the fsAttribute and fsOldAttribute unchanged.  If different,
+        // the system will do the highlight or fraeming or disabling for us,
+        // otherwise, we'd have to do it ourselves.
+        //
+    }
+#endif // wxUSE_MENUS_NATIVE
+
+    wxWindow*                       pItem = FindItem(vId);
+
+    if (pItem && pItem->IsKindOf(CLASSINFO(wxControl)))
+    {
+        return ((wxControl *)pItem)->OS2OnDraw(pItemStruct);
+    }
+#else
+    vId = vId;
+    pItemStruct = pItemStruct;
+#endif
+    return false;
+} // end of wxWindowOS2::OS2OnDrawItem
+
+long wxWindowOS2::OS2OnMeasureItem( int lId,
+                                    WXMEASUREITEMSTRUCT* pItemStruct )
+{
+#if wxUSE_OWNER_DRAWN
+    //
+    // Is it a menu item?
+    //
+    if (lId == 65536) // I really don't like this...has to be a better indicator
+    {
+        if (IsKindOf(CLASSINFO(wxFrame))) // we'll assume if Frame then a menu
+        {
+            size_t                  nWidth;
+            size_t                  nHeight;
+            POWNERITEM              pMeasureStruct = (POWNERITEM)pItemStruct;
+            wxFrame*                pFrame = (wxFrame*)this;
+            wxMenuItem*             pMenuItem = pFrame->GetMenuBar()->FindItem(pMeasureStruct->idItem, pMeasureStruct->hItem);
+
+            wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE );
+            nWidth  = 0L;
+            nHeight = 0L;
+            if (pMenuItem->OnMeasureItem( &nWidth
+                                         ,&nHeight
+                                        ))
+            {
+                MRESULT             mRc;
+
+                pMeasureStruct->rclItem.xRight  = nWidth;
+                pMeasureStruct->rclItem.xLeft   = 0L;
+                pMeasureStruct->rclItem.yTop    = nHeight;
+                pMeasureStruct->rclItem.yBottom = 0L;
+                mRc = MRFROM2SHORT(nHeight, nWidth);
+                return LONGFROMMR(mRc);
+            }
+            return 0L;
+        }
+    }
+    wxWindow*                      pItem = FindItem(lId);
+
+    if (pItem && pItem->IsKindOf(CLASSINFO(wxControl)))
+    {
+        OWNERITEM                   vItem;
+
+        vItem.idItem = (LONG)pItemStruct;
+        return ((wxControl *)pItem)->OS2OnMeasure((WXMEASUREITEMSTRUCT*)&vItem);
+    }
+#else
+    lId = lId;
+    pItemStruct = pItemStruct;
+#endif // wxUSE_OWNER_DRAWN
+    return FALSE;
+}
+
+// ---------------------------------------------------------------------------
+// colours and palettes
+// ---------------------------------------------------------------------------
+
+bool wxWindowOS2::HandleSysColorChange()
+{
+    wxSysColourChangedEvent         vEvent;
+
+    vEvent.SetEventObject(this);
+    return HandleWindowEvent(vEvent);
+} // end of wxWindowOS2::HandleSysColorChange
+
+bool wxWindowOS2::HandleCtlColor( WXHBRUSH* WXUNUSED(phBrush) )
+{
+    //
+    // Not much provided with message. So not sure I can do anything with it
+    //
+    return true;
+} // end of wxWindowOS2::HandleCtlColor
+
+
+// Define for each class of dialog and control
+WXHBRUSH wxWindowOS2::OnCtlColor(WXHDC WXUNUSED(hDC),
+                                 WXHWND WXUNUSED(hWnd),
+                                 WXUINT WXUNUSED(nCtlColor),
+                                 WXUINT WXUNUSED(message),
+                                 WXWPARAM WXUNUSED(wParam),
+                                 WXLPARAM WXUNUSED(lParam))
+{
+    return (WXHBRUSH)0;
+}
+
+bool wxWindowOS2::HandlePaletteChanged()
+{
+    // need to set this to something first
+    WXHWND                          hWndPalChange = NULLHANDLE;
+
+    wxPaletteChangedEvent           vEvent(GetId());
+
+    vEvent.SetEventObject(this);
+    vEvent.SetChangedWindow(wxFindWinFromHandle(hWndPalChange));
+
+    return HandleWindowEvent(vEvent);
+} // end of wxWindowOS2::HandlePaletteChanged
+
+//
+// Responds to colour changes: passes event on to children.
+//
+void wxWindowOS2::OnSysColourChanged(
+  wxSysColourChangedEvent&          rEvent
+)
+{
+    wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+
+    while (node)
+    {
+        //
+        // Only propagate to non-top-level windows
+        //
+        wxWindow*                   pWin = (wxWindow *)node->GetData();
+
+        if (pWin->GetParent())
+        {
+            wxSysColourChangedEvent vEvent;
+
+            rEvent.SetEventObject(pWin);
+            pWin->HandleWindowEvent(vEvent);
+        }
+        node = node->GetNext();
+    }
+} // end of wxWindowOS2::OnSysColourChanged
+
+// ---------------------------------------------------------------------------
+// painting
+// ---------------------------------------------------------------------------
+
+void wxWindow::OnPaint (
+  wxPaintEvent&                     rEvent
+)
+{
+    HDC                             hDC = (HDC)wxPaintDCImpl::FindDCInCache((wxWindow*) rEvent.GetEventObject());
+
+    if (hDC != 0)
+    {
+        OS2DefWindowProc( (WXUINT)WM_PAINT
+                         ,(WXWPARAM)hDC
+                         ,(WXLPARAM)0
+                        );
+    }
+} // end of wxWindow::OnPaint
+
+bool wxWindowOS2::HandlePaint()
+{
+    HRGN                            hRgn;
+    wxPaintEvent                    vEvent(m_windowId);
+    HPS                             hPS;
+    bool                            bProcessed;
+
+    // Create empty region
+    // TODO: get HPS somewhere else if possible
+    hPS  = ::WinGetPS(GetHwnd());
+    hRgn = ::GpiCreateRegion(hPS, 0, NULL);
+
+    if (::WinQueryUpdateRegion(GetHwnd(), hRgn) == RGN_ERROR)
+    {
+         wxLogLastError(wxT("CreateRectRgn"));
+         return false;
+    }
+    // Get all the rectangles from the region, convert the individual
+    // rectangles to "the other" coordinate system and reassemble a
+    // region from the rectangles, to be feed into m_updateRegion.
+    //
+    RGNRECT                     vRgnData;
+    PRECTL                      pUpdateRects = NULL;
+    vRgnData.ulDirection = RECTDIR_LFRT_TOPBOT;
+    if (::GpiQueryRegionRects( hPS          // Pres space
+                              ,hRgn         // Handle of region to query
+                              ,NULL         // Return all RECTs
+                              ,&vRgnData    // Will contain number or RECTs in region
+                              ,NULL         // NULL to return number of RECTs
+                             ))
+    {
+        pUpdateRects = new RECTL[vRgnData.crcReturned];
+        vRgnData.crc = vRgnData.crcReturned;
+        vRgnData.ircStart = 1;
+        if (::GpiQueryRegionRects( hPS      // Pres space of source
+                                  ,hRgn     // Handle of source region
+                                  ,NULL     // Return all RECTs
+                                  ,&vRgnData // Operations set to return rects
+                                  ,pUpdateRects // Will contain the actual RECTS
+                                 ))
+        {
+            int                     height;
+            RECT                    vRect;
+            ::WinQueryWindowRect(GetHwnd(), &vRect);
+            height = vRect.yTop;
+
+            for(size_t i = 0; i < vRgnData.crc; i++)
+            {
+                int                 rectHeight;
+                rectHeight = pUpdateRects[i].yTop - pUpdateRects[i].yBottom;
+                pUpdateRects[i].yBottom = height - pUpdateRects[i].yTop;
+                pUpdateRects[i].yTop = pUpdateRects[i].yBottom + rectHeight;
+            }
+            ::GpiSetRegion(hPS, hRgn, vRgnData.crc, pUpdateRects);
+            delete [] pUpdateRects;
+        }
+    }
+    m_updateRegion = wxRegion(hRgn, hPS);
+
+    vEvent.SetEventObject(this);
+    bProcessed = HandleWindowEvent(vEvent);
+
+    if (!bProcessed &&
+         IsKindOf(CLASSINFO(wxPanel)) &&
+         GetChildren().GetCount() == 0
+       )
+    {
+        //
+        // OS/2 needs to process this right here, not by the default proc
+        // Window's default proc correctly paints everything, OS/2 does not.
+        // For decorative panels that typically have no children, we draw
+        // borders.
+        //
+        HPS                         hPS;
+        RECTL                       vRect;
+
+        hPS = ::WinBeginPaint( GetHwnd()
+                              ,NULLHANDLE
+                              ,&vRect
+                             );
+        if(hPS)
+        {
+            ::GpiCreateLogColorTable( hPS
+                                     ,0L
+                                     ,LCOLF_CONSECRGB
+                                     ,0L
+                                     ,(LONG)wxTheColourDatabase->m_nSize
+                                     ,(PLONG)wxTheColourDatabase->m_palTable
+                                    );
+            ::GpiCreateLogColorTable( hPS
+                                     ,0L
+                                     ,LCOLF_RGB
+                                     ,0L
+                                     ,0L
+                                     ,NULL
+                                    );
+            if (::WinIsWindowVisible(GetHWND()))
+                ::WinFillRect(hPS, &vRect,  GetBackgroundColour().GetPixel());
+            if (m_dwExStyle)
+            {
+                LINEBUNDLE      vLineBundle;
+
+                vLineBundle.lColor     = 0x00000000; // Black
+                vLineBundle.usMixMode  = FM_OVERPAINT;
+                vLineBundle.fxWidth    = 1;
+                vLineBundle.lGeomWidth = 1;
+                vLineBundle.usType     = LINETYPE_SOLID;
+                vLineBundle.usEnd      = 0;
+                vLineBundle.usJoin     = 0;
+                ::GpiSetAttrs( hPS
+                              ,PRIM_LINE
+                              ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
+                              ,0L
+                              ,&vLineBundle
+                             );
+                ::WinQueryWindowRect(GetHwnd(), &vRect);
+                wxDrawBorder( hPS
+                             ,vRect
+                             ,m_dwExStyle
+                            );
+            }
+        }
+        ::WinEndPaint(hPS);
+        bProcessed = true;
+    }
+    else if (!bProcessed &&
+             IsKindOf(CLASSINFO(wxPanel))
+            )
+    {
+        //
+        // Panel with children, usually fills a frame client so no borders.
+        //
+        HPS hPS;
+        RECTL vRect;
+
+        hPS = ::WinBeginPaint( GetHwnd()
+                              ,NULLHANDLE
+                              ,&vRect
+                             );
+        if(hPS)
+        {
+            ::GpiCreateLogColorTable( hPS
+                                     ,0L
+                                     ,LCOLF_CONSECRGB
+                                     ,0L
+                                     ,(LONG)wxTheColourDatabase->m_nSize
+                                     ,(PLONG)wxTheColourDatabase->m_palTable
+                                    );
+            ::GpiCreateLogColorTable( hPS
+                                     ,0L
+                                     ,LCOLF_RGB
+                                     ,0L
+                                     ,0L
+                                     ,NULL
+                                    );
+
+            if (::WinIsWindowVisible(GetHWND()))
+                ::WinFillRect(hPS, &vRect,  GetBackgroundColour().GetPixel());
+        }
+        ::WinEndPaint(hPS);
+        bProcessed = true;
+    }
+    return bProcessed;
+} // end of wxWindowOS2::HandlePaint
+
+bool wxWindowOS2::HandleEraseBkgnd( WXHDC hDC )
+{
+    SWP vSwp;
+    bool rc;
+
+    ::WinQueryWindowPos(GetHwnd(), &vSwp);
+    if (vSwp.fl & SWP_MINIMIZE)
+        return true;
+
+    wxClientDC vDC(this);
+    wxPMDCImpl *impl = (wxPMDCImpl*) vDC.GetImpl();
+    impl->SetHDC(hDC);
+    impl->SetHPS((HPS)hDC); // this is really a PS
+
+    wxEraseEvent vEvent(m_windowId, &vDC);
+
+    vEvent.SetEventObject(this);
+
+    rc = HandleWindowEvent(vEvent);
+
+    impl->SetHPS(NULLHANDLE);
+    return true;
+} // end of wxWindowOS2::HandleEraseBkgnd
+
+void wxWindowOS2::OnEraseBackground(wxEraseEvent& rEvent)
+{
+    RECTL   vRect;
+    wxPMDCImpl *impl = (wxPMDCImpl*) rEvent.GetDC()->GetImpl();
+    HPS     hPS = impl->GetHPS();
+    APIRET  rc;
+    LONG    lColor = m_backgroundColour.GetPixel();
+
+    rc = ::WinQueryWindowRect(GetHwnd(), &vRect);
+    rc = ::WinFillRect(hPS, &vRect, lColor);
+}  // end of wxWindowOS2::OnEraseBackground
+
+// ---------------------------------------------------------------------------
+// moving and resizing
+// ---------------------------------------------------------------------------
+
+bool wxWindowOS2::HandleMinimize()
+{
+    wxIconizeEvent                  vEvent(m_windowId);
+
+    vEvent.SetEventObject(this);
+    return HandleWindowEvent(vEvent);
+} // end of wxWindowOS2::HandleMinimize
+
+bool wxWindowOS2::HandleMaximize()
+{
+    wxMaximizeEvent                 vEvent(m_windowId);
+
+    vEvent.SetEventObject(this);
+    return HandleWindowEvent(vEvent);
+} // end of wxWindowOS2::HandleMaximize
+
+bool wxWindowOS2::HandleMove( int nX, int nY )
+{
+    wxPoint pt(nX, nY);
+    wxMoveEvent vEvent(pt, m_windowId);
+
+    vEvent.SetEventObject(this);
+    return HandleWindowEvent(vEvent);
+}  // end of wxWindowOS2::HandleMove
+
+bool wxWindowOS2::HandleSize( int    nWidth,
+                              int    nHeight,
+                              WXUINT WXUNUSED(nFlag) )
+{
+    wxSize sz(nWidth, nHeight);
+    wxSizeEvent vEvent(sz, m_windowId);
+
+    vEvent.SetEventObject(this);
+    return HandleWindowEvent(vEvent);
+} // end of wxWindowOS2::HandleSize
+
+bool wxWindowOS2::HandleGetMinMaxInfo( PSWP pSwp )
+{
+    POINTL                          vPoint;
+
+    switch(pSwp->fl)
+    {
+        case SWP_MAXIMIZE:
+            ::WinGetMaxPosition(GetHwnd(), pSwp);
+            m_maxWidth = pSwp->cx;
+            m_maxHeight = pSwp->cy;
+            break;
+
+        case SWP_MINIMIZE:
+            ::WinGetMinPosition(GetHwnd(), pSwp, &vPoint);
+            m_minWidth = pSwp->cx;
+            m_minHeight = pSwp->cy;
+            break;
+
+        default:
+            return false;
+    }
+    return true;
+} // end of wxWindowOS2::HandleGetMinMaxInfo
+
+// ---------------------------------------------------------------------------
+// command messages
+// ---------------------------------------------------------------------------
+bool wxWindowOS2::HandleCommand( WXWORD wId,
+                                 WXWORD wCmd,
+                                 WXHWND hControl )
+{
+#if wxUSE_MENUS_NATIVE
+    if (wxCurrentPopupMenu)
+    {
+        wxMenu*                     pPopupMenu = wxCurrentPopupMenu;
+
+        wxCurrentPopupMenu = NULL;
+        return pPopupMenu->OS2Command(wCmd, wId);