2012-07-04 88 views
1

我有一個mfc應用程序,我必須在其中顯示文本。每當我使用滾動條時,都會調用OnDraw()函數。這是我的OnDraw()函數:在mfc應用程序中顯示文本文件時滾動

CString fileText = pDoc->GetFileText(); //get text from file 
CRect rect; 
GetClientRect(&rect); 

pDC->DrawText(fileText.GetString(), &rect, DT_LEFT|DT_NOCLIP); 

這似乎是效率低下,因爲滾動是永遠。問題是我正在重新繪製整個文本文件。我想使用GetClipBox函數重繪只有需要的。任何人都可以給我關於如何繼續的建議嗎?

謝謝。

回答

1

由於您仍將整個字符串繪製到離屏位圖上,所以雙緩衝將不會對您有所幫助。你想要的只是畫出實際顯示的字符串部分,這說起來容易做起來難。首先,如果每一行都具有相同的高度,這使得它更容易10倍(我還假設你沒有像在線圖像,格式化,段落間距等有趣的東西)。基本上你想要做的是沿着滾動條的總行數(假設你有1000行,滾動條在50%,這意味着你需要從第500行開始繪製)和您可以顯示多少行文本(可以通過將控制高度除以每行高度來輕鬆計算)。

然後,從字符串中提取這些行,並且只將這些行傳遞給DrawText()。最簡單的方法是將整個文本不是作爲一個字符串存儲,而是作爲一個字符串的向量,每個條目中一行。

現在仍然有一些細節需要弄清楚,比如當您一直滾動到最後時,顯示的內容是什麼,您是否允許半行顯示等等,但實際上上面是它沸騰的向下。

此外,我希望你沒有從每個OnDraw()的文件中讀取文本,因爲這可能會導致放緩。

GetClipBox()在這裏並不真正相關,因爲無論如何,即使只滾動1個像素,您仍然需要重新繪製內容窗口的整個內容。重點是減少要繪製的東西(您傳遞給DrawText())的數量,而不是限制正在繪製的屏幕空間量。

+0

當你重繪整個字符串時,我同意如果你繪製整個字符串,雙緩衝仍然會變慢。但是,僅用於滾動,根本不需要重新繪製字符串 - 只需使用BitBlt內存位圖進行屏幕顯示即可。不過,我同意你的看法 - 爲了加速完全重新繪製,你需要將文本分成幾部分並計算出你需要繪製的部分。這是棘手的。 – Redeye

+0

嗯,我想前進的方向是將文本分成幾行並只繪製相關的文字。就像你說的那樣,這會很棘手。還有,謝謝你的回答。 – molu

0

我認爲你的問題的最佳解決方案可能是雙緩衝。基本上,做你的畫到離屏位圖,然後在OnPaint()方法被調用時,只需撥打

CRect rcUpdate; 
GetClipBox(rcUpdate); 
pDC->BitBlt(rcUpdate.left, rcUpdate.top, rcUpdate.Width(), rcUpdate.Height(), 
         m_pMemDC, rcUpdate.left, rcUpdate.top, SRCCOPY); 

這將剛纔複製的屏幕的更新部分,應該大大提高你的表現。

我發佈了一些代碼,以幫助在前面的問題here雙緩衝區,這可能有所幫助。這還包括你實際上不需要的GDI +代碼,可以省略。

+0

感謝您的回答。提供雙緩衝。按照說明[這裏](http://www.codeproject.com/Articles/33/Flicker-Free-Drawing-In-MFC)。 它不起作用。事實上,情況更糟糕。我正在處理大約10mb的文本文件。 GetClipBox()似乎是唯一的方法(我知道的)。但是,我不知道該怎麼去做。 – molu

+1

我很驚訝雙緩衝更慢 - 我只能假設在某處執行有問題。但是,渲染大的文本文件可能需要不同的方法。你可能是正確的,你需要使用GetClipBox()。然後,您需要確定哪些文本需要重新繪製該CRect,並且只繪製該部分而不是整個文檔。我認爲你需要把這個字符串分解成子字符串,並且保留一個CRects列表來解決這個問題,但其他人可能會提出一個更好的方法。 – Redeye

+0

另外,當我嘗試按照您提到的鏈接中的代碼進行操作時,圖形中出現錯誤。 VS2010說它是一個未知的標識符。那是什麼? – molu

相關問題