我在Win32下有一个小小的文字绘图拼图。我正试图在窗口顶部为我的应用程序的用户绘制一些说明。
请参考以下窗口(我已经更改了文本的背景颜色,以便您可以看到边界)
(来源:billy-oneal.com)
我目前正在使用DrawTextEx将文本绘制到我的窗口,但问题是它没有填充我给它的整个RECTangle。没有绘制该区域就好了,直到窗口调整大小:
(来源:billy-oneal.com)
当由于窗口大小调整而重新包装文本时,因为DrawTextEx不清除它的背景,所以这些工件是剩余的。
我尝试使用FillRect填充文本绘图调用后面的区域,这确实消除了视觉瑕疵,但随后导致文本不断闪烁,因为它被完全擦除然后完全重绘为显示。
关于如何让不包含文本的区域用背景颜色绘制的任何想法?
编辑:我希望避免在应用程序可能的情况下对表单进行双重缓冲。
EDIT2:我在调整大小时检测到换行时只重绘了文本,解决了这个问题。
答案 0 :(得分:4)
使用双缓冲?
将所有内容绘制到位图并将位图绘制到窗口。闪烁通常是双重缓冲问题。
答案 1 :(得分:2)
有许多可能的解决方案,如果没有看到您的代码,很难说哪种方法最好,所以我建议您查看this article on flicker free drawing
答案 2 :(得分:2)
SetBkMode + SetBkColor?
答案 3 :(得分:2)
好吧,因为似乎没有人知道如何处理它,我这样实现了它:
std::vector<std::wstring> wrapString(HDC hDC, const std::wstring& text, const RECT& targetRect, HFONT font)
{
std::vector<std::wstring> result;
RECT targetRectangle;
CopyRect(&targetRectangle, &targetRect);
//Calculate the width of the bounding rectangle.
int maxWidth = targetRectangle.right - targetRectangle.left;
//Draw the lines one at a time
std::wstring currentLine;
for(std::wstring::const_iterator it = text.begin(); it != text.end(); currentLine.push_back(*it), it++)
{
if(*it == L'\r' || *it == L'\n')
{ //Hard return
while(it != text.end() && (*it == L'\r' || *it == L'\n')) it++;
result.push_back(currentLine);
currentLine.clear();
}
else
{ //Check for soft return
SIZE sizeStruct;
GetTextExtentPoint32(hDC, currentLine.c_str(), static_cast<int>(currentLine.length()), &sizeStruct);
if (sizeStruct.cx > maxWidth)
{
std::wstring::size_type lineLength = currentLine.find_last_of(L' ');
if (lineLength == currentLine.npos)
{ //Word is longer than a line.
for(;it != text.end() && !iswspace(*it);it++) currentLine.push_back(*it);
}
else
{ //Clip word to line.
//Backtrack our scan of the source text.
it -= currentLine.length() - lineLength - 1;
//Remove the clipped word
currentLine.erase(lineLength);
}
result.push_back(currentLine);
currentLine.clear();
}
}
}
//Last remaining text.
result.push_back(currentLine);
return result;
}
void DrawInstructionsWithFilledBackground(HDC hDC, const std::wstring& text, RECT& targetRectangle, HFONT font, COLORREF backgroundColor)
{
//Set up our background color.
int dcIdx = SaveDC(hDC);
HBRUSH backgroundBrush = CreateSolidBrush(backgroundColor);
SelectObject(hDC, backgroundBrush);
SelectObject(hDC, font);
SetBkColor(hDC, backgroundColor);
std::vector<std::wstring> lines(wrapString(hDC, text, targetRectangle, font));
for(std::vector<std::wstring>::const_iterator it = lines.begin(); it!=lines.end(); it++)
{
RECT backgroundRect = targetRectangle;
DrawText(hDC, const_cast<LPWSTR>(it->c_str()), static_cast<int>(it->length()), &backgroundRect, DT_CALCRECT | DT_NOCLIP | DT_SINGLELINE);
backgroundRect.left = backgroundRect.right;
backgroundRect.right = targetRectangle.right;
if (backgroundRect.right >= backgroundRect.left)
FillRect(hDC, &backgroundRect, backgroundBrush);
ExtTextOut(hDC, targetRectangle.left, targetRectangle.top, ETO_OPAQUE, NULL, it->c_str(), static_cast<UINT>(it->length()), NULL);
targetRectangle.top += backgroundRect.bottom - backgroundRect.top;
}
instructionsWrap = lines;
//Restore the DC to it's former glory.
RestoreDC(hDC, dcIdx);
DeleteObject(backgroundBrush);
}
答案 4 :(得分:-1)
获取/计算DrawText调用使用的rect,并在调用FillRect之前将其与ExcludeClipRect一起剪辑