2009-12-02 54 views
2

我在Win32下有一個小小的文字繪圖拼圖。我試圖在窗口頂部爲我的應用程序的用戶繪製一些說明。Win32文本繪圖拼圖

請參考下面的窗口(我已經改變背景顏色上的文本,所以你可以看到邊界)

Demonstration http://billy-oneal.com/forums/12-2-2009%203-46-15%20PM.png

我目前使用DrawTextEx的文字畫到我的窗口,但問題是它不會填充我給出的整個RECTangle。沒有繪製區域僅僅是罰款,直至調整窗口大小:

Demonstration after resize http://billy-oneal.com/forums/12-2-2009%203-51-45%20PM.png

當文本被重新包裝,由於窗口大小,因爲DrawTextEx並不清楚它的背景下,這些文物是剩。

我試着使用FillRect來填充文本繪圖調用後面的區域,它消除了視覺僞影,但隨後會導致文本不斷閃爍,因爲它會被完全擦除,然後完全重新繪製到顯示中。

關於如何讓不包含文本的區域用背景顏色繪製的任何想法?

編輯:我想避免必須雙緩衝窗體,如果在應用程序可能。

EDIT2:我在重新調整大小期間檢測到包裝發生變化時,通過重繪文本解決了問題。

+0

ExtTextOut + ETO_OPAQUE(https://msdn.microsoft.com/en-us/library/dd162713(v=vs.85).aspx) – 2017-02-26 10:46:01

回答

2

好,因爲似乎沒有人知道該怎麼做這件事之前,像ExcludeClipRect夾它,我實現了這種方式:

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

使用雙緩衝?

將一切都繪製到位圖並將位圖繪製到窗口。閃爍通常是一個雙緩衝問題。

+0

這將工作,但我想避免必須加倍緩衝一切進行如此簡單的操作。我在應用程序的其餘部分非常努力地工作,不需要雙緩衝區。看起來很遺憾,爲了這麼簡單的事情而浪費一切。 – 2009-12-02 21:03:53

+0

CPU是有限的資源還是內存?在前者的情況下,你可以對*當更新窗口時的限制性很強,即不多於每40ms更新一次。如果內存是你有限的資源,我想我們需要更多地瞭解你的硬件限制來解決你的問題。 – Pedery 2009-12-02 21:17:18

2

有許多可能的解決方案,並沒有看到你的代碼,這是很難說哪一種方法是最好的,所以我會建議考慮看看this article on flicker free drawing

+0

我讀過那篇文章 - 其他應用程序遵循指南。文本是唯一閃爍的東西。其他一切都很好。 – 2009-12-02 21:08:04

+0

你的意思是一個常量閃爍,或者只是在調整大小? – BarrettJ 2009-12-02 21:23:23

+0

僅在調整大小時。 – 2009-12-02 23:56:41

2

SetBkMode + SetBkColor?

+0

正確地在背後繪製背景。我需要一種方法讓函數在每行的左側繪製背景以填充指令所在的矩形。 – 2009-12-02 21:11:32

-1

獲取/計算由DrawText的調用中使用的矩形,並調用FillRect

+1

獲取/計算DrawText使用的矩形< - 照顧我如何將不規則形狀表示爲RECT? – 2009-12-02 23:57:29

+0

你已經有一個RECT,你傳遞給DrawText(首先用DT_CALCRECT或一些「硬編碼」值調用它) – Anders 2009-12-03 08:29:44