added support for drawing themed background: DoEraseBackground() and GetThemeBackgroundBrush()

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@30631 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2004-11-19 18:36:45 +00:00
parent 8a462d4ee1
commit caf95d2aef
2 changed files with 100 additions and 145 deletions

View File

@@ -72,6 +72,7 @@ public:
const wxSize& size = wxDefaultSize,
long style = 0,
const wxString& name = wxNOTEBOOK_NAME);
virtual ~wxNotebook();
// accessors
// ---------
@@ -111,9 +112,6 @@ public:
// set the padding between tabs (in pixels)
void SetPadding(const wxSize& padding);
// Windows only: attempts to get colour for UX theme page background
wxColour GetThemeBackgroundColour();
// operations
// ----------
// remove all pages
@@ -134,9 +132,6 @@ public:
// style.
void SetTabSize(const wxSize& sz);
// Windows only: attempts to apply the UX theme page background to this page
void ApplyThemeBackground(wxWindow* window, const wxColour& colour);
// hit test
virtual int HitTest(const wxPoint& pt, long *flags = NULL) const;
@@ -162,6 +157,19 @@ public:
virtual bool DoPhase(int nPhase);
#endif // wxUSE_CONSTRAINTS
// implementation only
// -------------------
#if wxUSE_UXTHEME
// handler for child pages erase background event
void DoEraseBackground(wxEraseEvent& event);
// get the brush to be used for painting the background for the controls
// which need it in their MSWControlColor()
WXHBRUSH GetThemeBackgroundBrush() const { return m_hbrBackground; }
#endif // wxUSE_UXTHEME
protected:
// common part of all ctors
void Init();
@@ -175,15 +183,20 @@ protected:
// set the size of the given page to fit in the notebook
void AdjustPageSize(wxNotebookPage *page);
// override WndProc.
#if wxUSE_UXTHEME
virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
#endif
// creates the brush to be used for drawing the tab control background
void UpdateBgBrush();
#endif // wxUSE_UXTHEME
// the current selection (-1 if none)
int m_nSelection;
wxNotebookPageInfoList m_pageInfos ;
wxNotebookPageInfoList m_pageInfos;
#if wxUSE_UXTHEME
// background brush used to paint the tab control
WXHBRUSH m_hbrBackground;
#endif // wxUSE_UXTHEME
DECLARE_DYNAMIC_CLASS_NO_COPY(wxNotebook)

View File

@@ -54,18 +54,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
// ----------------------------------------------------------------------------
@@ -220,6 +209,10 @@ void wxNotebook::Init()
{
m_imageList = NULL;
m_nSelection = -1;
#if wxUSE_UXTHEME
m_hbrBackground = NULL;
#endif // wxUSE_UXTHEME
}
// default for dynamic class
@@ -270,8 +263,6 @@ bool wxNotebook::Create(wxWindow *parent,
if ( !MSWCreateControl(WC_TABCONTROL, wxEmptyString, pos, size) )
return false;
SetBackgroundColour(wxColour(::GetSysColor(COLOR_BTNFACE)));
return true;
}
@@ -304,6 +295,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
// ----------------------------------------------------------------------------
@@ -571,27 +570,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
// ----------------------------
@@ -743,6 +721,10 @@ void wxNotebook::OnSize(wxSizeEvent& event)
pPage->SetSize(rc.left, rc.top, width, height);
}
#if wxUSE_UXTHEME
UpdateBgBrush();
#endif // wxUSE_UXTHEME
event.Skip();
}
@@ -877,6 +859,66 @@ void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event)
}
}
#if wxUSE_UXTHEME
void wxNotebook::UpdateBgBrush()
{
if ( m_hbrBackground )
::DeleteObject((HBRUSH)m_hbrBackground);
if ( wxUxThemeEngine::GetIfActive() )
{
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);
m_hbrBackground = (WXHBRUSH)::CreatePatternBrush(hBmp);
}
else // no themes
{
m_hbrBackground = NULL;
}
}
void wxNotebook::DoEraseBackground(wxEraseEvent& event)
{
// we can either draw the background ourselves or let DrawThemeBackground()
// do it, but as we already have the correct brush, let's do it ourselves
// (note that we use the same code in wxControl::MSWControlColor(), so if
// it breaks, it should at least break in consistent way)
if ( m_hbrBackground )
{
// before drawing with the background brush, we need to position it
// correctly
wxWindow *win = (wxWindow *)event.GetEventObject();
RECT rc;
::GetWindowRect(GetHwndOf(win), &rc);
::MapWindowPoints(NULL, GetHwnd(), (POINT *)&rc, 1);
HDC hdc = GetHdcOf(*event.GetDC());
if ( !::SetBrushOrgEx(hdc, -rc.left, -rc.top, NULL) )
{
wxLogLastError(_T("SetBrushOrgEx(notebook bg brush)"));
}
RECT rectClient;
::GetClientRect(GetHwndOf(win), &rectClient);
::FillRect(hdc, &rectClient, (HBRUSH)m_hbrBackground);
}
}
#endif // wxUSE_UXTHEME
// ----------------------------------------------------------------------------
// wxNotebook base class virtuals
// ----------------------------------------------------------------------------
@@ -941,104 +983,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 */,
3821 /* FILLCOLORHINT */,
&themeColor);
/*
[DS] Workaround for WindowBlinds:
Some themes return a near black theme color using FILLCOLORHINT,
this makes notebook pages have an ugly black background and makes
text (usually black) unreadable. Retry again with FILLCOLOR.
This workaround potentially breaks appearance of some themes,
but in practice it already fixes some themes.
*/
if (themeColor == 1)
{
wxUxThemeEngine::Get()->GetThemeColor(
hTheme,
10 /* TABP_BODY */,
1 /* NORMAL */,
3802 /* FILLCOLOR */,
&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