Для вывода текста мне необходимо вычислить размер BoundingRectangle.
Использую для этой цели GetTextExtentPoint32. Но если используемый вариант шрифта синтезируется из основного (в частности Italic для Tahoma), то результат оказывается не верным (в моём случае overhang не включается в общий размер). Как корректно выйти из данной ситуации?
Сейчас попробую как предложено в
http://rsdn.ru/Forum/Message.aspx?mid=44480&only=1Автор: Dutchman
Дата: 11.04.02
, но такой выход я не считаю хорошим. Во-первых есть вероятность столкнуться с проблемами выванными Clipping. И во-вторых Громоздко.
А>Для вывода текста мне необходимо вычислить размер BoundingRectangle.
А>Использую для этой цели GetTextExtentPoint32. Но если используемый вариант шрифта синтезируется из основного (в частности Italic для Tahoma), то результат оказывается не верным (в моём случае overhang не включается в общий размер). Как корректно выйти из данной ситуации?
А>Сейчас попробую как предложено в http://rsdn.ru/Forum/Message.aspx?mid=44480&only=1Автор: Dutchman
Дата: 11.04.02
, но такой выход я не считаю хорошим. Во-первых есть вероятность столкнуться с проблемами выванными Clipping. И во-вторых Громоздко.
А DrawText с DT_CALCRECT тоже некорректно отрабатывает?
После дальнейших экспериментов выяснилось, что Simulated Fonts здесь играют не столь значительную роль.
Неточности могут проявляться и с другими шрифтами.
Как оказалось GetTextExtentPoint32 определяет вовсе не высоту/ширину строки как расстояние между крайними печатаемыми пикселями.
/Дальше я буду говорить только о ширине./
А как рассотяние от reference point до … точки куда сместиться reference point при TextOut с включеным TA_UPDATECP.
Упрощённо (не учитываем лигатуры, упрощенный кернинг)
Для каждого символа строки:
От refpoint смещаем на A, рисуем букву шириной B (смещаем на B), смещаем на C.
(Получаем расстояние от reference point перед выводом строки, до reference point после)
Это позволяет склеивать строку из кусочков последовательным вызовом TextOut, но даёт неверные результаты при опеределении какой же прямоугольник нужно выделить для той или иной строки. (почему DrawText даёт такой же результат остаётся не ясным).
Но не учтенным оказывается расстояние A первого символа и расстояние C последнего. Именно на эти величины и нужна коррекция. Если требуется определить расстояние от левого края первого символа, до правого края последнего, то коррекцию производить для любых значений A и С.
Если же требуется определить прямоугольник в который осуществлять вывод TextOut и при этом не столкнуться с Clipping, то только для отрицательных значений A и С.
BOOL GetTextExtentPoint32Adj(HDC hDC,
LPCSTR lpStr,
DWORD dwLen,
LPSIZE sz,
BOOL maxSize)
{
ABC abc;
if (!::GetTextExtentPoint32(hDC, lpStr, dwLen, sz))
return FALSE;
if (!::GetCharABCWidths(hDC, lpStr[0], lpStr[0], &abc))
return FALSE;
if (maxSize || abc.abcA < 0)
sz->cx-=abc.abcA;
if(!::GetCharABCWidths(hDC, lpStr[dwLen-1], lpStr[dwLen-1], &abc))
return FALSE;
if (maxSize || abc.abcC < 0 )
sz->cx-=abc.abcC;
return TRUE;
}
Kirill Erofeev /tempo1232003 -at- yahoo.com/
Здравствуйте, Аноним, Вы писали:
Знаю, что пост старый, но столкнулся с этой проблемой только сейчас.
Может не на все случаи жизни подходит, не знаю всех случаев. Но у меня считало точно (обычный многострочный текст)
Мелочь, а кому-нить поможет
CSize CComent::GetSizeText(CDC *pDC, CString strText)
{
LPCTSTR strBeg = strText;
LPCTSTR strEnd = strBeg;
LPCTSTR strCur = strBeg;
size_t szLen = strText.GetLength();
CSize sz(0, 0);
while( *strEnd != NULL &&
(strEnd - strBeg) < szLen )
{
while( *strEnd != _T('\r') &&
*strEnd != _T('\n') &&
*strEnd != NULL )
++strEnd;
CSize _sz = pDC->GetTextExtent(strBeg, strEnd - strCur);
sz.cx = max(sz.cx, _sz.cx);
sz.cy += _sz.cy;
if( *strEnd == _T('\r') &&
*(strEnd+1) == _T('\n') )
++strEnd;
strCur = ++strEnd;
}
return sz;
}
...
CSize sz = GetSizeText(pDC, m_strText);
CRect rc(m_pt.x, m_pt.y,
m_pt.x + sz.cx+1, m_pt.y + sz.cy+1);
// пиксель в пиксель :-)
pDC->DrawText(m_strText, rc, DT_CENTER | DT_PATH_ELLIPSIS);
pDC->Rectangle( m_pt.x, m_pt.y,
m_pt.x + sz.cx+1, m_pt.y + sz.cy );
...
Здравствуйте, The_Thing, Вы писали:
T_T>T_T>CSize CComent::GetSizeText(CDC *pDC, CString strText)
T_T>{
T_T> while( *strEnd != NULL &&
T_T> (strEnd - strBeg) < szLen )
T_T> {
T_T> while( *strEnd != _T('\r') &&
T_T> *strEnd != _T('\n') &&
T_T> *strEnd != NULL )
T_T> ++strEnd;
...................................
T_T> if( *strEnd == _T('\r') &&
T_T> *(strEnd+1) == _T('\n') )
T_T> ++strEnd;
T_T> strCur = ++strEnd;
T_T> }
T_T>
Унылая попытка избежать пропуск нулевого символа...
Сделаю предположение, что этот код некорректно обработает табуляции...
Здравствуйте, rus blood, Вы писали:
RB>Унылая попытка избежать пропуск нулевого символа...
ASSERT(!IsBadStringPtr((LPCTSTR)strText,INFINITE)); //Рулит адназначно!