Win32文字绘图拼图 [英] Win32 Text Drawing Puzzle

查看:99
本文介绍了Win32文字绘图拼图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Win32下,我有一个小小的文字绘图难题。我正在尝试在窗口顶部为我的应用程序的用户绘制一些说明。



请参考以下窗口(我更改了背景色文本,以便您可以看到边界)





(来源:

(来源: billy-oneal.com



由于窗口大小而重新包装文本时,由于DrawTextEx不能清除其背景,这些工件被保留了。



我尝试使用FillRect填充文本绘图调用后的区域,这确实消除了视觉瑕疵,但随后导致文本不断闪烁,因为将其完全擦除然后完全重绘到显示上。



关于如何使不包含要用背景色绘制文本的区域的任何想法?



编辑:我想避免在应用程序可能的情况下必须双重缓冲表单。



编辑2:我仅在检测到调整大小时包装改变时才重绘文本,从而解决了该问题。

解决方案

好吧,因为似乎没人知道该怎么做,所以我以这种方式实现了它:

  std :: vector< std :: wstring> wrapString(HDC hDC,const std :: wstring& text,const RECT& targetRect,HFONT字体)
{
std :: vector< std :: wstring>结果;
RECT targetRectangle;
CopyRect(& targetRectangle,& targetRect);

//计算边界矩形的宽度。
int maxWidth = targetRectangle.right-targetRectangle.left;

//一次绘制一条线
std :: wstring currentLine;
for(std :: wstring :: const_iterator它= text.begin();它!= text.end(); currentLine.push_back(* it),它++)
{
if (* it == L'\r'|| * it == L'\n')
{//硬返回
while(it!= text.end()&& ;(* it == L'\r'|| * it == L'\n'))it ++;
result.push_back(currentLine);
currentLine.clear();
}
else
{//检查软收益
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)
{//单词长于一行。
for(; it!= text.end()&!iswspace(* it); it ++)currentLine.push_back(* it);
}
else
{//将单词切成一行。
//回溯我们对源文本的扫描。
it-= currentLine.length()-lineLength-1;
//删除被剪裁的单词
currentLine.erase(lineLength);
}
result.push_back(currentLine);
currentLine.clear();
}
}
}
//最后剩余的文字。
result.push_back(currentLine);
的返回结果;
}

void DrawInstructionsWithFilledBackground(HDC hDC,const std :: wstring& text,RECT& targetRectangle,HFONT font,COLORREF backgroundColor)
{
//设置我们的背景色。
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 =行;
//将DC恢复为以前的荣耀。
RestoreDC(hDC,dcIdx);
DeleteObject(backgroundBrush);
}


I've got a little text drawing puzzle under Win32. I'm trying to draw some instructions for users of my application at the top of the window.

Please refer to the following window (I've changed the background color on the text so you can see the boundaries)


(source: billy-oneal.com)

I'm currently using DrawTextEx to draw the text to my window, but the problem is that it does not fill the entire RECTangle that I give it. Not drawing that area is just fine, until the window resizes:


(source: billy-oneal.com)

When the text is re wrapped due to the window sizing, because DrawTextEx doesn't clear it's background, these artifacts are leftover.

I tried using FillRect to fill in the area behind the text drawing call, which does eliminate the visual artifacts, but then causes the text to flicker constantly, as it is completely erased and then completely redrawn to the display.

Any ideas on how one might get the area not containing text to be drawn with the background color?

EDIT: I'd like to avoid having to double buffer the form if at app possible.

EDIT2: I solved the problem by only redrawing the text when I detect that the wrapping changes during a resize.

解决方案

Well since nobody seems to know what to do about it, I implemented it this way:

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

这篇关于Win32文字绘图拼图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆