2

Win32 でちょっとしたテキスト描画パズルを手に入れました。ウィンドウの上部にアプリケーションのユーザー向けの指示を表示しようとしています。

以下のウィンドウを参照してください(境界が見えるようにテキストの背景色を変更しました)

デモンストレーション
(出典: billy-oneal.com )

現在、DrawTextEx を使用してテキストをウィンドウに描画していますが、指定した RECTangle 全体が塗りつぶされていないという問題があります。ウィンドウのサイズが変更されるまで、その領域を描画しなくても問題ありません。

リサイズ後のデモンストレーション
(出典: billy-oneal.com )

ウィンドウのサイズ変更のためにテキストが再ラップされると、DrawTextEx はその背景をクリアしないため、これらのアーティファクトは残ります。

FillRect を使用して、テキスト描画呼び出しの背後の領域を塗りつぶそうとしました。これにより、視覚的なアーティファクトがなくなりますが、テキストが完全に消去されてからディスプレイに完全に再描画されるため、テキストがちらつきます。

テキストを含まない領域を背景色で描画する方法についてのアイデアはありますか?

編集:可能であれば、フォームをダブルバッファリングする必要はありません。

EDIT2:サイズ変更中にラッピングが変更されたことを検出した場合にのみ、テキストを再描画することで問題を解決しました。

4

5 に答える 5

4

ダブルバッファリングを使用しますか?

すべてをビットマップに描画し、ビットマップをウィンドウに描画します。ちらつきは、通常、ダブル バッファリングの問題です。

于 2009-12-02T21:00:36.297 に答える
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);
}
于 2009-12-07T01:20:30.867 に答える
2

SetBkMode + SetBkColor ?

于 2009-12-02T21:07:12.607 に答える
2

考えられる解決策はたくさんあります。コードを見ないと、どの方法が最適かを判断するのは難しいため、ちらつきのない描画に関するこの記事を参照することをお勧めします。

于 2009-12-02T21:06:42.857 に答える
-1

DrawText 呼び出しで使用される四角形を取得/計算し、FillRect を呼び出す前に ExcludeClipRect などでクリップします。

于 2009-12-02T21:55:55.490 に答える