diff --git a/src/msw/renderer.cpp b/src/msw/renderer.cpp index 1e6e4c6c62..b85629e31f 100644 --- a/src/msw/renderer.cpp +++ b/src/msw/renderer.cpp @@ -1104,13 +1104,16 @@ void wxRendererXP::DrawItemText(wxWindow* win, such alignment use DT_TOP (0), which does work for multi-lines, and deal with the actual desired vertical alignment ourselves with the help of GetThemeTextExtent(). - */ - bool useTopDrawing = - s_GetThemeTextExtent - && ( align & (wxALIGN_BOTTOM | wxALIGN_CENTRE_VERTICAL) ) != 0 - && text.Contains(wxS('\n')); - if ( useTopDrawing ) + [TODO] Ideally text measurement should only be needed for the above + mentioned situations but because there can be a difference between + the extent from GetThemeTextExtent() and the rect received by this + function could have involved other text measurements (e.g. with wxDVC, + see #18487), use it in all cases for now. + */ + bool useTopDrawing = false; + + if ( s_GetThemeTextExtent != NULL ) { /* Get the actual text extent using GetThemeTextExtent() and adjust @@ -1151,6 +1154,30 @@ void wxRendererXP::DrawItemText(wxWindow* win, defTextFlags, NULL, &rcExtent); if ( SUCCEEDED(hr) ) { + /* + Compensate for rare cases where the horizontal extents differ + slightly. Don't use the width of the passed rect here to deal + with horizontal alignment as it results in the text always + fitting and ellipsization then can't occur. Instead check for + width differences by comparing with the extent as calculated + by wxDC. + */ + const int textWidthDc = dc.GetMultiLineTextExtent(text).x; + const int widthDiff = textWidthDc - rcExtent.right; + if ( widthDiff ) + { + if ( align & wxALIGN_CENTRE_HORIZONTAL ) + { + const int widthOffset = widthDiff / 2; + rc.left += widthOffset; + rc.right -= widthOffset; + } + else if ( align & wxALIGN_RIGHT ) + rc.left += widthDiff; + else // left aligned + rc.right -= widthDiff; + } + /* For height compare with the height of the passed rect and use the difference for handling vertical alignment. This has @@ -1163,8 +1190,12 @@ void wxRendererXP::DrawItemText(wxWindow* win, necessity) confines rendering to a cell's bounds. */ const int heightDiff = rect.GetHeight() - rcExtent.bottom; - if ( heightDiff ) + if ( heightDiff + && (align & (wxALIGN_BOTTOM | wxALIGN_CENTRE_VERTICAL)) + && text.Contains(wxS('\n')) ) { + useTopDrawing = true; + if ( align & wxALIGN_CENTRE_VERTICAL ) { const int heightOffset = heightDiff / 2; @@ -1177,10 +1208,6 @@ void wxRendererXP::DrawItemText(wxWindow* win, rc.bottom -= heightDiff; } } - else - { - useTopDrawing = false; - } } if ( !useTopDrawing )