Szerokość tekstu - jeszcze raz.

0

Cześć, problem wygląda następująco.
Tworzę sobie kontrolkę dziedziczącą po CStatic. To ma być zwykły label do pokazywania tekstu. Tyle, że ma mieć możliwość zawijania tekstu, jeśli ten będzie za długi. A więc muszę mieć szerokość tekstu i muszę mieć szerokość kontrolki. W teorii proste:

 
CRect thisRect;
SIZE txtSize = {0};
GetWindowRect(&thisRect); //pobieram szerokość kontrolki (piksele)

//liczę szerokość tekstu, funkcja zwraca wymiary w logical units
GetTextExtentPoint32(GetDC()->GetSafeHdc(), str, str.GetLength(), &txtSize);

//teraz muszę zmienić szerokość kontrolki z pikseli na logical units:
LONG baseUnits = GetDialogBaseUnits();
int baseUnitX = LOWORD(baseUnits);
int pxWidth = MulDiv(thisRect.Width(), baseUnitX, 4);

//teraz wystarczy sprawdzić, czy tekst jest dłuższy niż szerokość kontrolki:
if(txtSize.cx >= pxWidth)
{
}

Niestety, okazuje się, że daje mi to wynik taki, że kontrolka jest na tyle szeroka, żeby pomieścić naprawdę szerokie teksty. Oczywiście w rzeczywistości te szerokie teksty się nie mieszczą. Próbowałem też przeliczyć szerokość kontrolki w taki sposób (odwrotnie):

 
int pxWidth = MulDiv(thisRect.Width(), baseUnitX, 4);

Tutaj z kolei efekt jest taki, że teksty, które bez problemu mieszczą się w kontrolce, są zawijane. Szerokość kontrolki w wyniku tego działania wychodzi stosunkowo mała. Jak to zrobić poprawnie?

0

nie ma w standardowym C++ czegos takiego jak CStatic

Wiec warto wiedziec z jakimi technologiami pracujesz.

0

WindowsAPI C:

int TEXT_GetWidthInPixel(HDC &hdc, string strText){
    SIZE p;
    GetTextExtentPoint32(hdc, &strText[0], strText.length(), &p);
    return p.cx;
}
int TEXT_GetHeightInPixel(HDC &hdc, string strText){
    SIZE p;
    GetTextExtentPoint32(hdc, &strText[0], strText.length(), &p);
    return p.cy;
} 
0

gswidwa, przecież właśnie TO robię. GetTextExtentPoint32 nie zwraca szerokości w pikselach, tylko w logical units:

lpSize [out]
A pointer to a SIZE structure that receives the dimensions of the string, in logical units.

0

Proszę moderatorów o przeniesienie do forum C++, ponieważ, jak widać, problem nie jest trywialny.

0

Pokaż kod, jak tego uzywasz i jaki hdc przekazujesz.

0

Kod podałem w pierwszej wiadomości. To jest część zdarzenia OnSetText

1

Albo ja nie rozumiem albo wg. helpa powinieneś użyć tego wzoru:
https://msdn.microsoft.com/pl-pl/library/windows/desktop/ms645475(v=vs.85).aspx

Similarly, to convert from pixels to dialog template units, use the following formulas:

templateunitX = MulDiv(pixelX, 4, baseunitX);
templateunitY = MulDiv(pixelY, 8, baseunitY);

bo przecież txtSize.cx masz w base units więc jak chcesz inaczej to porównywać.

0

Spróbuj usunąć

int pxWidth = MulDiv(thisRect.Width(), baseUnitX, 4); 

i zastosować suę do mojej funkcji.

W załączniku masz przykład obliczania tekstu w metodzie f_Redraw() Zobacz w release przykład wpisywania tekstu do Edita, że działa.

0

Nie buduje mi się to :)
Anyway, widzę jedną diametralną różnicę. Ty używasz standardowej czcionki systemowej. U mnie jest jakiś tam Arial, czy inne cudo. Poza tym, zauważ, że ja też to wykorzystuję:

 
//liczę szerokość tekstu, funkcja zwraca wymiary w logical units
GetTextExtentPoint32(GetDC()->GetSafeHdc(), str, str.GetLength(), &txtSize);
1

OK, zrobiłem to z pomocą GDIPlus. Na pewno można lepiej i prościej, niestety nie wiadomo jak:

 
Gdiplus::Font f(GetDC()->GetSafeHdc(), (HFONT)GetFont()->GetSafeHandle());
Gdiplus::RectF resultRect;
Gdiplus::Graphics g(GetDC()->GetSafeHdc());			
g.MeasureString((LPCWSTR)str, (INT)str.GetLength(), &f, Gdiplus::PointF(0, 0), &resultRect);

Wielkość podana w resultRect jest w pikselach.

1 użytkowników online, w tym zalogowanych: 0, gości: 1