bool wxNotebook::MSWPrintChild(WXHDC hDC, wxWindow *child) { // solid background colour overrides themed background drawing if ( !UseBgCol() && DoDrawBackground(hDC, child) ) return true; // If we're using a solid colour (for example if we've switched off // theming for this notebook), paint it if (UseBgCol()) { wxRect r = GetPageSize(); if ( r.IsEmpty() ) return false; RECT rc; wxCopyRectToRECT(r, rc); // map rect to the coords of the window we're drawing in if ( child ) ::MapWindowPoints(GetHwnd(), GetHwndOf(child), (POINT *)&rc, 2); wxBrush brush(GetBackgroundColour()); HBRUSH hbr = GetHbrushOf(brush); ::FillRect((HDC) hDC, &rc, hbr); return true; } return wxNotebookBase::MSWPrintChild(hDC, child); }
WXHBRUSH wxScrollBar::MSWControlColor(WXHDC pDC, WXHWND hWnd) { // unless we have an explicitly set bg colour, use default (gradient under // XP) brush instead of GetBackgroundColour() one as the base class would // // note that fg colour isn't used for a scrollbar return UseBgCol() ? wxControl::MSWControlColor(pDC, hWnd) : NULL; }
void wxPanel::DoSetBackgroundBitmap(const wxBitmap& bmp) { delete m_backgroundBrush; m_backgroundBrush = bmp.IsOk() ? new wxBrush(bmp) : NULL; // Our transparent children should use our background if we have it, // otherwise try to restore m_inheritBgCol to some reasonable value: true // if we also have non-default background colour or false otherwise. m_inheritBgCol = bmp.IsOk() || UseBgCol(); }
bool wxWindow::DoDrawBackground(wxDC& dc) { wxRect rect; wxSize size = GetSize(); // Why not GetClientSize() ? rect.x = 0; rect.y = 0; rect.width = size.x; rect.height = size.y; wxWindow * const parent = GetParent(); if ( HasTransparentBackground() && !UseBgCol() && parent ) { // DirectFB paints the parent first, then its child windows, so by // the time this code is called, parent's background was already // drawn and there's no point in (imperfectly!) duplicating the work // here: #ifndef __WXDFB__ wxASSERT( !IsTopLevel() ); wxPoint pos = GetPosition(); AdjustForParentClientOrigin( pos.x, pos.y, 0 ); // Adjust DC logical origin wxCoord org_x, org_y, x, y; dc.GetLogicalOrigin( &org_x, &org_y ); x = org_x + pos.x; y = org_y + pos.y; dc.SetLogicalOrigin( x, y ); // Adjust draw rect rect.x = pos.x; rect.y = pos.y; // Let parent draw the background parent->EraseBackground( dc, rect ); // Restore DC logical origin dc.SetLogicalOrigin( org_x, org_y ); #endif // !__WXDFB__ } else { // Draw background ourselves EraseBackground( dc, rect ); } return true; }
void wxStaticBitmap::DoPaintManually(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(this); const wxSize size(GetSize()); const wxBitmap bmp(GetBitmap()); // Clear the background: notice that we're supposed to be transparent, so // use the parent background colour if we don't have our own instead of // falling back to the default const wxWindow *win = UseBgCol() ? this : GetParent(); dc.SetBrush(win->GetBackgroundColour()); dc.SetPen(*wxTRANSPARENT_PEN); dc.DrawRectangle(0, 0, size.GetWidth(), size.GetHeight()); // Draw the image in the middle dc.DrawBitmap(bmp, (size.GetWidth() - bmp.GetWidth()) / 2, (size.GetHeight() - bmp.GetHeight()) / 2, true /* use mask */); }
// Responds to colour changes, and passes event on to children. void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event) { // Don't override the colour explicitly set by the user, if any. if ( !UseBgCol() ) { SetOwnBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE)); Refresh(); } #if wxUSE_STATUSBAR if ( m_frameStatusBar ) { wxSysColourChangedEvent event2; event2.SetEventObject( m_frameStatusBar ); m_frameStatusBar->HandleWindowEvent(event2); } #endif // wxUSE_STATUSBAR // Propagate the event to the non-top-level children wxWindow::OnSysColourChanged(event); }
void wxNotebook::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(this); wxMemoryDC memdc; RECT rc; ::GetClientRect(GetHwnd(), &rc); wxBitmap bmp(rc.right, rc.bottom); memdc.SelectObject(bmp); const wxLayoutDirection dir = dc.GetLayoutDirection(); memdc.SetLayoutDirection(dir); const HDC hdc = GetHdcOf(memdc); // The drawing logic of the native tab control is absolutely impenetrable // but observation shows that in the current Windows versions (XP and 7), // the tab control always erases its entire background in its window proc // when the tabs are top-aligned but does not do it when the tabs are in // any other position. // // This means that we can't rely on our background colour being used for // the blank area in the tab row because this doesn't work in the default // top-aligned case, hence the hack with ExtFloodFill() below. But it also // means that we still do need to erase the DC to account for the other // cases. // // Moreover, just in case some very old or very new (or even future, // although it seems unlikely that this is ever going to change by now) // version of Windows didn't do it like this, do both things in all cases // instead of optimizing away the one of them which doesn't do anything for // the effectively used tab orientation -- better safe than fast. // Notice that we use our own background here, not the background used for // the pages, because the tab row background must blend with the parent and // so the background colour inherited from it (if any) must be used. AutoHBRUSH hbr(wxColourToRGB(GetBackgroundColour())); ::FillRect(hdc, &rc, hbr); MSWDefWindowProc(WM_PAINT, (WPARAM)hdc, 0); // At least for the top-aligned tabs, our background colour was overwritten // and so we now replace the default background with our colour. This is // horribly inefficient, of course, but seems to be the only way to do it. if ( UseBgCol() ) { SelectInHDC selectBrush(hdc, hbr); // Find the point which must contain the default background colour: // this is a hack, of course, but using this point "close" to the // corner seems to work fine in practice. int x = 0, y = 0; switch ( GetWindowStyle() & wxBK_ALIGN_MASK ) { case wxBK_TOP: x = rc.right - 2; y = 2; break; case wxBK_BOTTOM: x = rc.right - 2; y = rc.bottom - 2; break; case wxBK_LEFT: x = 2; y = rc.bottom - 2; break; case wxBK_RIGHT: x = 2; y = rc.bottom - 2; break; } ::ExtFloodFill(hdc, x, y, ::GetSysColor(COLOR_BTNFACE), FLOODFILLSURFACE); } // For some reason in RTL mode, source offset has to be -1, otherwise the // right border (physical) remains unpainted. const wxCoord ofs = dir == wxLayout_RightToLeft ? -1 : 0; dc.Blit(ofs, 0, rc.right, rc.bottom, &memdc, ofs, 0); }
// Create() function bool wxNotebook::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) { if ( (style & wxBK_ALIGN_MASK) == wxBK_DEFAULT ) { #if defined(__POCKETPC__) style |= wxBK_BOTTOM | wxNB_FLAT; #else style |= wxBK_TOP; #endif } #ifdef __WXWINCE__ // Not sure why, but without this style, there is no border // around the notebook tabs. if (style & wxNB_FLAT) style |= wxBORDER_SUNKEN; #endif #if !wxUSE_UXTHEME // ComCtl32 notebook tabs simply don't work unless they're on top if we // have uxtheme, we can work around it later (after control creation), but // if we have been compiled without uxtheme support, we have to clear those // styles if ( HasTroubleWithNonTopTabs() ) { style &= ~(wxBK_BOTTOM | wxBK_LEFT | wxBK_RIGHT); } #endif //wxUSE_UXTHEME #if defined(__WINE__) && wxUSE_UNICODE LPCTSTR className = L"SysTabControl32"; #else LPCTSTR className = WC_TABCONTROL; #endif #if USE_NOTEBOOK_ANTIFLICKER // SysTabCtl32 class has natively CS_HREDRAW and CS_VREDRAW enabled and it // causes horrible flicker when resizing notebook, so get rid of it by // using a class without these styles (but otherwise identical to it) if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE) ) { static ClassRegistrar s_clsNotebook; if ( !s_clsNotebook.IsInitialized() ) { // get a copy of standard class and modify it WNDCLASS wc; if ( ::GetClassInfo(NULL, WC_TABCONTROL, &wc) ) { gs_wndprocNotebook = reinterpret_cast<WXFARPROC>(wc.lpfnWndProc); wc.lpszClassName = wxT("_wx_SysTabCtl32"); wc.style &= ~(CS_HREDRAW | CS_VREDRAW); wc.hInstance = wxGetInstance(); wc.lpfnWndProc = wxNotebookWndProc; s_clsNotebook.Register(wc); } else { wxLogLastError(wxT("GetClassInfoEx(SysTabCtl32)")); } } // use our custom class if available but fall back to the standard // notebook if we failed to register it if ( s_clsNotebook.IsRegistered() ) { // it's ok to use c_str() here as the static s_clsNotebook object // has sufficiently long lifetime className = s_clsNotebook.GetName().c_str(); } } #endif // USE_NOTEBOOK_ANTIFLICKER if ( !CreateControl(parent, id, pos, size, style | wxTAB_TRAVERSAL, wxDefaultValidator, name) ) return false; if ( !MSWCreateControl(className, wxEmptyString, pos, size) ) return false; // Inherit parent attributes and, unlike the default, also inherit the // parent background colour in order to blend in with its background if // it's set to a non-default value. InheritAttributes(); if ( parent->InheritsBackgroundColour() && !UseBgCol() ) SetBackgroundColour(parent->GetBackgroundColour()); #if wxUSE_UXTHEME if ( HasFlag(wxNB_NOPAGETHEME) || wxSystemOptions::IsFalse(wxT("msw.notebook.themed-background")) ) { SetBackgroundColour(GetThemeBackgroundColour()); } else // use themed background by default { // create backing store UpdateBgBrush(); } // comctl32.dll 6.0 doesn't support non-top tabs with visual styles (the // control is simply not rendered correctly), so we disable themes // if possible, otherwise we simply clear the styles. if ( HasTroubleWithNonTopTabs() && (style & (wxBK_BOTTOM | wxBK_LEFT | wxBK_RIGHT)) ) { // check if we use themes at all -- if we don't, we're still okay if ( wxUxThemeEngine::GetIfActive() ) { wxUxThemeEngine::GetIfActive()->SetWindowTheme(GetHwnd(), L"", L""); // correct the background color for the new non-themed control SetBackgroundColour(GetThemeBackgroundColour()); } } #endif // wxUSE_UXTHEME // Undocumented hack to get flat notebook style // In fact, we should probably only do this in some // curcumstances, i.e. if we know we will have a border // at the bottom (the tab control doesn't draw it itself) #if defined(__POCKETPC__) || defined(__SMARTPHONE__) if (HasFlag(wxNB_FLAT)) { SendMessage(GetHwnd(), CCM_SETVERSION, COMCTL32_VERSION, 0); if (!m_hasBgCol) SetBackgroundColour(*wxWHITE); } #endif return true; }
void wxStaticBox::PaintForeground(wxDC& dc, const RECT& rc) { 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 ( m_hasFgCol && wxUxThemeEngine::GetIfActive() ) { // draw over the text in default colour in our colour HDC hdc = GetHdcOf(*impl); ::SetTextColor(hdc, GetForegroundColour().GetPixel()); 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 ) { selFont.Init(hdc, GetHfontOf(GetFont())); } else // no font set, use the one set by the theme { wxUxThemeHandle hTheme(this, L"BUTTON"); if ( hTheme ) { 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); } } } // Get the font extent int 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 ) { x = 9; dimensions.left = x; dimensions.right = x + width; } else { x = rc.right - 7; dimensions.left = x - width; dimensions.right = x; } // need to adjust the rectangle to cover all the label background dimensions.left -= 2; dimensions.right += 2; dimensions.bottom += 2; 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.t_str(), label.length(), &rc2, drawTextFlags); } else // RTL { RECT rc2 = { x, 0, x - width, y }; ::DrawText(hdc, label.t_str(), label.length(), &rc2, drawTextFlags | DT_RTLREADING); } } }
void wxStaticBox::PaintForeground(wxDC& dc, const RECT& rc) { 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 ( m_hasFgCol && wxUxThemeEngine::GetIfActive() ) { // draw over the text in default colour in our colour HDC hdc = GetHdcOf(*impl); ::SetTextColor(hdc, GetForegroundColour().GetPixel()); 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 ) { selFont.Init(hdc, GetHfontOf(GetFont())); } else // no font set, use the one set by the theme { wxUxThemeHandle hTheme(this, L"BUTTON"); if ( hTheme ) { // GetThemeFont() expects its parameter to be LOGFONTW and not // LOGFONTA even in ANSI programs and will happily corrupt // memory after the struct end if we pass a LOGFONTA (which is // smaller) to it! LOGFONTW lfw; if ( wxUxThemeEngine::Get()->GetThemeFont ( hTheme, hdc, BP_GROUPBOX, GBS_NORMAL, TMT_FONT, (LOGFONT *)&lfw ) == S_OK ) { #if wxUSE_UNICODE // ok, no conversion necessary const LOGFONT& lf = lfw; #else // !wxUSE_UNICODE // most of the fields are the same in LOGFONTA and LOGFONTW LOGFONT lf; memcpy(&lf, &lfw, sizeof(lf)); // but the face name must be converted WideCharToMultiByte(CP_ACP, 0, lfw.lfFaceName, -1, lf.lfFaceName, sizeof(lf.lfFaceName), NULL, NULL); #endif // wxUSE_UNICODE/!wxUSE_UNICODE font.Init(lf); if ( font ) selFont.Init(hdc, font); } } } // Get the font extent int 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 ) { x = 9; dimensions.left = x; dimensions.right = x + width; } else { x = rc.right - 7; dimensions.left = x - width; dimensions.right = x; } // need to adjust the rectangle to cover all the label background dimensions.left -= 2; dimensions.right += 2; dimensions.bottom += 2; 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); } // now draw the text if ( !rtl ) { RECT rc2 = { x, 0, x + width, y }; ::DrawText(hdc, label.wx_str(), label.length(), &rc2, DT_SINGLELINE | DT_VCENTER); } else // RTL { RECT rc2 = { x, 0, x - width, y }; ::DrawText(hdc, label.wx_str(), label.length(), &rc2, DT_SINGLELINE | DT_VCENTER | DT_RTLREADING); } } }
void gcImageControl::doPaint(wxDC* dc) { wxSize sz = GetSize(); dc->SetBackgroundMode(wxTRANSPARENT); if (!m_imgHandle.getImg() || !m_imgHandle->IsOk()) { dc->SetTextForeground(wxColor(0,0,0)); dc->Clear(); return; } if (m_bClearBG) { const wxWindow *win = UseBgCol() ? this : GetParent(); dc->SetBrush(win->GetBackgroundColour()); dc->SetPen(*wxTRANSPARENT_PEN); dc->DrawRectangle(0, 0, sz.GetWidth(), sz.GetHeight()); } if (m_uiXPro == 0 || m_uiYPro == 0) { wxBitmap temp(sz.GetWidth(), sz.GetHeight()); if (m_bTile) gcImage::tileImg(temp, wxBitmap(*m_imgHandle.getImg())); else temp = wxBitmap(m_imgHandle->Scale(sz.GetWidth(), sz.GetHeight(), wxIMAGE_QUALITY_HIGH)); dc->DrawBitmap(temp, 0, 0, true); if (m_bTransEnabled && m_imgHandle->HasMask()) { wxRegion region = wxRegion(temp); SetShape(region, this); if (m_bStoreRegion) m_Region = region; } } else { uint32 h = sz.GetWidth() * m_uiYPro / m_uiXPro; uint32 w = sz.GetHeight() * m_uiXPro / m_uiYPro; uint32 x=0; uint32 y=0; if (!m_bClearBG) { dc->SetPen(wxPen(GetBackgroundColour(),1)); dc->SetBrush(wxBrush(GetBackgroundColour())); } if (h < (uint32)sz.GetHeight()) { y = (sz.GetHeight()-h)/2; w = sz.GetWidth(); if (!m_bClearBG) { dc->DrawRectangle(0, 0, w, y); dc->DrawRectangle(0, sz.GetHeight()-y, w, y); } } else { x = (sz.GetWidth()-w)/2; h = sz.GetHeight(); if (!m_bClearBG) { dc->DrawRectangle(0, 0, x, h); dc->DrawRectangle(sz.GetWidth()-x, 0, x, h); } } wxBitmap temp(m_imgHandle->Scale(w, h, wxIMAGE_QUALITY_HIGH)); wxMemoryDC memDC; memDC.SelectObject(temp); dc->Blit(x, y, // Draw at (100, 100) w, h, // Draw full bitmap &memDC, // Draw from memDC 0, 0, // Draw from bitmap origin wxCOPY, // Logical operation true); // Take mask into account memDC.SelectObject(wxNullBitmap); } }