调整字体大小以适合矩形

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);