Forward port of changes for using themed drawing of owner-drawn buttons.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@39488 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn 2006-05-31 21:26:39 +00:00
parent 876cd6f7e3
commit 4e9da8b79e
2 changed files with 336 additions and 47 deletions

View File

@ -27,7 +27,27 @@
#include "wx/msw/private.h"
#include "wx/image.h"
#include "wx/msw/uxtheme.h"
#if wxUSE_UXTHEME
#include "wx/msw/uxtheme.h"
// no need to include tmschema.h
#ifndef BP_PUSHBUTTON
#define BP_PUSHBUTTON 1
#define PBS_NORMAL 1
#define PBS_HOT 2
#define PBS_PRESSED 3
#define PBS_DISABLED 4
#define PBS_DEFAULTED 5
#define TMT_CONTENTMARGINS 3602
#endif
#endif // wxUSE_UXTHEME
#ifndef ODS_NOFOCUSRECT
#define ODS_NOFOCUSRECT 0x0200
#endif
// ----------------------------------------------------------------------------
// macros
@ -119,8 +139,6 @@ bool wxBitmapButton::Create(wxWindow *parent, wxWindowID id,
parent->AddChild(this);
m_backgroundColour = parent->GetBackgroundColour();
m_foregroundColour = parent->GetForegroundColour();
m_windowStyle = style;
if ( style & wxBU_AUTODRAW )
@ -226,6 +244,79 @@ void wxBitmapButton::OnSetBitmap()
wxBitmapButtonBase::OnSetBitmap();
}
#if wxUSE_UXTHEME
static
void MSWDrawXPBackground(wxButton *button, WXDRAWITEMSTRUCT *wxdis)
{
LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)wxdis;
HDC hdc = lpDIS->hDC;
UINT state = lpDIS->itemState;
RECT rectBtn;
CopyRect(&rectBtn, &lpDIS->rcItem);
wxUxThemeHandle theme(button, L"BUTTON");
int iState;
if ( state & ODS_SELECTED )
{
iState = PBS_PRESSED;
}
else if ( button->HasCapture() || button->IsMouseInWindow() )
{
iState = PBS_HOT;
}
else if ( state & ODS_FOCUS )
{
iState = PBS_DEFAULTED;
}
else if ( state & ODS_DISABLED )
{
iState = PBS_DISABLED;
}
else
{
iState = PBS_NORMAL;
}
// draw parent background if needed
if ( wxUxThemeEngine::Get()->IsThemeBackgroundPartiallyTransparent(theme,
BP_PUSHBUTTON,
iState) )
{
wxUxThemeEngine::Get()->DrawThemeParentBackground(GetHwndOf(button), hdc, &rectBtn);
}
// draw background
wxUxThemeEngine::Get()->DrawThemeBackground(theme, hdc, BP_PUSHBUTTON, iState,
&rectBtn, NULL);
// calculate content area margins
MARGINS margins;
wxUxThemeEngine::Get()->GetThemeMargins(theme, hdc, BP_PUSHBUTTON, iState,
TMT_CONTENTMARGINS, &rectBtn, &margins);
RECT rectClient;
::CopyRect(&rectClient, &rectBtn);
::InflateRect(&rectClient, -margins.cxLeftWidth, -margins.cyTopHeight);
// if focused and !nofocus rect
if ( (state & ODS_FOCUS) && !(state & ODS_NOFOCUSRECT) )
{
DrawFocusRect(hdc, &rectClient);
}
if ( button->UseBgCol() )
{
COLORREF colBg = wxColourToRGB(button->GetBackgroundColour());
HBRUSH hbrushBackground = ::CreateSolidBrush(colBg);
// don't overwrite the focus rect
::InflateRect(&rectClient, -1, -1);
FillRect(hdc, &rectClient, hbrushBackground);
::DeleteObject(hbrushBackground);
}
}
#endif // wxUSE_UXTHEME
// VZ: should be at the very least less than wxDEFAULT_BUTTON_MARGIN
#define FOCUS_MARGIN 3
@ -273,6 +364,58 @@ bool wxBitmapButton::MSWOnDraw(WXDRAWITEMSTRUCT *item)
int wBmp = bitmap->GetWidth();
int hBmp = bitmap->GetHeight();
#if wxUSE_UXTHEME
if ( autoDraw && wxUxThemeEngine::GetIfActive() )
{
MSWDrawXPBackground(this, item);
wxUxThemeHandle theme(this, L"BUTTON");
// calculate content area margins
// assuming here that each state is the same size
MARGINS margins;
wxUxThemeEngine::Get()->GetThemeMargins(theme, NULL,
BP_PUSHBUTTON, PBS_NORMAL,
TMT_CONTENTMARGINS, NULL,
&margins);
int marginX = margins.cxLeftWidth + 1;
int marginY = margins.cyTopHeight + 1;
int x1,y1;
if ( m_windowStyle & wxBU_LEFT )
{
x1 = x + marginX;
}
else if ( m_windowStyle & wxBU_RIGHT )
{
x1 = x + (width - wBmp) - marginX;
}
else
{
x1 = x + (width - wBmp) / 2;
}
if ( m_windowStyle & wxBU_TOP )
{
y1 = y + marginY;
}
else if ( m_windowStyle & wxBU_BOTTOM )
{
y1 = y + (height - hBmp) - marginY;
}
else
{
y1 = y + (height - hBmp) / 2;
}
// draw the bitmap
wxClientDC dst;
dst.SetHDC((WXHDC) hDC, false);
dst.DrawBitmap(*bitmap, x1, y1, true);
return true;
}
#endif // wxUSE_UXTHEME
int x1,y1;
if(m_windowStyle & wxBU_LEFT)
@ -346,10 +489,7 @@ void wxBitmapButton::DrawFace( WXHDC dc, int left, int top,
penLight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DLIGHT));
penShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DSHADOW));
penDkShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DDKSHADOW));
// brushFace = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
// Taking the background colour fits in better with
// Windows XP themes.
brushFace = CreateSolidBrush(m_backgroundColour.m_pixel);
brushFace = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
// draw the rectangle
RECT rect;
@ -452,6 +592,25 @@ wxSize wxBitmapButton::DoGetBestSize() const
{
if ( m_bmpNormal.Ok() )
{
#if wxUSE_UXTHEME
if ( (GetWindowStyleFlag() & wxBU_AUTODRAW) && wxUxThemeEngine::GetIfActive() )
{
wxUxThemeHandle theme((wxBitmapButton *)this, L"BUTTON");
// calculate content area margins
// assuming here that each state is the same size
MARGINS margins;
wxUxThemeEngine::Get()->GetThemeMargins(theme, NULL,
BP_PUSHBUTTON, PBS_NORMAL,
TMT_CONTENTMARGINS, NULL,
&margins);
wxSize best(m_bmpNormal.GetWidth() + 2 * (margins.cxLeftWidth + 1),
m_bmpNormal.GetHeight() + 2* (margins.cyTopHeight + 1));
CacheBestSize(best);
return best;
}
#endif // wxUSE_UXTHEME
wxSize best(m_bmpNormal.GetWidth() + 2*m_marginX,
m_bmpNormal.GetHeight() + 2*m_marginY);
CacheBestSize(best);

View File

@ -42,6 +42,35 @@
#include "wx/tokenzr.h"
#include "wx/msw/private.h"
#if wxUSE_UXTHEME
#include "wx/msw/uxtheme.h"
// no need to include tmschema.h
#ifndef BP_PUSHBUTTON
#define BP_PUSHBUTTON 1
#define PBS_NORMAL 1
#define PBS_HOT 2
#define PBS_PRESSED 3
#define PBS_DISABLED 4
#define PBS_DEFAULTED 5
#define TMT_CONTENTMARGINS 3602
#endif
#endif // wxUSE_UXTHEME
#ifndef WM_THEMECHANGED
#define WM_THEMECHANGED 0x031A
#endif
#ifndef ODS_NOACCEL
#define ODS_NOACCEL 0x0100
#endif
#ifndef ODS_NOFOCUSRECT
#define ODS_NOFOCUSRECT 0x0200
#endif
// ----------------------------------------------------------------------------
// macros
// ----------------------------------------------------------------------------
@ -474,6 +503,27 @@ WXLRESULT wxButton::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
// and continue with processing the message normally as well
}
#if wxUSE_UXTHEME
else if ( nMsg == WM_THEMECHANGED )
{
// need to recalculate the best size here
// as the theme size might have changed
InvalidateBestSize();
}
else if ( wxUxThemeEngine::GetIfActive() )
{
// we need to Refresh() if mouse has entered or left window
// so we can update the hot tracking state
// must use m_mouseInWindow here instead of IsMouseInWindow()
// since we need to know the first time the mouse enters the window
// and IsMouseInWindow() would return true in this case
if ( ( nMsg == WM_MOUSEMOVE && !m_mouseInWindow ) ||
nMsg == WM_MOUSELEAVE )
{
Refresh();
}
}
#endif // wxUSE_UXTHEME
// let the base class do all real processing
return wxControl::MSWWindowProc(nMsg, wParam, lParam);
@ -667,23 +717,101 @@ static void DrawButtonFrame(HDC hdc, const RECT& rectBtn,
DeleteObject(hpenBlack);
}
bool wxButton::MSWOnDraw(WXDRAWITEMSTRUCT *wxdis)
#if wxUSE_UXTHEME
static
void MSWDrawXPBackground(wxButton *button, WXDRAWITEMSTRUCT *wxdis)
{
LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)wxdis;
HDC hdc = lpDIS->hDC;
UINT state = lpDIS->itemState;
RECT rectBtn;
CopyRect(&rectBtn, &lpDIS->rcItem);
COLORREF colBg = wxColourToRGB(GetBackgroundColour()),
colFg = wxColourToRGB(GetForegroundColour());
wxUxThemeHandle theme(button, L"BUTTON");
int iState;
if ( state & ODS_SELECTED )
{
iState = PBS_PRESSED;
}
else if ( button->HasCapture() || button->IsMouseInWindow() )
{
iState = PBS_HOT;
}
else if ( state & ODS_FOCUS )
{
iState = PBS_DEFAULTED;
}
else if ( state & ODS_DISABLED )
{
iState = PBS_DISABLED;
}
else
{
iState = PBS_NORMAL;
}
// draw parent background if needed
if ( wxUxThemeEngine::Get()->IsThemeBackgroundPartiallyTransparent(theme,
BP_PUSHBUTTON,
iState) )
{
wxUxThemeEngine::Get()->DrawThemeParentBackground(GetHwndOf(button), hdc, &rectBtn);
}
// draw background
wxUxThemeEngine::Get()->DrawThemeBackground(theme, hdc, BP_PUSHBUTTON, iState,
&rectBtn, NULL);
// calculate content area margins
MARGINS margins;
wxUxThemeEngine::Get()->GetThemeMargins(theme, hdc, BP_PUSHBUTTON, iState,
TMT_CONTENTMARGINS, &rectBtn, &margins);
RECT rectClient;
::CopyRect(&rectClient, &rectBtn);
::InflateRect(&rectClient, -margins.cxLeftWidth, -margins.cyTopHeight);
// if focused and !nofocus rect
if ( (state & ODS_FOCUS) && !(state & ODS_NOFOCUSRECT) )
{
DrawFocusRect(hdc, &rectClient);
}
if ( button->UseBgCol() )
{
COLORREF colBg = wxColourToRGB(button->GetBackgroundColour());
HBRUSH hbrushBackground = ::CreateSolidBrush(colBg);
// don't overwrite the focus rect
::InflateRect(&rectClient, -1, -1);
FillRect(hdc, &rectClient, hbrushBackground);
::DeleteObject(hbrushBackground);
}
}
#endif // wxUSE_UXTHEME
bool wxButton::MSWOnDraw(WXDRAWITEMSTRUCT *wxdis)
{
LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)wxdis;
HDC hdc = lpDIS->hDC;
UINT state = lpDIS->itemState;
RECT rectBtn;
CopyRect(&rectBtn, &lpDIS->rcItem);
#if wxUSE_UXTHEME
if ( wxUxThemeEngine::GetIfActive() )
{
MSWDrawXPBackground(this, wxdis);
}
else
#endif // wxUSE_UXTHEME
{
COLORREF colBg = wxColourToRGB(GetBackgroundColour());
// first, draw the background
HBRUSH hbrushBackground = ::CreateSolidBrush(colBg);
FillRect(hdc, &rectBtn, hbrushBackground);
::DeleteObject(hbrushBackground);
// draw the border for the current state
bool selected = (state & ODS_SELECTED) != 0;
@ -699,8 +827,8 @@ bool wxButton::MSWOnDraw(WXDRAWITEMSTRUCT *wxdis)
DrawButtonFrame(hdc, rectBtn, selected, pushed);
// draw the focus rect if needed
if ( state & ODS_FOCUS )
// if focused and !nofocus rect
if ( (state & ODS_FOCUS) && !(state & ODS_NOFOCUSRECT) )
{
RECT rectFocus;
CopyRect(&rectFocus, &rectBtn);
@ -717,13 +845,15 @@ bool wxButton::MSWOnDraw(WXDRAWITEMSTRUCT *wxdis)
// the label is shifted by 1 pixel to create "pushed" effect
OffsetRect(&rectBtn, 1, 1);
}
}
DrawButtonText(hdc, &rectBtn, GetLabel(),
COLORREF colFg = wxColourToRGB(GetForegroundColour());
DrawButtonText(hdc, &rectBtn,
(state & ODS_NOACCEL ? wxStripMenuCodes(GetLabel())
: GetLabel()),
state & ODS_DISABLED ? GetSysColor(COLOR_GRAYTEXT)
: colFg);
::DeleteObject(hbrushBackground);
return true;
}