#include "wx/msw/uxtheme.h"
#include "wx/msw/private.h"
#include "wx/msw/missing.h"
+#include "wx/msw/dc.h"
+
+// the values coincide with those in tmschema.h
+#define BP_GROUPBOX 4
+
+#define GBS_NORMAL 1
+
+#define TMT_FONT 210
// ----------------------------------------------------------------------------
// wxWin macros
return true;
}
-wxBorder wxStaticBox::GetDefaultBorder() const
-{
- return wxBORDER_NONE;
-}
-
WXDWORD wxStaticBox::MSWGetStyle(long style, WXDWORD *exstyle) const
{
long styleWin = wxStaticBoxBase::MSWGetStyle(style, exstyle);
return 0;
}
+ if ( nMsg == WM_UPDATEUISTATE )
+ {
+ // DefWindowProc() redraws just the static box text when it gets this
+ // message and it does it using the standard (blue in standard theme)
+ // colour and not our own label colour that we use in PaintForeground()
+ // resulting in the label mysteriously changing the colour when e.g.
+ // "Alt" is pressed anywhere in the window, see #12497.
+ //
+ // To avoid this we simply refresh the window forcing our own code
+ // redrawing the label in the correct colour to be called. This is
+ // inefficient but there doesn't seem to be anything else we can do.
+ //
+ // Notice that the problem is XP-specific and doesn't arise under later
+ // systems.
+ if ( m_hasFgCol && wxGetWinVersion() == wxWinVersion_XP )
+ Refresh();
+ }
+
return wxControl::MSWWindowProc(nMsg, wParam, lParam);
}
AutoHRGN hrgnRect(::CreateRectRgn(left, top, right, bottom));
if ( !hrgnRect )
{
- wxLogLastError(_T("CreateRectRgn()"));
+ wxLogLastError(wxT("CreateRectRgn()"));
return;
}
// we did it
// 3. this is backwards compatible behaviour and some people rely on it,
// see http://groups.google.com/groups?selm=4252E932.3080801%40able.es
- wxWindow *parent = GetParent();
- HBRUSH hbr = (HBRUSH)parent->MSWGetBgBrush(dc.GetHDC(), GetHWND());
+ wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
+ HBRUSH hbr = MSWGetBgBrush(impl->GetHDC());
// if there is no special brush for painting this control, just use the
// solid background colour
wxBrush brush;
if ( !hbr )
{
- brush = wxBrush(parent->GetBackgroundColour());
+ brush = wxBrush(GetParent()->GetBackgroundColour());
hbr = GetHbrushOf(brush);
}
- ::FillRect(GetHdcOf(dc), &rc, hbr);
+ ::FillRect(GetHdcOf(*impl), &rc, hbr);
}
void wxStaticBox::PaintForeground(wxDC& dc, const RECT& rc)
{
- MSWDefWindowProc(WM_PAINT, (WPARAM)GetHdcOf(dc), 0);
+ wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
+ MSWDefWindowProc(WM_PAINT, (WPARAM)GetHdcOf(*impl), 0);
// when using XP themes, neither setting the text colour nor transparent
// background mode doesn't change anything: the static box def window proc
// still draws the label in its own colours, so we need to redraw the text
// ourselves if we have a non default fg colour
- if ( wxUxThemeEngine::GetIfActive() )
+ if ( m_hasFgCol && wxUxThemeEngine::GetIfActive() )
{
// draw over the text in default colour in our colour
- dc.SetFont(GetFont());
+ HDC hdc = GetHdcOf(*impl);
+ ::SetTextColor(hdc, GetForegroundColour().GetPixel());
- HDC hdc = GetHdcOf(dc);
- if ( m_hasFgCol )
+ const bool rtl = wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft;
+ if ( rtl )
+ ::SetTextAlign(hdc, TA_RTLREADING | TA_RIGHT);
+
+ // Get dimensions of the label
+ const wxString label = GetLabel();
+
+ // choose the correct font
+ AutoHFONT font;
+ SelectInHDC selFont;
+ if ( m_hasFont )
{
- ::SetTextColor(hdc, GetForegroundColour().GetPixel());
+ selFont.Init(hdc, GetHfontOf(GetFont()));
}
- else
+ else // no font set, use the one set by the theme
{
wxUxThemeHandle hTheme(this, L"BUTTON");
- if (hTheme)
- {
- COLORREF col;
- wxUxThemeEngine::Get()->GetThemeColor(
- hTheme,
- 4 /* BP_GROUPBOX */,
- 1 /* GBS_NORMAL */,
- 3803 /* TMT_TEXTCOLOR */,
- &col);
-
- ::SetTextColor(hdc, col);
- }
- else
+ if ( hTheme )
{
- // can't open the theme - default to blue
- ::SetTextColor(hdc, 0x00D54600);
+ wxUxThemeFont themeFont;
+ if ( wxUxThemeEngine::Get()->GetThemeFont
+ (
+ hTheme,
+ hdc,
+ BP_GROUPBOX,
+ GBS_NORMAL,
+ TMT_FONT,
+ themeFont.GetPtr()
+ ) == S_OK )
+ {
+ font.Init(themeFont.GetLOGFONT());
+ if ( font )
+ selFont.Init(hdc, font);
+ }
}
}
- // FIXME: value of x is hardcoded as this is what it is on my system,
- // no idea if it's true everywhere
-
- const bool rtl = wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft;
- if ( rtl )
- ::SetTextAlign(hdc, TA_RTLREADING | TA_RIGHT);
-
- // Get dimensions of the label
- const wxString label = GetLabel();
+ // Get the font extent
int width, height;
- dc.GetTextExtent(wxStripMenuCodes(label, wxStrip_Mnemonics), &width, &height);
+ dc.GetTextExtent(wxStripMenuCodes(label, wxStrip_Mnemonics),
+ &width, &height);
int x;
int y = height;
// first we need to correctly paint the background of the label
// as Windows ignores the brush offset when doing it
+ //
+ // FIXME: value of x is hardcoded as this is what it is on my system,
+ // no idea if it's true everywhere
RECT dimensions = {0, 0, 0, y};
if ( !rtl )
{
dimensions.left -= 2;
dimensions.right += 2;
dimensions.bottom += 2;
- PaintBackground(dc, dimensions);
+
+ if ( UseBgCol() )
+ {
+ // our own background colour should be used for the background of
+ // the label: this is consistent with the behaviour under pre-XP
+ // systems (i.e. without visual themes) and generally makes sense
+ wxBrush brush = wxBrush(GetBackgroundColour());
+ wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
+ ::FillRect(GetHdcOf(*impl), &dimensions, GetHbrushOf(brush));
+ }
+ else // paint parent background
+ {
+ PaintBackground(dc, dimensions);
+ }
+
+ UINT drawTextFlags = DT_SINGLELINE | DT_VCENTER;
+
+ // determine the state of UI queues to draw the text correctly under XP
+ // and later systems
+ static const bool isXPorLater = wxGetWinVersion() >= wxWinVersion_XP;
+ if ( isXPorLater )
+ {
+ if ( ::SendMessage(GetHwnd(), WM_QUERYUISTATE, 0, 0) &
+ UISF_HIDEACCEL )
+ {
+ drawTextFlags |= DT_HIDEPREFIX;
+ }
+ }
// now draw the text
if ( !rtl )
{
RECT rc2 = { x, 0, x + width, y };
- ::DrawText(hdc, label, label.length(), &rc2,
- DT_SINGLELINE | DT_VCENTER);
+ ::DrawText(hdc, label.wx_str(), label.length(), &rc2,
+ drawTextFlags);
}
else // RTL
{
RECT rc2 = { x, 0, x - width, y };
- ::DrawText(hdc, label, label.length(), &rc2,
- DT_SINGLELINE | DT_VCENTER | DT_RTLREADING);
+ ::DrawText(hdc, label.wx_str(), label.length(), &rc2,
+ drawTextFlags | DT_RTLREADING);
}
}
}
dc.Blit(border, 0, rc.right - border, borderTop,
&memdc, border, 0);
// bottom
- dc.Blit(border, rc.bottom - border, rc.right - border, rc.bottom,
+ dc.Blit(border, rc.bottom - border, rc.right - border, border,
&memdc, border, rc.bottom - border);
// left
dc.Blit(0, 0, border, rc.bottom,
&memdc, 0, 0);
- // right
- dc.Blit(rc.right - border, 0, rc.right, rc.bottom,
- &memdc, rc.right - border, 0);
+ // right (note that upper and bottom right corners were already part of the
+ // first two blits so we shouldn't overwrite them here to avoi flicker)
+ dc.Blit(rc.right - border, borderTop,
+ border, rc.bottom - borderTop - border,
+ &memdc, rc.right - border, borderTop);
// create the region excluding box children
// and also the box itself
MSWGetRegionWithoutSelf((WXHRGN) hrgn, rc.right, rc.bottom);
- HDCClipper clipToBg(GetHdcOf(dc), hrgn);
+ wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
+ HDCClipper clipToBg(GetHdcOf(*impl), hrgn);
// paint the inside of the box (excluding box itself and child controls)
PaintBackground(dc, rc);