X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/cc0bffacebe299b312ce7fdf49a8825f466cf73f..884a37aed25b5cdabcc6f9f7604878aa97ecb031:/src/msw/notebook.cpp diff --git a/src/msw/notebook.cpp b/src/msw/notebook.cpp index 765866b191..f4614c1267 100644 --- a/src/msw/notebook.cpp +++ b/src/msw/notebook.cpp @@ -22,9 +22,10 @@ #if wxUSE_NOTEBOOK -// wxWindows +// wxWidgets #ifndef WX_PRECOMP #include "wx/string.h" + #include "wx/dc.h" #endif // WX_PRECOMP #include "wx/log.h" @@ -54,18 +55,7 @@ #include "wx/msw/winundef.h" #if wxUSE_UXTHEME -#include "wx/msw/uxtheme.h" - -#include "wx/radiobut.h" -#include "wx/radiobox.h" -#include "wx/checkbox.h" -#include "wx/bmpbuttn.h" -#include "wx/statline.h" -#include "wx/statbox.h" -#include "wx/stattext.h" -#include "wx/slider.h" -#include "wx/scrolwin.h" -#include "wx/panel.h" + #include "wx/msw/uxtheme.h" #endif // ---------------------------------------------------------------------------- @@ -126,7 +116,7 @@ wxBEGIN_FLAGS( wxNotebookStyle ) wxFLAGS_MEMBER(wxBORDER_RAISED) wxFLAGS_MEMBER(wxBORDER_STATIC) wxFLAGS_MEMBER(wxBORDER_NONE) - + // old style border flags wxFLAGS_MEMBER(wxSIMPLE_BORDER) wxFLAGS_MEMBER(wxSUNKEN_BORDER) @@ -167,17 +157,17 @@ wxBEGIN_PROPERTIES_TABLE(wxNotebook) wxEVENT_PROPERTY( PageChanged , wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED , wxNotebookEvent ) wxPROPERTY_COLLECTION( PageInfos , wxNotebookPageInfoList , wxNotebookPageInfo* , AddPageInfo , GetPageInfos , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) - wxPROPERTY_FLAGS( WindowStyle , wxNotebookStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style + wxPROPERTY_FLAGS( WindowStyle , wxNotebookStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style wxEND_PROPERTIES_TABLE() wxBEGIN_HANDLERS_TABLE(wxNotebook) wxEND_HANDLERS_TABLE() -wxCONSTRUCTOR_5( wxNotebook , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size , long , WindowStyle) +wxCONSTRUCTOR_5( wxNotebook , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size , long , WindowStyle) wxBEGIN_PROPERTIES_TABLE(wxNotebookPageInfo) - wxREADONLY_PROPERTY( Page , wxNotebookPage* , GetPage , , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) + wxREADONLY_PROPERTY( Page , wxNotebookPage* , GetPage , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) wxREADONLY_PROPERTY( Text , wxString , GetText , wxString() , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) wxREADONLY_PROPERTY( Selected , bool , GetSelected , false, 0 /*flags*/ , wxT("Helpstring") , wxT("group") ) wxREADONLY_PROPERTY( ImageId , int , GetImageId , -1 , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) @@ -186,7 +176,7 @@ wxEND_PROPERTIES_TABLE() wxBEGIN_HANDLERS_TABLE(wxNotebookPageInfo) wxEND_HANDLERS_TABLE() -wxCONSTRUCTOR_4( wxNotebookPageInfo , wxNotebookPage* , Page , wxString , Text , bool , Selected , int , ImageId ) +wxCONSTRUCTOR_4( wxNotebookPageInfo , wxNotebookPage* , Page , wxString , Text , bool , Selected , int , ImageId ) #else IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxControl) @@ -220,6 +210,10 @@ void wxNotebook::Init() { m_imageList = NULL; m_nSelection = -1; + +#if wxUSE_UXTHEME + m_hbrBackground = NULL; +#endif // wxUSE_UXTHEME } // default for dynamic class @@ -249,20 +243,20 @@ bool wxNotebook::Create(wxWindow *parent, long style, const wxString& name) { - // Does ComCtl32 support non-top tabs? - int verComCtl32 = wxApp::GetComCtl32Version(); - if ( verComCtl32 < 470 || verComCtl32 >= 600 ) + // comctl32.dll 6.0 doesn't support non-top tabs with visual styles (the + // control is simply not rendered correctly), so disable them in this case + const int verComCtl32 = wxApp::GetComCtl32Version(); + if ( verComCtl32 == 600 ) { - if (style & wxNB_BOTTOM) - style &= ~wxNB_BOTTOM; - - if (style & wxNB_LEFT) - style &= ~wxNB_LEFT; - - if (style & wxNB_RIGHT) - style &= ~wxNB_RIGHT; + // check if we use themes at all -- if we don't, we're still ok +#if wxUSE_UXTHEME + if ( wxUxThemeEngine::GetIfActive() ) +#endif + { + style &= ~(wxNB_BOTTOM | wxNB_LEFT | wxNB_RIGHT); + } } - + if ( !CreateControl(parent, id, pos, size, style | wxTAB_TRAVERSAL, wxDefaultValidator, name) ) return false; @@ -270,8 +264,6 @@ bool wxNotebook::Create(wxWindow *parent, if ( !MSWCreateControl(WC_TABCONTROL, wxEmptyString, pos, size) ) return false; - SetBackgroundColour(wxColour(::GetSysColor(COLOR_BTNFACE))); - return true; } @@ -304,6 +296,14 @@ WXDWORD wxNotebook::MSWGetStyle(long style, WXDWORD *exstyle) const return tabStyle; } +wxNotebook::~wxNotebook() +{ +#if wxUSE_UXTHEME + if ( m_hbrBackground ) + ::DeleteObject((HBRUSH)m_hbrBackground); +#endif // wxUSE_UXTHEME +} + // ---------------------------------------------------------------------------- // wxNotebook accessors // ---------------------------------------------------------------------------- @@ -323,7 +323,7 @@ int wxNotebook::GetRowCount() const int wxNotebook::SetSelection(size_t nPage) { - wxCHECK_MSG( IS_VALID_PAGE(nPage), -1, wxT("notebook page out of range") ); + wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("notebook page out of range") ); if ( int(nPage) != m_nSelection ) { @@ -437,8 +437,8 @@ void wxNotebook::SetTabSize(const wxSize& sz) wxSize wxNotebook::CalcSizeFromPage(const wxSize& sizePage) const { wxSize sizeTotal = sizePage; - - // We need to make getting tab size part of the wxWindows API. + + // We need to make getting tab size part of the wxWidgets API. wxSize tabSize(0, 0); if (GetPageCount() > 0) { @@ -471,9 +471,18 @@ void wxNotebook::AdjustPageSize(wxNotebookPage *page) // get the page size from the notebook size GetSize((int *)&rc.right, (int *)&rc.bottom); - TabCtrl_AdjustRect(m_hwnd, false, &rc); - page->SetSize(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); + // This check is to work around a bug in TabCtrl_AdjustRect which will + // cause a crash on win2k, or on XP with themes disabled, if the + // wxNB_MULTILINE style is used and the rectangle is very small, (such as + // when the notebook is first created.) The value of 20 is just + // arbitrarily chosen, if there is a better way to determine this value + // then please do so. --RD + if (rc.right > 20 && rc.bottom > 20) + { + TabCtrl_AdjustRect(m_hwnd, false, &rc); + page->SetSize(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); + } } // ---------------------------------------------------------------------------- @@ -500,8 +509,8 @@ wxNotebookPage *wxNotebook::DoRemovePage(size_t nPage) if (selNew != -1) { // No selection change, just refresh the current selection. - // Because it could be that the slection index changed - // we need to update it. + // Because it could be that the slection index changed + // we need to update it. // Note: this does not mean the selection it self changed. m_nSelection = selNew; m_pages[m_nSelection]->Refresh(); @@ -509,13 +518,13 @@ wxNotebookPage *wxNotebook::DoRemovePage(size_t nPage) else if (int(nPage) == m_nSelection) { // The selection was deleted. - + // Determine new selection. if (m_nSelection == int(GetPageCount())) selNew = m_nSelection - 1; else selNew = m_nSelection; - + // m_nSelection must be always valid so reset it before calling // SetSelection() m_nSelection = -1; @@ -544,6 +553,7 @@ bool wxNotebook::DeleteAllPages() m_nSelection = -1; + InvalidateBestSize(); return true; } @@ -561,27 +571,6 @@ bool wxNotebook::InsertPage(size_t nPage, wxASSERT_MSG( pPage->GetParent() == this, _T("notebook pages must have notebook as parent") ); -#if wxUSE_UXTHEME && wxUSE_UXTHEME_AUTO - static bool g_TestedForTheme = false; - static bool g_UseTheme = false; - if (!g_TestedForTheme) - { - int commCtrlVersion = wxTheApp->GetComCtl32Version() ; - - g_UseTheme = (commCtrlVersion >= 600); - g_TestedForTheme = true; - } - - // Automatically apply the theme background, - // changing the colour of the panel to match the - // tab page colour. This won't work well with all - // themes but it's a start. - if (g_UseTheme && wxUxThemeEngine::Get() && pPage->IsKindOf(CLASSINFO(wxPanel))) - { - ApplyThemeBackground(pPage, GetThemeBackgroundColour()); - } -#endif - // add a new tab to the control // ---------------------------- @@ -603,6 +592,16 @@ bool wxNotebook::InsertPage(size_t nPage, tcItem.pszText = (wxChar *)strText.c_str(); // const_cast } + // hide the page: unless it is selected, it shouldn't be shown (and if it + // is selected it will be shown later) + HWND hwnd = GetWinHwnd(pPage); + SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_VISIBLE); + + // this updates internal flag too -- otherwise it would get out of sync + // with the real state + pPage->Show(false); + + // fit the notebook page to the tab control's display area: this should be // done before adding it to the notebook or TabCtrl_InsertItem() will // change the notebooks size itself! @@ -628,16 +627,6 @@ bool wxNotebook::InsertPage(size_t nPage, AdjustPageSize(pPage); } - // hide the page: unless it is selected, it shouldn't be shown (and if it - // is selected it will be shown later) - HWND hwnd = GetWinHwnd(pPage); - SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_VISIBLE); - - // this updates internal flag too -- otherwise it would get out of sync - // with the real state - pPage->Show(false); - - // now deal with the selection // --------------------------- @@ -660,6 +649,7 @@ bool wxNotebook::InsertPage(size_t nPage, if ( selNew != -1 ) SetSelection(selNew); + InvalidateBestSize(); return true; } @@ -732,6 +722,10 @@ void wxNotebook::OnSize(wxSizeEvent& event) pPage->SetSize(rc.left, rc.top, width, height); } +#if wxUSE_UXTHEME + UpdateBgBrush(); +#endif // wxUSE_UXTHEME + event.Skip(); } @@ -866,6 +860,90 @@ void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event) } } +#if wxUSE_UXTHEME + +WXHANDLE wxNotebook::QueryBgBitmap(wxWindow *win) +{ + RECT rc; + GetWindowRect(GetHwnd(), &rc); + + WindowHDC hDC(GetHwnd()); + MemoryHDC hDCMem(hDC); + CompatibleBitmap hBmp(hDC, rc.right - rc.left, rc.bottom - rc.top); + + SelectInHDC selectBmp(hDCMem, hBmp); + + ::SendMessage(GetHwnd(), WM_PRINTCLIENT, + (WPARAM)(HDC)hDCMem, + PRF_ERASEBKGND | PRF_CLIENT | PRF_NONCLIENT); + + if ( win ) + { + RECT rc2; + ::GetWindowRect(GetHwndOf(win), &rc2); + + COLORREF c = ::GetPixel(hDCMem, rc2.left - rc.left, rc2.top - rc.top); + + return (WXHANDLE)c; + } + else // we are asked to create the brush + { + return (WXHANDLE)::CreatePatternBrush(hBmp); + } +} + +void wxNotebook::UpdateBgBrush() +{ + if ( m_hbrBackground ) + ::DeleteObject((HBRUSH)m_hbrBackground); + + if ( !m_hasBgCol && wxUxThemeEngine::GetIfActive() ) + { + m_hbrBackground = (WXHBRUSH)QueryBgBitmap(); + } + else // no themes + { + m_hbrBackground = NULL; + } +} + +WXHBRUSH wxNotebook::MSWGetBgBrushForChild(WXHDC hDC, wxWindow *win) +{ + if ( m_hbrBackground ) + { + // before drawing with the background brush, we need to position it + // correctly + RECT rc; + ::GetWindowRect(GetHwndOf(win), &rc); + + ::MapWindowPoints(NULL, GetHwnd(), (POINT *)&rc, 1); + + if ( !::SetBrushOrgEx((HDC)hDC, -rc.left, -rc.top, NULL) ) + { + wxLogLastError(_T("SetBrushOrgEx(notebook bg brush)")); + } + + return m_hbrBackground; + } + + return wxNotebookBase::MSWGetBgBrushForChild(hDC, win); +} + +wxColour wxNotebook::MSWGetBgColourForChild(wxWindow *win) +{ + if ( m_hasBgCol ) + return GetBackgroundColour(); + + if ( !wxUxThemeEngine::GetIfActive() ) + return wxNullColour; + + COLORREF c = (COLORREF)QueryBgBitmap(win); + + return c == CLR_INVALID ? wxNullColour : wxRGBToColour(c); +} + +#endif // wxUSE_UXTHEME + // ---------------------------------------------------------------------------- // wxNotebook base class virtuals // ---------------------------------------------------------------------------- @@ -930,85 +1008,4 @@ bool wxNotebook::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM* result) return processed; } -// Windows only: attempts to get colour for UX theme page background -wxColour wxNotebook::GetThemeBackgroundColour() -{ -#if wxUSE_UXTHEME - if (wxUxThemeEngine::Get()) - { - wxUxThemeHandle hTheme(this, L"TAB"); - if (hTheme) - { - // This is total guesswork. - // See PlatformSDK\Include\Tmschema.h for values - COLORREF themeColor; - wxUxThemeEngine::Get()->GetThemeColor( - hTheme, - 10 /* TABP_BODY */, - 1 /* NORMAL */, - 3802 /* color of bg fill */, - &themeColor); - - wxColour colour(GetRValue(themeColor), GetGValue(themeColor), GetBValue(themeColor)); - return colour; - } - } -#endif // wxUSE_UXTHEME - - return GetBackgroundColour(); -} - -// Windows only: attempts to apply the UX theme page background to this page -#if wxUSE_UXTHEME -void wxNotebook::ApplyThemeBackground(wxWindow* window, const wxColour& colour) -#else -void wxNotebook::ApplyThemeBackground(wxWindow*, const wxColour&) -#endif -{ -#if wxUSE_UXTHEME - - window->ApplyParentThemeBackground(colour); - - for ( wxWindowList::compatibility_iterator node = window->GetChildren().GetFirst(); node; node = node->GetNext() ) - { - wxWindow *child = node->GetData(); - ApplyThemeBackground(child, colour); - } -#endif -} - -#if wxUSE_UXTHEME -WXLRESULT wxNotebook::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) -{ - static bool g_TestedForTheme = false; - static bool g_supportsThemes = false; - switch ( nMsg ) - { - case WM_ERASEBKGND: - { - if (!g_TestedForTheme) - { - int commCtrlVersion = wxTheApp->GetComCtl32Version() ; - - g_supportsThemes = (commCtrlVersion >= 600); - g_TestedForTheme = true; - } - - // If currently an XP theme is active, it seems we can get away - // with not drawing a background, which reduces flicker. - if (g_supportsThemes) - { - wxUxThemeEngine *p = wxUxThemeEngine::Get(); - if (p && p->IsThemeActive() ) - { - return true; - } - } - } - } - - return wxControl::MSWWindowProc(nMsg, wParam, lParam); -} -#endif // #if wxUSE_UXTHEME - #endif // wxUSE_NOTEBOOK