void CanvasGdiplus::DrawStringInt(const std::wstring& text, HFONT font, const Color& color, int x, int y, int w, int h, int flags) { if(!IntersectsClipRectInt(x, y, w, h)) { return; } // Clamp the max amount of text we'll draw to 32K. There seem to be bugs in // DrawText() if you e.g. ask it to character-break a no-whitespace string of // length > 43680 (for which it draws nothing), and since we clamped to 2K in // SizeStringInt() we're unlikely to be able to display this much anyway. const int kMaxStringLength = 32768 - 1; // So the trailing \0 fits in 32K. std::wstring clamped_string(text.substr(0, kMaxStringLength)); RECT text_bounds = { x, y, x+w, y+h }; HDC dc = BeginPlatformPaint(); SetBkMode(dc, TRANSPARENT); HFONT old_font = (HFONT)SelectObject(dc, font); SetTextColor(dc, color.ToCOLORREF()); int f = ComputeFormatFlags(flags, clamped_string); DoDrawText(dc, clamped_string, &text_bounds, f); // Restore the old font. This way we don't have to worry if the caller // deletes the font and the DC lives longer. SelectObject(dc, old_font); EndPlatformPaint(dc); }
void wxGCDCImpl::DoDrawRotatedText(const wxString& text, wxCoord x, wxCoord y, double angle) { wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawRotatedText - invalid DC") ); if ( text.empty() ) return; if ( !m_logicalFunctionSupported ) return; // we test that we have some font because otherwise we should still use the // "else" part below to avoid that DrawRotatedText(angle = 180) and // DrawRotatedText(angle = 0) use different fonts (we can't use the default // font for drawing rotated fonts unfortunately) if ( (angle == 0.0) && m_font.IsOk() ) { DoDrawText(text, x, y); // Bounding box already updated by DoDrawText(), no need to do it again. return; } // Get extent of whole text. wxCoord w, h, heightLine; GetOwner()->GetMultiLineTextExtent(text, &w, &h, &heightLine); // Compute the shift for the origin of the next line. const double rad = wxDegToRad(angle); const double dx = heightLine * sin(rad); const double dy = heightLine * cos(rad); // Draw all text line by line const wxArrayString lines = wxSplit(text, '\n', '\0'); for ( size_t lineNum = 0; lineNum < lines.size(); lineNum++ ) { // Calculate origin for each line to avoid accumulation of // rounding errors. if ( m_backgroundMode == wxTRANSPARENT ) m_graphicContext->DrawText( lines[lineNum], x + wxRound(lineNum*dx), y + wxRound(lineNum*dy), wxDegToRad(angle )); else m_graphicContext->DrawText( lines[lineNum], x + wxRound(lineNum*dx), y + wxRound(lineNum*dy), wxDegToRad(angle ), m_graphicContext->CreateBrush(m_textBackgroundColour) ); } // call the bounding box by adding all four vertices of the rectangle // containing the text to it (simpler and probably not slower than // determining which of them is really topmost/leftmost/...) // "upper left" and "upper right" CalcBoundingBox(x, y); CalcBoundingBox(x + wxCoord(w*cos(rad)), y - wxCoord(w*sin(rad))); // "bottom left" and "bottom right" x += (wxCoord)(h*sin(rad)); y += (wxCoord)(h*cos(rad)); CalcBoundingBox(x, y); CalcBoundingBox(x + wxCoord(w*cos(rad)), y - wxCoord(w*sin(rad))); }
virtual void OnDraw (CDC* pDC) { ASSERT_VALID (this); ASSERT_VALID (pDC); CRect rectText = m_rect; rectText.DeflateRect (nTextMarginHorz, 0); DoDrawText (pDC, m_strText, rectText, DT_SINGLELINE | DT_VCENTER); }
//******************************************************************************** void CBCGPRibbonSlider::OnDraw (CDC* pDC) { ASSERT_VALID (this); ASSERT_VALID (pDC); if (m_rect.IsRectEmpty ()) { return; } if (m_bZoomButtons) { // Draw zoom buttons: CBCGPVisualManager::GetInstance ()->OnDrawRibbonSliderZoomButton ( pDC, this, m_rectZoomOut, TRUE, m_bIsHighlighted && m_nHighlighted == nZoomOutIndex, m_bIsPressed && m_nPressed == nZoomOutIndex, IsDisabled ()); CBCGPVisualManager::GetInstance ()->OnDrawRibbonSliderZoomButton ( pDC, this, m_rectZoomIn, FALSE, m_bIsHighlighted && m_nHighlighted == nZoomInIndex, m_bIsPressed && m_nPressed == nZoomInIndex, IsDisabled ()); } // Draw channel: CRect rectChannel = m_rectSlider; if (IsVert ()) { rectChannel.left = rectChannel.CenterPoint ().x - 1; rectChannel.right = rectChannel.left + 2; } else { rectChannel.top = rectChannel.CenterPoint ().y - 1; rectChannel.bottom = rectChannel.top + 2; } CBCGPVisualManager::GetInstance ()->OnDrawRibbonSliderChannel ( pDC, this, rectChannel); // Draw thumb: CBCGPVisualManager::GetInstance ()->OnDrawRibbonSliderThumb ( pDC, this, m_rectThumb, (m_bIsHighlighted && (m_nHighlighted == nThumbIndex || m_nHighlighted == nSliderIndex)) || IsFocused (), m_bIsPressed && m_nPressed == nThumbIndex, IsDisabled ()); if (!m_rectLabel.IsRectEmpty () && !m_strText.IsEmpty ()) { DoDrawText (pDC, m_strText, m_rectLabel, DT_CENTER | DT_SINGLELINE); } }
// static void CanvasGdiplus::SizeStringInt(const std::wstring& text, const Font& font, int* width, int* height, int flags) { // Clamp the max amount of text we'll measure to 2K. When the string is // actually drawn, it will be clipped to whatever size box is provided, and // the time to do that doesn't depend on the length being clipped off. const int kMaxStringLength = 2048 - 1; // So the trailing \0 fits in 2K. std::wstring clamped_string(text.substr(0, kMaxStringLength)); if(*width == 0) { // If multi-line + character break are on, the computed width will be one // character wide (useless). Furthermore, if in this case the provided text // contains very long "words" (substrings without a word-breaking point), // DrawText() can run extremely slowly (e.g. several seconds). So in this // case, we turn character breaking off to get a more accurate "desired" // width and avoid the slowdown. if(flags & (Canvas::MULTI_LINE|Canvas::CHARACTER_BREAK)) { flags &= ~Canvas::CHARACTER_BREAK; } // Weird undocumented behavior: if the width is 0, DoDrawText() won't // calculate a size at all. So set it to 1, which it will then change. if(!text.empty()) { *width = 1; } } RECT r = { 0, 0, *width, *height }; HDC dc = GetDC(NULL); HFONT old_font = static_cast<HFONT>(SelectObject(dc, font.GetNativeFont())); DoDrawText(dc, clamped_string, &r, ComputeFormatFlags(flags, clamped_string)|DT_CALCRECT); SelectObject(dc, old_font); ReleaseDC(NULL, dc); *width = r.right; *height = r.bottom; }
//************************************************************************** void CBCGPRibbonComboBox::OnDraw (CDC* pDC) { ASSERT_VALID (this); ASSERT_VALID (pDC); OnDrawLabelAndImage (pDC); BOOL bIsHighlighted = m_bIsHighlighted; if (m_bIsFocused) { m_bIsHighlighted = TRUE; } if (IsDisabled ()) { m_bIsHighlighted = FALSE; } CRect rectSaved = m_rect; m_rect.left = m_rectCommand.left; CBCGPVisualManager::GetInstance ()->OnFillRibbonButton (pDC, this); if (m_pWndEdit->GetSafeHwnd () == NULL) { CRect rectText = m_rectCommand; rectText.DeflateRect (m_szMargin); UINT uiDTFlags = DT_SINGLELINE | DT_VCENTER; if (!m_bSearchResultMode) { if (m_nAlign == ES_CENTER) { uiDTFlags |= DT_CENTER; } else if (m_nAlign == ES_RIGHT) { uiDTFlags |= DT_RIGHT; } } BOOL bDrawPrompt = m_strEdit.IsEmpty() && !m_strSearchPrompt.IsEmpty() && !IsDroppedDown(); const CString& str = bDrawPrompt ? m_strSearchPrompt : m_strEdit; COLORREF clrText = bDrawPrompt ? CBCGPVisualManager::GetInstance()->GetToolbarEditPromptColor() : (COLORREF)-1; if (IsDisabled()) { clrText = globalData.clrGrayedText; } DoDrawText (pDC, str, rectText, uiDTFlags, clrText); } if (m_bSearchMode && m_strEdit.IsEmpty() && m_ImageSearch.IsValid()) { CRect rectIcon = m_rectMenu; rectIcon.right = rectIcon.left - 1; rectIcon.left = rectIcon.right - rectIcon.Height(); m_ImageSearch.DrawEx(pDC, rectIcon, 0, CBCGPToolBarImages::ImageAlignHorzCenter, CBCGPToolBarImages::ImageAlignVertCenter, CRect(0, 0, 0, 0), IsDisabled() ? (BYTE)127 : (BYTE)255); } CBCGPVisualManager::GetInstance ()->OnDrawRibbonButtonBorder (pDC, this); CBCGPToolbarComboBoxButton buttonDummy; buttonDummy.m_bIsRibbon = TRUE; buttonDummy.m_bIsRibbonFloaty = IsFloatyMode (); BOOL bIsDropDownHighlighted = IsMenuAreaHighlighted () || m_bIsFocused || m_bIsEditFocused || (bIsHighlighted && !m_bHasEditBox); CBCGPVisualManager::GetInstance ()->OnDrawComboDropButton ( pDC, m_rectMenu, IsDisabled (), IsDroppedDown (), bIsDropDownHighlighted, &buttonDummy); if (m_bIsCalculator) { m_ButtonImages.DrawEx(pDC, m_rectMenu, 2, CBCGPToolBarImages::ImageAlignHorzCenter, CBCGPToolBarImages::ImageAlignVertCenter); } m_bIsHighlighted = bIsHighlighted; m_rect = rectSaved; }
/** ** Draw text with font at x,y clipped. ** ** See VideoDrawText. ** ** @return The length of the printed text. */ global int VideoDrawTextClip(int x,int y,unsigned font, const unsigned char* text) { return DoDrawText(x,y,font,text,1); }
//*********************************************************************************** void CBCGPRibbonLabel::OnDraw (CDC* pDC) { ASSERT_VALID (this); ASSERT_VALID (pDC); if (m_rect.IsRectEmpty ()) { return; } CRect rectText = m_rect; rectText.DeflateRect (m_szMargin.cx, 0); COLORREF cltTextOld = (COLORREF)-1; BOOL bIsMenuMode = IsMenuMode () || m_bIsPaletteGroup; if (bIsMenuMode) { rectText.bottom -= 2; COLORREF clrText = CBCGPVisualManager::GetInstance ()->OnDrawMenuLabel (pDC, m_rect); if (clrText != (COLORREF)-1) { cltTextOld = pDC->SetTextColor (clrText); } } else { CBCGPVisualManager::GetInstance ()->OnDrawRibbonLabel (pDC, this, m_rect); } CFont* pOldFont = NULL; if (bIsMenuMode) { pOldFont = pDC->SelectObject (&globalData.fontBold); ASSERT_VALID (pOldFont); } UINT uiDTFlags = bIsMenuMode || !m_bIsAlwaysLarge ? DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX : DT_WORDBREAK | DT_NOPREFIX; if (!bIsMenuMode && m_bIsAlwaysLarge) { int dy = max (0, (rectText.Height () - m_sizeTextRight.cy) / 2); rectText.DeflateRect (0, dy); } DoDrawText (pDC, m_strText, rectText, uiDTFlags); if (pOldFont != NULL) { pDC->SelectObject (pOldFont); } if (cltTextOld != (COLORREF)-1) { cltTextOld = pDC->SetTextColor (cltTextOld); } }
/** ** Draw text with font at x,y clipped. ** ** @see DoDrawText. ** ** @param x X screen position ** @param y Y screen position ** @param font Font number ** @param text Text to be displayed. ** ** @return The length of the printed text. */ int VideoDrawTextClip(int x, int y, CFont *font, const std::string &text) { return DoDrawText(x, y, font->FontFamily(), font->IsPlainText(), text, true); }