+ vInfo.cb = sizeof(SBCDATA);
+ vInfo.posFirst = 0;
+ vInfo.posLast = (SHORT)nRange1;
+ vInfo.posThumb = nPos;
+
+ if (nOrient == wxHORIZONTAL )
+ {
+ ulStyle |= SBS_HORZ;
+ if (m_hWndScrollBarHorz == 0L)
+ {
+ //
+ // We create the scrollbars with the desktop so that they are not
+ // registered as child windows of the window in order that child
+ // windows may be scrolled without scrolling the scrollbars themselves!
+ //
+ m_hWndScrollBarHorz = ::WinCreateWindow( hWnd
+ ,WC_SCROLLBAR
+ ,(PSZ)NULL
+ ,ulStyle
+ ,vRect.xLeft
+ ,vRect.yBottom
+ ,vRect.xRight - vRect.xLeft
+ ,20
+ ,hWnd
+ ,HWND_TOP
+ ,FID_HORZSCROLL
+ ,&vInfo
+ ,NULL
+ );
+ }
+ else
+ {
+ RECTL vRect2;
+
+ //
+ // Only want to resize the scrollbar if it changes, otherwise
+ // we'd probably end up in a recursive loop until we crash the call stack
+ // because this method is called in a ScrolledWindow OnSize event and SWP_MOVE | SWP_SIZE
+ // generates those events.
+ //
+ ::WinQueryWindowRect(m_hWndScrollBarHorz, &vRect2);
+ if (!(vRect2.xLeft == vRect.xLeft &&
+ vRect2.xRight == vRect.xRight &&
+ vRect2.yBottom == vRect.yBottom &&
+ vRect2.yTop == vRect.yTop
+ ) )
+ {
+ ::WinSetWindowPos( m_hWndScrollBarHorz
+ ,HWND_TOP
+ ,vRect.xLeft
+ ,vRect.yBottom
+ ,vRect.xRight - vRect.xLeft
+ ,20
+ ,SWP_ACTIVATE | SWP_MOVE | SWP_SIZE | SWP_SHOW
+ );
+ }
+ ::WinSendMsg(m_hWndScrollBarHorz, SBM_SETSCROLLBAR, (MPARAM)nPos, MPFROM2SHORT(0, (SHORT)nRange1));
+ ::WinSendMsg(m_hWndScrollBarHorz, SBM_SETTHUMBSIZE, MPFROM2SHORT((SHORT)nThumbVisible, (SHORT)nRange1), (MPARAM)0);
+ }
+ }
+ else
+ {
+ ulStyle |= SBS_VERT;
+ if (m_hWndScrollBarVert == 0L)
+ {
+ m_hWndScrollBarVert = ::WinCreateWindow( hWnd
+ ,WC_SCROLLBAR
+ ,(PSZ)NULL
+ ,ulStyle
+ ,vRect.xRight - 20
+ ,vRect.yBottom + 20
+ ,20
+ ,vRect.yTop - (vRect.yBottom + 20)
+ ,hWnd
+ ,HWND_TOP
+ ,FID_VERTSCROLL
+ ,&vInfo
+ ,NULL
+ );
+ }
+ else
+ {
+ RECTL vRect2;
+
+ //
+ // Only want to resize the scrollbar if it changes, otherwise
+ // we'd probably end up in a recursive loop until we crash the call stack
+ // because this method is called in a ScrolledWindow OnSize event and SWP_MOVE | SWP_SIZE
+ // generates those events.
+ //
+ ::WinQueryWindowRect(m_hWndScrollBarVert, &vRect2);
+ if (!(vRect2.xLeft == vRect.xLeft &&
+ vRect2.xRight == vRect.xRight &&
+ vRect2.yBottom == vRect.yBottom &&
+ vRect2.yTop == vRect.yTop
+ ) )
+ {
+ ::WinSetWindowPos( m_hWndScrollBarVert
+ ,HWND_TOP
+ ,vRect.xRight - 20
+ ,vRect.yBottom + 20
+ ,20
+ ,vRect.yTop - (vRect.yBottom + 20)
+ ,SWP_ACTIVATE | SWP_MOVE | SWP_SIZE | SWP_SHOW
+ );
+ }
+ ::WinSendMsg(m_hWndScrollBarVert, SBM_SETSCROLLBAR, (MPARAM)nPos, MPFROM2SHORT(0, (SHORT)nRange1));
+ ::WinSendMsg(m_hWndScrollBarVert, SBM_SETTHUMBSIZE, MPFROM2SHORT((SHORT)nThumbVisible, (SHORT)nRange1), (MPARAM)0);
+ }
+ m_nYThumbSize = nThumbVisible;
+ }
+} // end of wxWindowOS2::SetScrollbar
+
+void wxWindowOS2::ScrollWindow(
+ int nDx
+, int nDy
+, const wxRect* pRect
+)
+{
+ RECTL vRect;
+ RECTL vRect2;
+
+ nDy *= -1; // flip the sign of Dy as OS/2 is opposite wxWin.
+ if (pRect)
+ {
+ vRect2.xLeft = pRect->x;
+ vRect2.yTop = pRect->y + pRect->height;
+ vRect2.xRight = pRect->x + pRect->width;
+ vRect2.yBottom = pRect->y;
+ }
+ else
+ {
+ ::WinQueryWindowRect(GetHwnd(), &vRect2);
+ ::WinQueryWindowRect(m_hWndScrollBarHorz, &vRect);
+ vRect2.yBottom += vRect.yTop - vRect.yBottom;
+ ::WinQueryWindowRect(m_hWndScrollBarVert, &vRect);
+ vRect2.xRight -= vRect.xRight - vRect.xLeft;
+
+ }
+ if (pRect)
+ ::WinScrollWindow( GetHwnd()
+ ,(LONG)nDx
+ ,(LONG)nDy
+ ,&vRect2
+ ,NULL
+ ,NULLHANDLE
+ ,NULL
+ ,SW_INVALIDATERGN
+ );
+ else
+ ::WinScrollWindow( GetHwnd()
+ ,nDx
+ ,nDy
+ ,NULL
+ ,NULL
+ ,NULLHANDLE
+ ,NULL
+ ,SW_INVALIDATERGN
+ );
+
+ //
+ // Move the children
+ wxWindowList::Node* pCurrent = GetChildren().GetFirst();
+ SWP vSwp;
+
+ while (pCurrent)
+ {
+ wxWindow* pChildWin = pCurrent->GetData();
+
+ if (pChildWin->GetHWND() != NULLHANDLE)
+ {
+ ::WinQueryWindowPos(pChildWin->GetHWND(), &vSwp);
+ ::WinQueryWindowRect(pChildWin->GetHWND(), &vRect);
+ if (pChildWin->GetHWND() == m_hWndScrollBarVert ||
+ pChildWin->GetHWND() == m_hWndScrollBarHorz)
+ {
+ ::WinSetWindowPos( pChildWin->GetHWND()
+ ,HWND_TOP
+ ,vSwp.x + nDx
+ ,vSwp.y + nDy
+ ,0
+ ,0
+ ,SWP_MOVE | SWP_SHOW | SWP_ZORDER
+ );
+ }
+ else
+ {
+ ::WinSetWindowPos( pChildWin->GetHWND()
+ ,HWND_BOTTOM
+ ,vSwp.x + nDx
+ ,vSwp.y + nDy
+ ,0
+ ,0
+ ,SWP_MOVE | SWP_ZORDER
+ );
+ ::WinInvalidateRect(pChildWin->GetHWND(), &vRect, FALSE);
+ }
+ }
+ pCurrent = pCurrent->GetNext();
+ }
+} // end of wxWindowOS2::ScrollWindow
+
+// ---------------------------------------------------------------------------
+// subclassing
+// ---------------------------------------------------------------------------
+
+void wxWindowOS2::SubclassWin(
+ WXHWND hWnd
+)
+{
+ HWND hwnd = (HWND)hWnd;
+
+ wxASSERT_MSG( !m_fnOldWndProc, wxT("subclassing window twice?") );
+ wxCHECK_RET(::WinIsWindow(vHabmain, hwnd), wxT("invalid HWND in SubclassWin") );
+ m_fnOldWndProc = (WXFARPROC) ::WinSubclassWindow(hwnd, (PFNWP)wxWndProc);
+} // end of wxWindowOS2::SubclassWin
+
+void wxWindowOS2::UnsubclassWin()
+{
+ //
+ // Restore old Window proc
+ //
+ HWND hwnd = GetHWND();
+
+ if (m_hWnd)
+ {
+ wxCHECK_RET( ::WinIsWindow(vHabmain, hwnd), wxT("invalid HWND in UnsubclassWin") );
+
+ PFNWP fnProc = (PFNWP)::WinQueryWindowPtr(hwnd, QWP_PFNWP);
+
+ if ( (m_fnOldWndProc != 0) && (fnProc != (PFNWP) m_fnOldWndProc))
+ {
+ WinSubclassWindow(hwnd, (PFNWP)m_fnOldWndProc);
+ m_fnOldWndProc = 0;
+ }
+ }
+} // end of wxWindowOS2::UnsubclassWin
+
+//
+// Make a Windows extended style from the given wxWindows window style
+//
+WXDWORD wxWindowOS2::MakeExtendedStyle(
+ long lStyle
+, bool bEliminateBorders
+)
+{
+ //
+ // Simply fill out with wxWindow extended styles. We'll conjure
+ // something up in OS2Create and all window redrawing pieces later
+ //
+ WXDWORD dwStyle = 0;
+
+ if (lStyle & wxTRANSPARENT_WINDOW )
+ dwStyle |= wxTRANSPARENT_WINDOW;
+
+ if (!bEliminateBorders)
+ {
+ if (lStyle & wxSUNKEN_BORDER)
+ dwStyle |= wxSUNKEN_BORDER;
+ if (lStyle & wxDOUBLE_BORDER)
+ dwStyle |= wxDOUBLE_BORDER;
+ if (lStyle & wxRAISED_BORDER )
+ dwStyle |= wxRAISED_BORDER;
+ if (lStyle & wxSTATIC_BORDER)
+ dwStyle |= wxSTATIC_BORDER;
+ }
+ return dwStyle;
+} // end of wxWindowOS2::MakeExtendedStyle
+
+//
+// Determines whether simulated 3D effects or CTL3D should be used,
+// applying a default border style if required, and returning an extended
+// style to pass to OS2Create.
+//
+WXDWORD wxWindowOS2::Determine3DEffects(
+ WXDWORD dwDefaultBorderStyle
+, bool* pbWant3D
+) const
+{
+ WXDWORD dwStyle = 0L;
+
+ //
+ // Native PM does not have any specialize 3D effects like WIN32 does,
+ // so we have to try and invent them.
+ //
+
+ //
+ // If matches certain criteria, then assume no 3D effects
+ // unless specifically requested (dealt with in MakeExtendedStyle)
+ //
+ if (!GetParent() ||
+ !IsKindOf(CLASSINFO(wxControl)) ||
+ (m_windowStyle & wxNO_BORDER)
+ )
+ {
+ *pbWant3D = FALSE;
+ return MakeExtendedStyle(m_windowStyle, FALSE);
+ }
+
+ //
+ // 1) App can specify global 3D effects
+ //
+ *pbWant3D = wxTheApp->GetAuto3D();
+
+ //
+ // 2) If the parent is being drawn with user colours, or simple border
+ // specified, switch effects off.
+ //
+ if (GetParent() &&
+ (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS) ||
+ (m_windowStyle & wxSIMPLE_BORDER)
+ )
+ *pbWant3D = FALSE;
+
+ //
+ // 3) Control can override this global setting by defining
+ // a border style, e.g. wxSUNKEN_BORDER
+ //
+ if ((m_windowStyle & wxDOUBLE_BORDER) ||
+ (m_windowStyle & wxRAISED_BORDER) ||
+ (m_windowStyle & wxSTATIC_BORDER) ||
+ (m_windowStyle & wxSUNKEN_BORDER)
+ )
+ *pbWant3D = TRUE;
+
+ dwStyle = MakeExtendedStyle( m_windowStyle
+ ,FALSE
+ );
+
+ //
+ // If we want 3D, but haven't specified a border here,
+ // apply the default border style specified.
+ //
+ if (dwDefaultBorderStyle && (*pbWant3D) &&
+ !((m_windowStyle & wxDOUBLE_BORDER) ||
+ (m_windowStyle & wxRAISED_BORDER) ||
+ (m_windowStyle & wxSTATIC_BORDER) ||
+ (m_windowStyle & wxSIMPLE_BORDER)
+ )
+ )
+ dwStyle |= dwDefaultBorderStyle;
+ return dwStyle;
+} // end of wxWindowOS2::Determine3DEffects
+
+#if WXWIN_COMPATIBILITY
+void wxWindowOS2::OnCommand(
+ wxWindow& rWin
+, wxCommandEvent& rEvent
+)
+{
+ if (GetEventHandler()->ProcessEvent(rEvent))
+ return;
+ if (m_parent)
+ m_parent->GetEventHandler()->OnCommand( rWin
+ ,rEvent
+ );
+} // end of wxWindowOS2::OnCommand
+
+wxObject* wxWindowOS2::GetChild(
+ int nNumber
+) const
+{
+ //
+ // Return a pointer to the Nth object in the Panel
+ //
+ wxNode* pNode = GetChildren().First();
+ int n = nNumber;
+
+ while (pNode && n--)
+ pNode = pNode->Next();
+ if (pNode)
+ {
+ wxObject* pObj = (wxObject*)pNode->Data();
+ return(pObj);
+ }
+ else
+ return NULL;
+} // end of wxWindowOS2::GetChild
+
+#endif // WXWIN_COMPATIBILITY
+
+//
+// Setup background and foreground colours correctly
+//
+void wxWindowOS2::SetupColours()
+{
+ if ( GetParent() )
+ SetBackgroundColour(GetParent()->GetBackgroundColour());
+} // end of wxWindowOS2::SetupColours
+
+void wxWindowOS2::OnIdle(
+ wxIdleEvent& WXUNUSED(rEvent)
+)
+{
+ //
+ // Check if we need to send a LEAVE event
+ //
+ if (m_bMouseInWindow)
+ {
+ POINTL vPoint;
+
+ ::WinQueryPointerPos(HWND_DESKTOP, &vPoint);
+ if (::WinWindowFromPoint(HWND_DESKTOP, &vPoint, FALSE) != (HWND)GetHwnd())
+ {
+ //
+ // Generate a LEAVE event
+ //
+ m_bMouseInWindow = FALSE;
+
+ //
+ // Unfortunately the mouse button and keyboard state may have changed
+ // by the time the OnIdle function is called, so 'state' may be
+ // meaningless.
+ //
+ int nState = 0;
+
+ if (::WinGetKeyState(HWND_DESKTOP, VK_SHIFT) != 0)
+ nState |= VK_SHIFT;
+ if (::WinGetKeyState(HWND_DESKTOP, VK_CTRL) != 0);
+ nState |= VK_CTRL;
+
+ wxMouseEvent rEvent(wxEVT_LEAVE_WINDOW);
+
+ InitMouseEvent( rEvent
+ ,vPoint.x
+ ,vPoint.y
+ ,nState
+ );
+ (void)GetEventHandler()->ProcessEvent(rEvent);
+ }
+ }
+ UpdateWindowUI();
+} // end of wxWindowOS2::OnIdle
+
+//
+// Set this window to be the child of 'parent'.
+//
+bool wxWindowOS2::Reparent(
+ wxWindow* pParent
+)
+{
+ if (!wxWindowBase::Reparent(pParent))
+ return FALSE;
+
+ HWND hWndChild = GetHwnd();
+ HWND hWndParent = GetParent() ? GetWinHwnd(GetParent()) : (HWND)0;
+
+ ::WinSetParent(hWndChild, hWndParent, TRUE);
+ return TRUE;
+} // end of wxWindowOS2::Reparent
+
+void wxWindowOS2::Clear()
+{
+ wxClientDC vDc((wxWindow*)this);
+ wxBrush vBrush( GetBackgroundColour()
+ ,wxSOLID
+ );
+
+ vDc.SetBackground(vBrush);
+ vDc.Clear();
+} // end of wxWindowOS2::Clear
+
+void wxWindowOS2::Update()
+{
+ ::WinUpdateWindow(GetHwnd());
+} // end of wxWindowOS2::Update
+
+void wxWindowOS2::Freeze()
+{
+ ::WinSendMsg(GetHwnd(), WM_VRNDISABLED, (MPARAM)0, (MPARAM)0);
+} // end of wxWindowOS2::Freeze
+
+void wxWindowOS2::Thaw()
+{
+ ::WinSendMsg(GetHwnd(), WM_VRNENABLED, (MPARAM)TRUE, (MPARAM)0);
+
+ //
+ // We need to refresh everything or otherwise he invalidated area is not
+ // repainted.
+ //
+ Refresh();
+} // end of wxWindowOS2::Thaw
+
+void wxWindowOS2::Refresh(
+ bool bEraseBack
+, const wxRect* pRect
+)
+{
+ HWND hWnd = GetHwnd();
+
+ if (hWnd)
+ {
+ if (pRect)
+ {
+ RECTL vOs2Rect;
+
+ vOs2Rect.xLeft = pRect->x;
+ vOs2Rect.yTop = pRect->y;
+ vOs2Rect.xRight = pRect->x + pRect->width;
+ vOs2Rect.yBottom = pRect->y + pRect->height;
+
+ ::WinInvalidateRect(hWnd, &vOs2Rect, bEraseBack);
+ }
+ else
+ ::WinInvalidateRect(hWnd, NULL, bEraseBack);
+ }
+} // end of wxWindowOS2::Refresh
+
+// ---------------------------------------------------------------------------
+// drag and drop
+// ---------------------------------------------------------------------------
+
+#if wxUSE_DRAG_AND_DROP
+void wxWindowOS2::SetDropTarget(
+ wxDropTarget* pDropTarget
+)
+{
+ if (m_dropTarget != 0)
+ {
+ m_dropTarget->Revoke(m_hWnd);
+ delete m_dropTarget;
+ }
+ m_dropTarget = pDropTarget;
+ if (m_dropTarget != 0)
+ m_dropTarget->Register(m_hWnd);
+} // end of wxWindowOS2::SetDropTarget
+#endif
+
+//