2011-10-10 38 views
7

我正在使用Delphi 7.我比使用畫布和繪製文本到畫布以及使用TCanvas.TextHeight等要熟悉的多。問題出現在我想要的時候實施Word Wrap。我不僅需要最好的方法來將文本繪製到畫布上,並且它會自動包裝到給定的寬度約束,但是我還需要知道它在包裝後有多高(或多少行)。在繪製文本之前,我需要準備另一張圖像,這個圖像需要足夠大才能放置包裝文本。這是試圖複製iPhone顯示SMS消息的方式,在可變高度滾動框(TScrollingWinControl是我的基礎)的屏幕兩側都有一個氣球。在繪製到畫布之前計算文本的大小

+3

使用的DrawText,並讓系統做自動換行 –

回答

32

使用(幾乎)萬能DrawText使用初始矩形DT_CALCRECT功能,和標誌DT_WORDBREAK(意味着字符串應該是自動換行)和:

procedure TForm1.FormPaint(Sender: TObject); 
const 
    S = 'This is a sample text, I think, is it not?'; 
var 
    r: TRect; 
begin 
    r := Rect(10, 10, 60, 60); 
    DrawText(Canvas.Handle, 
    PChar(S), 
    Length(S), 
    r, 
    DT_LEFT or DT_WORDBREAK or DT_CALCRECT); 

    DrawText(Canvas.Handle, 
    PChar(S), 
    Length(S), 
    r, 
    DT_LEFT or DT_WORDBREAK); 
end; 

由於標誌DT_CALCRECT,第一DrawText將不會繪製任何東西,但只會改變r的高度,以便它可以包含整個字符串S(或者如果S恰好適合單行,則會減少r的寬度;此外,如果S包含的字詞n不適合在一條線上,則會增加r的寬度)。然後你可以用r做任何你想做的事情,然後你就可以繪製真正的字符串。

試試這個,例如:

procedure TForm1.FormPaint(Sender: TObject); 
const 
    S: array[0..3] of string = ('Hi! How are you?', 
    'I am fine, thanks. How are you? How are your kids?', 
    'Fine!', 
    'Glad to hear that!'); 
    Colors: array[boolean] of TColor = (clMoneyGreen, clSkyBlue); 
    Aligns: array[boolean] of integer = (DT_RIGHT, DT_LEFT); 
var 
    i, y, MaxWidth, RectWidth: integer; 
    r, r2: TRect; 
begin 

    y := 10; 
    MaxWidth := ClientWidth div 2; 

    for i := low(S) to high(S) do 
    begin 

    Canvas.Brush.Color := Colors[Odd(i)]; 

    r := Rect(10, y, MaxWidth, 16); 
    DrawText(Canvas.Handle, 
     PChar(S[i]), 
     Length(S[i]), 
     r, 
     Aligns[Odd(i)] or DT_WORDBREAK or DT_CALCRECT); 

    if not Odd(i) then 
    begin 
     RectWidth := r.Right - r.Left; 
     r.Right := ClientWidth - 10; 
     r.Left := r.Right - RectWidth; 
    end; 

    r2 := Rect(r.Left - 4, r.Top - 4, r.Right + 4, r.Bottom + 4); 
    Canvas.RoundRect(r2, 5, 5); 

    DrawText(Canvas.Handle, 
     PChar(S[i]), 
     Length(S[i]), 
     r, 
     Aligns[Odd(i)] or DT_WORDBREAK); 

    y := r.Bottom + 10; 

    end; 

end; 

procedure TForm1.FormResize(Sender: TObject); 
begin 
    Invalidate; 
end; 

Screenshot http://privat.rejbrand.se/DrawTextChat.png

+7

+1失望的談話是不是在瑞典...... ;-) –

+0

真棒,實際上我發現這只是在找到這個答覆之前...謝謝你一堆,這將在這個組件很好。現在,如果我能得到一些建議什麼是這個組件的最佳繼承 - TScrollingWinControl/TImage(直接畫布)或TScrollingWinControl/TDrawGrid(Grid畫布)?它當然需要能夠輕鬆地上下滾動 - 我有一個使用TScrollBox中的TDrawGrid的版本 - 但需要更直接的繼承。 –

+0

嗨安德烈亞斯 - 很好的答案像往常一樣! – Ampere

相關問題