+#if defined(__WIN95__)
+ int oldRange = range - thumbVisible;
+
+ int range1 = oldRange;
+
+ // Try to adjust the range to cope with page size > 1
+ // - a Windows API quirk
+ int pageSize = thumbVisible;
+ if ( pageSize > 1 && range > 0)
+ {
+ range1 += (pageSize - 1);
+ }
+
+ SCROLLINFO info;
+ int dir;
+
+ if ( orient == wxHORIZONTAL ) {
+ dir = SB_HORZ;
+ } else {
+ dir = SB_VERT;
+ }
+
+ info.cbSize = sizeof(SCROLLINFO);
+ info.nPage = pageSize; // Have to set this, or scrollbar goes awry
+ info.nMin = 0;
+ info.nMax = range1;
+ info.nPos = pos;
+ info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
+
+ HWND hWnd = GetHwnd();
+ if ( hWnd )
+ ::SetScrollInfo(hWnd, dir, &info, refresh);
+#else
+ int wOrient;
+ if ( orient == wxHORIZONTAL )
+ wOrient = SB_HORZ;
+ else
+ wOrient = SB_VERT;
+
+ HWND hWnd = GetHwnd();
+ if ( hWnd )
+ {
+ ::SetScrollRange(hWnd, wOrient, 0, range, FALSE);
+ ::SetScrollPos(hWnd, wOrient, pos, refresh);
+ }
+#endif
+ if ( orient == wxHORIZONTAL ) {
+ m_xThumbSize = thumbVisible;
+ } else {
+ m_yThumbSize = thumbVisible;
+ }
+}
+
+void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *prect)
+{
+ RECT rect;
+ RECT *pr;
+ if ( prect )
+ {
+ rect.left = prect->x;
+ rect.top = prect->y;
+ rect.right = prect->x + prect->width;
+ rect.bottom = prect->y + prect->height;
+ pr = ▭
+ }
+ else
+ {
+ pr = NULL;
+ }
+
+ ::ScrollWindow(GetHwnd(), dx, dy, pr, pr);
+}
+
+static bool ScrollVertically(HWND hwnd, int kind, int count)
+{
+ int posStart = GetScrollPosition(hwnd, SB_VERT);
+
+ int pos = posStart;
+ for ( int n = 0; n < count; n++ )
+ {
+ ::SendMessage(hwnd, WM_VSCROLL, kind, 0);
+
+ int posNew = GetScrollPosition(hwnd, SB_VERT);
+ if ( posNew == pos )
+ {
+ // don't bother to continue, we're already at top/bottom
+ break;
+ }
+
+ pos = posNew;
+ }
+
+ return pos != posStart;
+}
+
+bool wxWindowMSW::ScrollLines(int lines)
+{
+ bool down = lines > 0;
+
+ return ScrollVertically(GetHwnd(),
+ down ? SB_LINEDOWN : SB_LINEUP,
+ down ? lines : -lines);
+}
+
+bool wxWindowMSW::ScrollPages(int pages)
+{
+ bool down = pages > 0;
+
+ return ScrollVertically(GetHwnd(),
+ down ? SB_PAGEDOWN : SB_PAGEUP,
+ down ? pages : -pages);
+}
+
+// ---------------------------------------------------------------------------
+// subclassing
+// ---------------------------------------------------------------------------
+
+void wxWindowMSW::SubclassWin(WXHWND hWnd)
+{
+ wxASSERT_MSG( !m_oldWndProc, wxT("subclassing window twice?") );
+
+ HWND hwnd = (HWND)hWnd;
+ wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in SubclassWin") );
+
+ wxAssociateWinWithHandle(hwnd, this);
+
+ m_oldWndProc = (WXFARPROC)::GetWindowLong((HWND)hWnd, GWL_WNDPROC);
+
+ // we don't need to subclass the window of our own class (in the Windows
+ // sense of the word)
+ if ( !wxCheckWindowWndProc(hWnd, (WXFARPROC)wxWndProc) )
+ {
+ ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) wxWndProc);
+ }
+ else
+ {
+ // don't bother restoring it neither: this also makes it easy to
+ // implement IsOfStandardClass() method which returns TRUE for the
+ // standard controls and FALSE for the wxWindows own windows as it can
+ // simply check m_oldWndProc
+ m_oldWndProc = NULL;
+ }
+}
+
+void wxWindowMSW::UnsubclassWin()
+{
+ wxRemoveHandleAssociation(this);
+
+ // Restore old Window proc
+ HWND hwnd = GetHwnd();
+ if ( hwnd )
+ {
+ m_hWnd = 0;
+
+ wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in UnsubclassWin") );
+
+ if ( m_oldWndProc )
+ {
+ if ( !wxCheckWindowWndProc((WXHWND)hwnd, m_oldWndProc) )
+ {
+ ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) m_oldWndProc);
+ }
+
+ m_oldWndProc = NULL;
+ }
+ }
+}
+
+bool wxCheckWindowWndProc(WXHWND hWnd, WXFARPROC wndProc)
+{
+ // Unicows note: the code below works, but only because WNDCLASS contains
+ // original window handler rather that the unicows fake one. This may not
+ // be on purpose, though; if it stops working with future versions of
+ // unicows.dll, we can override unicows hooks by setting
+ // Unicows_{Set,Get}WindowLong and Unicows_RegisterClass to our own
+ // versions that keep track of fake<->real wnd proc mapping.
+ WNDCLASS cls;
+ if ( !::GetClassInfo(wxGetInstance(), wxGetWindowClass(hWnd), &cls) )
+ {
+ wxLogLastError(_T("GetClassInfo"));
+
+ return FALSE;
+ }
+
+ return wndProc == (WXFARPROC)cls.lpfnWndProc;
+}
+
+// ----------------------------------------------------------------------------
+// Style handling
+// ----------------------------------------------------------------------------
+
+void wxWindowMSW::SetWindowStyleFlag(long flags)
+{
+ long flagsOld = GetWindowStyleFlag();
+ if ( flags == flagsOld )
+ return;
+
+ // update the internal variable
+ wxWindowBase::SetWindowStyleFlag(flags);
+
+ // now update the Windows style as well if needed - and if the window had
+ // been already created
+ if ( !GetHwnd() )
+ return;
+
+ WXDWORD exstyle, exstyleOld;
+ long style = MSWGetStyle(flags, &exstyle),
+ styleOld = MSWGetStyle(flagsOld, &exstyleOld);
+
+ if ( style != styleOld )
+ {
+ // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by
+ // this function so instead of simply setting the style to the new
+ // value we clear the bits which were set in styleOld but are set in
+ // the new one and set the ones which were not set before
+ long styleReal = ::GetWindowLong(GetHwnd(), GWL_STYLE);
+ styleReal &= ~styleOld;
+ styleReal |= style;
+
+ ::SetWindowLong(GetHwnd(), GWL_STYLE, styleReal);
+ }
+
+ // and the extended style
+ if ( exstyle != exstyleOld )
+ {
+ long exstyleReal = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
+ exstyleReal &= ~exstyleOld;
+ exstyleReal |= exstyle;
+
+ ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyleReal);
+
+ // we must call SetWindowPos() to flash the cached extended style and
+ // also to make the change to wxSTAY_ON_TOP style take effect: just
+ // setting the style simply doesn't work
+ if ( !::SetWindowPos(GetHwnd(),
+ exstyleReal & WS_EX_TOPMOST ? HWND_TOPMOST
+ : HWND_NOTOPMOST,
+ 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE) )
+ {
+ wxLogLastError(_T("SetWindowPos"));
+ }
+ }
+}
+
+WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
+{
+ // translate the style
+ WXDWORD style = WS_CHILD;
+
+ if ( flags & wxCLIP_CHILDREN )
+ style |= WS_CLIPCHILDREN;
+
+ if ( flags & wxCLIP_SIBLINGS )
+ style |= WS_CLIPSIBLINGS;
+
+ wxBorder border = (wxBorder)(flags & wxBORDER_MASK);
+ if ( border != wxBORDER_NONE && border != wxBORDER_DEFAULT )
+ style |= WS_BORDER;
+
+ // now deal with ext style if the caller wants it
+ if ( exstyle )
+ {
+ *exstyle = 0;
+
+ if ( flags & wxTRANSPARENT_WINDOW )
+ *exstyle |= WS_EX_TRANSPARENT;
+
+ switch ( flags & wxBORDER_MASK )
+ {
+ default:
+ wxFAIL_MSG( _T("unknown border style") );
+ // fall through
+
+ case wxBORDER_NONE:
+ case wxBORDER_SIMPLE:
+ case wxBORDER_DEFAULT:
+ break;
+
+ case wxBORDER_STATIC:
+ *exstyle |= WS_EX_STATICEDGE;
+ break;
+
+ case wxBORDER_RAISED:
+ *exstyle |= WS_EX_WINDOWEDGE;
+ break;
+
+ case wxBORDER_SUNKEN:
+ *exstyle |= WS_EX_CLIENTEDGE;
+ break;
+
+ case wxBORDER_DOUBLE:
+ *exstyle |= WS_EX_DLGMODALFRAME;
+ break;
+ }
+
+ // wxUniv doesn't use Windows dialog navigation functions at all
+#ifndef __WXUNIVERSAL__
+ // to make the dialog navigation work with the nested panels we must
+ // use this style (top level windows such as dialogs don't need it)
+ if ( (flags & wxTAB_TRAVERSAL) && !IsTopLevel() )
+ {
+ *exstyle |= WS_EX_CONTROLPARENT;
+ }
+#endif // __WXUNIVERSAL__
+ }
+
+ return style;
+}
+
+// Make a Windows extended style from the given wxWindows window style
+WXDWORD wxWindowMSW::MakeExtendedStyle(long style, bool eliminateBorders)
+{
+ WXDWORD exStyle = 0;
+ if ( style & wxTRANSPARENT_WINDOW )
+ exStyle |= WS_EX_TRANSPARENT;
+
+ if ( !eliminateBorders )
+ {
+ if ( style & wxSUNKEN_BORDER )
+ exStyle |= WS_EX_CLIENTEDGE;
+ if ( style & wxDOUBLE_BORDER )
+ exStyle |= WS_EX_DLGMODALFRAME;
+#if defined(__WIN95__)
+ if ( style & wxRAISED_BORDER )
+ // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does
+ exStyle |= WS_EX_DLGMODALFRAME; /* WS_EX_WINDOWEDGE */;
+ if ( style & wxSTATIC_BORDER )
+ exStyle |= WS_EX_STATICEDGE;
+#endif
+ }
+
+ return exStyle;
+}
+
+// Determines whether native 3D effects or CTL3D should be used,
+// applying a default border style if required, and returning an extended
+// style to pass to CreateWindowEx.
+WXDWORD wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle,
+ bool *want3D) const
+{
+ // If matches certain criteria, then assume no 3D effects
+ // unless specifically requested (dealt with in MakeExtendedStyle)
+ if ( !GetParent()
+#if wxUSE_CONTROLS
+ || !IsKindOf(CLASSINFO(wxControl))
+#endif // wxUSE_CONTROLS
+ || (m_windowStyle & wxNO_BORDER) )
+ {
+ *want3D = FALSE;
+ return MakeExtendedStyle(m_windowStyle);
+ }
+
+ // Determine whether we should be using 3D effects or not.
+ bool nativeBorder = FALSE; // by default, we don't want a Win95 effect
+
+ // 1) App can specify global 3D effects
+ *want3D = wxTheApp->GetAuto3D();
+
+ // 2) If the parent is being drawn with user colours, or simple border specified,
+ // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D
+ if ( GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS) || (m_windowStyle & wxSIMPLE_BORDER) )
+ *want3D = FALSE;
+
+ // 3) Control can override this global setting by defining
+ // a border style, e.g. wxSUNKEN_BORDER
+ if ( m_windowStyle & wxSUNKEN_BORDER )
+ *want3D = TRUE;
+
+ // 4) If it's a special border, CTL3D can't cope so we want a native border
+ if ( (m_windowStyle & wxDOUBLE_BORDER) || (m_windowStyle & wxRAISED_BORDER) ||
+ (m_windowStyle & wxSTATIC_BORDER) )
+ {
+ *want3D = TRUE;
+ nativeBorder = TRUE;
+ }
+
+ // 5) If this isn't a Win95 app, and we are using CTL3D, remove border
+ // effects from extended style
+#if wxUSE_CTL3D
+ if ( *want3D )
+ nativeBorder = FALSE;
+#endif
+
+ DWORD exStyle = MakeExtendedStyle(m_windowStyle, !nativeBorder);
+
+ // If we want 3D, but haven't specified a border here,
+ // apply the default border style specified.
+ // TODO what about non-Win95 WIN32? Does it have borders?
+#if defined(__WIN95__) && !wxUSE_CTL3D
+ if ( defaultBorderStyle && (*want3D) && ! ((m_windowStyle & wxDOUBLE_BORDER) || (m_windowStyle & wxRAISED_BORDER ) ||
+ (m_windowStyle & wxSTATIC_BORDER) || (m_windowStyle & wxSIMPLE_BORDER) ))
+ exStyle |= defaultBorderStyle; // WS_EX_CLIENTEDGE;
+#endif
+
+ return exStyle;
+}
+
+#if WXWIN_COMPATIBILITY
+// If nothing defined for this, try the parent.
+// E.g. we may be a button loaded from a resource, with no callback function
+// defined.
+void wxWindowMSW::OnCommand(wxWindow& win, wxCommandEvent& event)
+{
+ if ( GetEventHandler()->ProcessEvent(event) )
+ return;
+ if ( m_parent )
+ m_parent->GetEventHandler()->OnCommand(win, event);
+}
+#endif // WXWIN_COMPATIBILITY_2
+
+#if WXWIN_COMPATIBILITY
+wxObject* wxWindowMSW::GetChild(int number) const
+{
+ // Return a pointer to the Nth object in the Panel
+ wxNode *node = GetChildren().First();
+ int n = number;
+ while (node && n--)
+ node = node->Next();
+ if ( node )
+ {
+ wxObject *obj = (wxObject *)node->Data();
+ return(obj);