调整字体大小以适合矩形
Sizing Font to fit in a Rectangle
我正在使用以下改编自 here 的代码来使文本适合 MFC 应用程序中的矩形,这有效,但我希望它也使用垂直 space .
这似乎与使用 ExtTextOut 有关,但我无法让它适应其他功能。有什么想法吗?
void CCube::FontInRect(CDC *pDC, CString sText, CRect &rFont, DWORD dSettings) {
int i, nStringLength;
BOOL bResult;
int *pDx;
int nX = rFont.left;
int nY = rFont.top;
int Width = 0;
// How long is the string - you need this later in this code.
nStringLength = lstrlen(sText);
// Allocate enough memory for the intercharacter spacing array.
pDx = (int *)new int[sizeof(int)* nStringLength];
// Initialize the array with the standard values.
for (i = 0; i < nStringLength; i++) {
ABC abc;
if (!GetCharABCWidths(*pDC, sText[i], sText[i], &abc)) {
delete[] pDx;
return;
}
pDx[i] = abc.abcA + abc.abcB + abc.abcC;
// You need the width.
Width += pDx[i];
// Also, account for the Black extent of the string.
if (i == 0) {
// Adjustment before the first character for underhang
nX -= abc.abcA;
Width -= abc.abcA;
}
if (i == nStringLength - 1) {
// Adjustment for overhang
Width -= abc.abcC;
}
}
int deltaCX = rFont.right - rFont.left - Width;
int deltaCh = deltaCX / nStringLength;
int remainder = deltaCX % nStringLength;
int error = 0;
// Distribute the adjustment through the intercharacter spacing.
// For a more typographically correct approach, distribute the
// adjustment in the "white space."
for (i = 0; i < nStringLength; i++) {
pDx[i] += deltaCh;
error += remainder;
if (abs(error) >= nStringLength) // adjustment?
{
int adjustment = abs(error) / error;
pDx[i] += adjustment;
error -= nStringLength*adjustment;
}
}
// ExtTextOut() draws our text with our ICS array.
bResult = ExtTextOut(*pDC, nX, nY, 0, &rFont, sText, nStringLength, pDx);
// Clean up.
delete[] pDx;
}
(请暂时忽略矩形的大小。)
当前的:
期望:
您可以使用带有 DT_CALCRECT
标志的 DrawText
。你必须知道目标矩形的宽度,然后 DrawText 将计算它需要的矩形的高度。它让你画任何段落。
CString str = L"Test Test Test Test Test Test Test Test\nLine 2";
CRect rtext(20, 20, 200, 0);
DWORD textformat = DT_TOP | DT_LEFT | DT_WORDBREAK;
dc.DrawText(str, &rtext, textformat| DT_CALCRECT);
CRect rc = rtext;
rc.InflateRect(2, 2);
CPen pen;
pen.CreatePen(PS_SOLID, 1, RGB(0,0,0));
dc.SelectObject(&pen);
dc.Rectangle(rc);
dc.DrawText(str, &rtext, textformat);
要强制文本适合固定矩形,只需使用 dc.DrawText(str, &target_rect, textformat);
如有必要,最后几行将被剪掉。
也可以通过调整字体大小使文本适合固定的矩形。这种方法不是很常用,这里只是为了举例:
CString str = L"Test Test Test Test Test Test Test\nLine 2\nLine 3\nLine 4\nLine 5";
DWORD textformat = DT_TOP | DT_LEFT | DT_WORDBREAK;
CRect rctarget(20, 20, 200, 80);
CRect r = rctarget;
int gap = 1;
r.InflateRect(-gap, -gap);
CFont font;
LOGFONT logfont{ 0 };
wcscpy_s(logfont.lfFaceName, L"Segoe UI");
CRect rctext;
//Try different font heights. If large height won't
//fit then go down to the lowest possible height.
for (int fontheight = 24; fontheight > 10; fontheight--)
{
logfont.lfHeight = -fontheight;
font.CreateFontIndirect(&logfont);
CFont *oldfont = dc.SelectObject(&font);
rctext = r;
dc.DrawText(str, &rctext, textformat | DT_CALCRECT);
if (rctext.Height() < r.Height())
break;//it fits, stops here
dc.SelectObject(oldfont);
font.DeleteObject();
}
//uncomment this line to show all of the text without clipping
//rctarget.bottom = rctext.bottom + 2 * gap;
dc.Rectangle(rctarget);
rctarget.InflateRect(-gap, -gap);
dc.DrawText(str, &rctarget, textformat);
我正在使用以下改编自 here 的代码来使文本适合 MFC 应用程序中的矩形,这有效,但我希望它也使用垂直 space .
这似乎与使用 ExtTextOut 有关,但我无法让它适应其他功能。有什么想法吗?
void CCube::FontInRect(CDC *pDC, CString sText, CRect &rFont, DWORD dSettings) {
int i, nStringLength;
BOOL bResult;
int *pDx;
int nX = rFont.left;
int nY = rFont.top;
int Width = 0;
// How long is the string - you need this later in this code.
nStringLength = lstrlen(sText);
// Allocate enough memory for the intercharacter spacing array.
pDx = (int *)new int[sizeof(int)* nStringLength];
// Initialize the array with the standard values.
for (i = 0; i < nStringLength; i++) {
ABC abc;
if (!GetCharABCWidths(*pDC, sText[i], sText[i], &abc)) {
delete[] pDx;
return;
}
pDx[i] = abc.abcA + abc.abcB + abc.abcC;
// You need the width.
Width += pDx[i];
// Also, account for the Black extent of the string.
if (i == 0) {
// Adjustment before the first character for underhang
nX -= abc.abcA;
Width -= abc.abcA;
}
if (i == nStringLength - 1) {
// Adjustment for overhang
Width -= abc.abcC;
}
}
int deltaCX = rFont.right - rFont.left - Width;
int deltaCh = deltaCX / nStringLength;
int remainder = deltaCX % nStringLength;
int error = 0;
// Distribute the adjustment through the intercharacter spacing.
// For a more typographically correct approach, distribute the
// adjustment in the "white space."
for (i = 0; i < nStringLength; i++) {
pDx[i] += deltaCh;
error += remainder;
if (abs(error) >= nStringLength) // adjustment?
{
int adjustment = abs(error) / error;
pDx[i] += adjustment;
error -= nStringLength*adjustment;
}
}
// ExtTextOut() draws our text with our ICS array.
bResult = ExtTextOut(*pDC, nX, nY, 0, &rFont, sText, nStringLength, pDx);
// Clean up.
delete[] pDx;
}
(请暂时忽略矩形的大小。)
当前的:
期望:
您可以使用带有 DT_CALCRECT
标志的 DrawText
。你必须知道目标矩形的宽度,然后 DrawText 将计算它需要的矩形的高度。它让你画任何段落。
CString str = L"Test Test Test Test Test Test Test Test\nLine 2";
CRect rtext(20, 20, 200, 0);
DWORD textformat = DT_TOP | DT_LEFT | DT_WORDBREAK;
dc.DrawText(str, &rtext, textformat| DT_CALCRECT);
CRect rc = rtext;
rc.InflateRect(2, 2);
CPen pen;
pen.CreatePen(PS_SOLID, 1, RGB(0,0,0));
dc.SelectObject(&pen);
dc.Rectangle(rc);
dc.DrawText(str, &rtext, textformat);
要强制文本适合固定矩形,只需使用 dc.DrawText(str, &target_rect, textformat);
如有必要,最后几行将被剪掉。
也可以通过调整字体大小使文本适合固定的矩形。这种方法不是很常用,这里只是为了举例:
CString str = L"Test Test Test Test Test Test Test\nLine 2\nLine 3\nLine 4\nLine 5";
DWORD textformat = DT_TOP | DT_LEFT | DT_WORDBREAK;
CRect rctarget(20, 20, 200, 80);
CRect r = rctarget;
int gap = 1;
r.InflateRect(-gap, -gap);
CFont font;
LOGFONT logfont{ 0 };
wcscpy_s(logfont.lfFaceName, L"Segoe UI");
CRect rctext;
//Try different font heights. If large height won't
//fit then go down to the lowest possible height.
for (int fontheight = 24; fontheight > 10; fontheight--)
{
logfont.lfHeight = -fontheight;
font.CreateFontIndirect(&logfont);
CFont *oldfont = dc.SelectObject(&font);
rctext = r;
dc.DrawText(str, &rctext, textformat | DT_CALCRECT);
if (rctext.Height() < r.Height())
break;//it fits, stops here
dc.SelectObject(oldfont);
font.DeleteObject();
}
//uncomment this line to show all of the text without clipping
//rctarget.bottom = rctext.bottom + 2 * gap;
dc.Rectangle(rctarget);
rctarget.InflateRect(-gap, -gap);
dc.DrawText(str, &rctarget, textformat);