如何让“DrawText”矩形刚好适应文本?

4
文档【这里】说明,如果我们使用DT_CALCRECT标志,则会执行以下操作:

确定矩形的宽度和高度。如果有多行文本,DrawText将使用pRect参数指向的矩形的宽度,并扩展矩形的底部以限定最后一行文本。如果只有一行文本,DrawText会修改矩形的右侧,使其限定行中的最后一个字符。在任何情况下,DrawText返回格式化文本的高度,但不绘制文本。

从描述中可以清楚地看出,DT_CALCRECT将使DrawText 绘制内容,因此我应该做一些像…的事情。
DrawTextExA(hdc, fromsqlite->descrip, -1, &rect, DT_CALCRECT, NULL);
// On debugging, I can see that rect is being modified in the above step.
if (DrawTextExA(hdc, fromsqlite->descrip, -1, &rect,
            DT_LEFT | DT_EDITCONTROL | DT_WORDBREAK, NULL) == 0) {
MessageBox(NULL, L"DrawText failed", NULL, MB_OK);
}

现在的问题是矩形的宽度应该是固定的。因此,我只想要矩形rect的底部扩展。在我的情况下,从sqlite数据库检索到的fromsqlite->descrip总是被视为单行文本。任何帮助都将不胜感激。
1个回答

5

应添加DT_WORDBREAK以打破单行文本。

应与最终格式结合使用DT_CALCRECT以获取矩形。

文档:DrawText函数(GDI函数)

DT_WORDBREAK
断字换行。如果一个单词会超过lpRect参数指定的矩形边缘,则自动在单词之间换行。回车换行序列也会断开该行。

如果未指定此项,则输出在一行上。

示例:

RECT rc={ 0, 0, 200, 0 };
const wchar_t* text = L"word1 word2 word3 word4 word5";
UINT format = DT_LEFT | DT_TOP | DT_EDITCONTROL | DT_WORDBREAK;
DrawText(hdc, text, -1, &rc, format | DT_CALCRECT);
DrawText(hdc, text, -1, &rc, format);

输出结果类似于以下内容(取决于字体大小)

单词1 单词2 单词3
单词4 单词5

DT_EDITCONTROL 是否必要?

考虑以下示例:

text = L"SingleLinexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
format = DT_LEFT | DT_TOP | DT_WORDBREAK;
DrawText(hdc, text, -1, &rc, format | DT_CALCRECT);
DrawText(hdc, text, -1, &rc, format);

此次“单词”长度可能超过矩形的宽度,文字不会换行,会溢出到右侧。您可以将格式与 DT_EDITCONTROL 或其他标志(如 DT_WORD_ELLIPSIS)相结合,以确保右侧没有溢出。DrawTextEx 使用相同的 DT_XXXX 标志。附注:如果您的文本是 UTF-8,则可以使用 MultiByteToWideChar 将其转换为 UTF-16,而不是使用希望 ANSI 输入的 DrawTextA。

谢谢伙计!我正在调查这个问题... 这里使用DrawTextA是有意的,因为我严格处理 ANSI 输入。 - sjsam
2
@sjsam,在你的示例中使用了DT_EDITCONTROL。正如这个答案正确显示的那样,你必须在第一次调用DrawText和第二次调用DrawText中使用相同的标志,否则计算得出的矩形将是不正确的。 - zett42
还有,如果没有使用DT_EDITCONTROL,文本也可以溢出矩形的右侧。请参考更新后的答案。 - Barmak Shemirani
1
你可以直接复制矩形,rcText = rc,然后更改 rc 的高度。 - Barmak Shemirani
是的,那正是我所想的,并且此刻正在做... :) - sjsam
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接