void wxMetafileDCImpl::DoGetTextExtent(const wxString& string, wxCoord *x, wxCoord *y, wxCoord *descent, wxCoord *externalLeading, const wxFont *theFont) const { const wxFont *fontToUse = theFont; if (!fontToUse) fontToUse = &m_font; ScreenHDC dc; SelectInHDC selFont(dc, GetHfontOf(*fontToUse)); SIZE sizeRect; TEXTMETRIC tm; ::GetTextExtentPoint32(dc, WXSTRINGCAST string, wxStrlen(WXSTRINGCAST string), &sizeRect); ::GetTextMetrics(dc, &tm); if ( x ) *x = sizeRect.cx; if ( y ) *y = sizeRect.cy; if ( descent ) *descent = tm.tmDescent; if ( externalLeading ) *externalLeading = tm.tmExternalLeading; }
void drawTextWithSpacing(GraphicsContext* graphicsContext, const SimpleFontData* font, const wxColour& color, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) { #if USE(WXGC) wxGCDC* dc = static_cast<wxGCDC*>(graphicsContext->platformContext()); #else wxDC* dc = graphicsContext->platformContext(); #endif // get the native HDC handle to draw using native APIs HDC hdc = 0; #if USE(WXGC) wxGraphicsContext* gc = dc->GetGraphicsContext(); Gdiplus::Graphics* g; if (gc) { g = (Gdiplus::Graphics*)gc->GetNativeContext(); hdc = g->GetHDC(); } #else hdc = static_cast<HDC>(dc->GetHDC()); #endif // ExtTextOut wants the offsets as an array of ints, so extract them // from the glyph buffer const GlyphBufferGlyph* glyphs = glyphBuffer.glyphs(from); const GlyphBufferAdvance* advances = glyphBuffer.advances(from); float y = point.y() - font->ascent(); float x = point.x(); int* spacing = new int[numGlyphs - from]; for (unsigned i = 0; i < numGlyphs; ++i) spacing[i] = advances[i].width(); wxFont* wxfont = font->getWxFont(); if (wxfont && wxfont->IsOk()) ::SelectObject(hdc, GetHfontOf(*wxfont)); if (color.Ok()) ::SetTextColor(hdc, color.GetPixel()); // do not draw background behind characters ::SetBkMode(hdc, TRANSPARENT); // draw text with optional character widths array wxString string = wxString((wxChar*)(&glyphs[from]), numGlyphs); ::ExtTextOut(hdc, x, y, 0, NULL, string.c_str(), string.length(), spacing); ::SetBkMode(hdc, TRANSPARENT); #if USE(WXGC) g->ReleaseHDC(hdc); #endif delete [] spacing; }
void wxListBox::SetHorizontalExtent(const wxString& s) { // in any case, our best size could have changed InvalidateBestSize(); // the rest is only necessary if we want a horizontal scrollbar if ( !HasFlag(wxHSCROLL) ) return; WindowHDC dc(GetHwnd()); SelectInHDC selFont(dc, GetHfontOf(GetFont())); TEXTMETRIC lpTextMetric; ::GetTextMetrics(dc, &lpTextMetric); int largestExtent = 0; SIZE extentXY; if ( s.empty() ) { // set extent to the max length of all strings for ( unsigned int i = 0; i < m_noItems; i++ ) { const wxString str = GetString(i); ::GetTextExtentPoint32(dc, str.c_str(), str.length(), &extentXY); int extentX = (int)(extentXY.cx + lpTextMetric.tmAveCharWidth); if ( extentX > largestExtent ) largestExtent = extentX; } } else // just increase the extent to the length of this string { int existingExtent = (int)SendMessage(GetHwnd(), LB_GETHORIZONTALEXTENT, 0, 0L); ::GetTextExtentPoint32(dc, s.c_str(), s.length(), &extentXY); int extentX = (int)(extentXY.cx + lpTextMetric.tmAveCharWidth); if ( extentX > existingExtent ) largestExtent = extentX; } if ( largestExtent ) SendMessage(GetHwnd(), LB_SETHORIZONTALEXTENT, LOWORD(largestExtent), 0L); //else: it shouldn't change }
void FastDC::SetFontStyles(int fontStyles, std::map<int,wxFont>& fontMap) { const int fontStyle = (fontStyles & wxFONTFLAG_ITALIC) ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL; const int fontWeight = (fontStyles & wxFONTFLAG_BOLD) ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL; const bool fontUnderline = (fontStyles & wxFONTFLAG_UNDERLINED) ? true : false; // Check if we need to change font style // (changing the font can be expensive, so we want to avoid it if possible) const bool styleChanged = (m_font.GetStyle() != fontStyle); const bool widthChanged = (m_font.GetWeight() != fontWeight); const bool underlineChanged = (m_font.GetUnderlined() != fontUnderline); if (!styleChanged && !widthChanged && !underlineChanged) return; // Check if we have font in cache std::map<int,wxFont>::const_iterator p = fontMap.find(fontStyles); if (p == fontMap.end()) { m_font.SetStyle(fontStyle); m_font.SetWeight(fontWeight); m_font.SetUnderlined(fontUnderline); fontMap[fontStyles] = m_font; } else m_font = p->second; /*m_font.SetStyle(fontStyle); m_font.SetWeight(fontWeight); m_font.SetUnderlined(fontUnderline);*/ #ifdef __WXMSW__ HGDIOBJ hfont = ::SelectObject(GetHdc(), GetHfontOf(m_font)); if ( hfont == HGDI_ERROR ) { wxLogLastError(_T("SelectObject(font)")); } else // selected ok { if ( !m_oldFont ) m_oldFont = (WXHPEN)hfont; } #else SetFont(m_font); #endif }
void wxTextMeasure::BeginMeasuring() { if ( m_dc ) { m_hdc = m_dc->GetHDC(); // Non-native wxDC subclasses should override their DoGetTextExtent() // and other methods. wxASSERT_MSG( m_hdc, wxS("Must not be used with non-native wxDCs") ); } else if ( m_win ) { m_hdc = ::GetDC(GetHwndOf(m_win)); } // We need to set the font if it's explicitly specified, of course, but // also if we're associated with a window because the window HDC created // above has the default font selected into it and not the font of the // window. if ( m_font || m_win ) m_hfontOld = (HFONT)::SelectObject(m_hdc, GetHfontOf(GetFont())); }
// draw the item bool wxOwnerDrawn::OnDrawItem(wxDC& dc, const wxRect& rc, wxODAction, wxODStatus stat) { // we do nothing if item isn't ownerdrawn if ( !IsOwnerDrawn() ) return true; wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl(); HDC hdc = GetHdcOf(*impl); RECT rect; wxCopyRectToRECT(rc, rect); { // set the font and colors wxFont font; GetFontToUse(font); wxColour colText, colBack; GetColourToUse(stat, colText, colBack); SelectInHDC selFont(hdc, GetHfontOf(font)); wxMSWImpl::wxTextColoursChanger textCol(hdc, colText, colBack); wxMSWImpl::wxBkModeChanger bkMode(hdc, wxBRUSHSTYLE_TRANSPARENT); AutoHBRUSH hbr(wxColourToPalRGB(colBack)); SelectInHDC selBrush(hdc, hbr); ::FillRect(hdc, &rect, hbr); // using native API because it recognizes '&' wxString text = GetName(); SIZE sizeRect; ::GetTextExtentPoint32(hdc, text.c_str(), text.length(), &sizeRect); int flags = DST_PREFIXTEXT; if ( (stat & wxODDisabled) && !(stat & wxODSelected) ) flags |= DSS_DISABLED; if ( (stat & wxODHidePrefix) ) flags |= DSS_HIDEPREFIX; int x = rc.x + GetMarginWidth(); int y = rc.y + (rc.GetHeight() - sizeRect.cy) / 2; int cx = rc.GetWidth() - GetMarginWidth(); int cy = sizeRect.cy; ::DrawState(hdc, NULL, NULL, wxMSW_CONV_LPARAM(text), text.length(), x, y, cx, cy, flags); } // reset to default the font, colors and brush if (stat & wxODHasFocus) ::DrawFocusRect(hdc, &rect); 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); } } }
bool wxMenuItem::OnDrawItem(wxDC& dc, const wxRect& rc, wxODAction WXUNUSED(act), wxODStatus stat) { const MenuDrawData* data = MenuDrawData::Get(); wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl(); HDC hdc = GetHdcOf(*impl); RECT rect; wxCopyRectToRECT(rc, rect); int imgWidth = wxMax(GetMarginWidth(), data->CheckSize.cx); if ( IsOwnerDrawn() ) { // font and colors to use wxFont font; GetFontToUse(font); wxColour colText, colBack; GetColourToUse(stat, colText, colBack); // calculate metrics of item parts RECT rcSelection = rect; data->ItemMargin.ApplyTo(rcSelection); RECT rcSeparator = rcSelection; data->SeparatorMargin.ApplyTo(rcSeparator); RECT rcGutter = rcSelection; rcGutter.right = data->ItemMargin.cxLeftWidth + data->CheckBgMargin.cxLeftWidth + data->CheckMargin.cxLeftWidth + imgWidth + data->CheckMargin.cxRightWidth + data->CheckBgMargin.cxRightWidth; RECT rcText = rcSelection; rcText.left = rcGutter.right + data->TextBorder; // we draw the text label vertically centered, but this results in it // being 1px too low compared to native menus for some reason, fix it if ( data->MenuLayout() != MenuDrawData::FullTheme ) rcText.top--; #if wxUSE_UXTHEME // If a custom background colour is explicitly specified, we should use // it instead of the default theme background. wxUxThemeEngine* const theme = GetBackgroundColour().IsOk() ? NULL : MenuDrawData::GetUxThemeEngine(); if ( theme ) { POPUPITEMSTATES state; if ( stat & wxODDisabled ) { state = (stat & wxODSelected) ? MPI_DISABLEDHOT : MPI_DISABLED; } else if ( stat & wxODSelected ) { state = MPI_HOT; } else { state = MPI_NORMAL; } wxUxThemeHandle hTheme(GetMenu()->GetWindow(), L"MENU"); if ( theme->IsThemeBackgroundPartiallyTransparent(hTheme, MENU_POPUPITEM, state) ) { theme->DrawThemeBackground(hTheme, hdc, MENU_POPUPBACKGROUND, 0, &rect, NULL); } theme->DrawThemeBackground(hTheme, hdc, MENU_POPUPGUTTER, 0, &rcGutter, NULL); if ( IsSeparator() ) { rcSeparator.left = rcGutter.right; theme->DrawThemeBackground(hTheme, hdc, MENU_POPUPSEPARATOR, 0, &rcSeparator, NULL); return true; } theme->DrawThemeBackground(hTheme, hdc, MENU_POPUPITEM, state, &rcSelection, NULL); } else #endif // wxUSE_UXTHEME { if ( IsSeparator() ) { DrawEdge(hdc, &rcSeparator, EDGE_ETCHED, BF_TOP); return true; } AutoHBRUSH hbr(colBack.GetPixel()); SelectInHDC selBrush(hdc, hbr); ::FillRect(hdc, &rcSelection, hbr); } // draw text label // using native API because it recognizes '&' HDCTextColChanger changeTextCol(hdc, colText.GetPixel()); HDCBgColChanger changeBgCol(hdc, colBack.GetPixel()); HDCBgModeChanger changeBgMode(hdc, TRANSPARENT); SelectInHDC selFont(hdc, GetHfontOf(font)); // item text name without mnemonic for calculating size wxString text = GetName(); SIZE textSize; ::GetTextExtentPoint32(hdc, text.c_str(), text.length(), &textSize); // item text name with mnemonic text = GetItemLabel().BeforeFirst('\t'); int flags = DST_PREFIXTEXT; // themes menu is using specified color for disabled labels if ( data->MenuLayout() == MenuDrawData::Classic && (stat & wxODDisabled) && !(stat & wxODSelected) ) flags |= DSS_DISABLED; if ( (stat & wxODHidePrefix) && !data->AlwaysShowCues ) flags |= DSS_HIDEPREFIX; int x = rcText.left; int y = rcText.top + (rcText.bottom - rcText.top - textSize.cy) / 2; ::DrawState(hdc, NULL, NULL, wxMSW_CONV_LPARAM(text), text.length(), x, y, 0, 0, flags); // ::SetTextAlign(hdc, TA_RIGHT) doesn't work with DSS_DISABLED or DSS_MONO // as the last parameter in DrawState() (at least with Windows98). So we have // to take care of right alignment ourselves. wxString accel = GetItemLabel().AfterFirst(wxT('\t')); if ( !accel.empty() ) { SIZE accelSize; ::GetTextExtentPoint32(hdc, accel.c_str(), accel.length(), &accelSize); flags = DST_TEXT; // themes menu is using specified color for disabled labels if ( data->MenuLayout() == MenuDrawData::Classic && (stat & wxODDisabled) && !(stat & wxODSelected) ) flags |= DSS_DISABLED; x = rcText.right - data->ArrowMargin.GetTotalX() - data->ArrowSize.cx - data->ArrowBorder; // right align accel on FullTheme menu, left otherwise if ( data->MenuLayout() == MenuDrawData::FullTheme) x -= accelSize.cx; else x -= m_parentMenu->GetMaxAccelWidth(); y = rcText.top + (rcText.bottom - rcText.top - accelSize.cy) / 2; ::DrawState(hdc, NULL, NULL, wxMSW_CONV_LPARAM(accel), accel.length(), x, y, 0, 0, flags); } } // draw the bitmap RECT rcImg; SetRect(&rcImg, rect.left + data->ItemMargin.cxLeftWidth + data->CheckBgMargin.cxLeftWidth + data->CheckMargin.cxLeftWidth, rect.top + data->ItemMargin.cyTopHeight + data->CheckBgMargin.cyTopHeight + data->CheckMargin.cyTopHeight, rect.left + data->ItemMargin.cxLeftWidth + data->CheckBgMargin.cxLeftWidth + data->CheckMargin.cxLeftWidth + imgWidth, rect.bottom - data->ItemMargin.cyBottomHeight - data->CheckBgMargin.cyBottomHeight - data->CheckMargin.cyBottomHeight); if ( IsCheckable() && !m_bmpChecked.IsOk() ) { if ( stat & wxODChecked ) { DrawStdCheckMark((WXHDC)hdc, &rcImg, stat); } } else { wxBitmap bmp; if ( stat & wxODDisabled ) { bmp = GetDisabledBitmap(); } if ( !bmp.IsOk() ) { // for not checkable bitmaps we should always use unchecked one // because their checked bitmap is not set bmp = GetBitmap(!IsCheckable() || (stat & wxODChecked)); #if wxUSE_IMAGE if ( bmp.IsOk() && stat & wxODDisabled ) { // we need to grey out the bitmap as we don't have any specific // disabled bitmap wxImage imgGrey = bmp.ConvertToImage().ConvertToGreyscale(); if ( imgGrey.IsOk() ) bmp = wxBitmap(imgGrey); } #endif // wxUSE_IMAGE } if ( bmp.IsOk() ) { wxMemoryDC dcMem(&dc); dcMem.SelectObjectAsSource(bmp); // center bitmap int nBmpWidth = bmp.GetWidth(), nBmpHeight = bmp.GetHeight(); int x = rcImg.left + (imgWidth - nBmpWidth) / 2; int y = rcImg.top + (rcImg.bottom - rcImg.top - nBmpHeight) / 2; dc.Blit(x, y, nBmpWidth, nBmpHeight, &dcMem, 0, 0, wxCOPY, true); } } 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 ) { // 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); } } }