2011-10-10 11 views
7

Sto usando Delphi 7. Sono più che pratico nell'usare una tela e disegnare del testo su una tela, e anche usando TCanvas.TextHeight ecc. Il problema sorge quando voglio implementare Word Wrap. Non solo ho bisogno del modo migliore per disegnare il testo su una tela e farlo avvolgere automaticamente su un determinato vincolo di larghezza, ma ho anche bisogno di sapere quanto in alto (o quante linee) sarà dopo averlo avvolto. Ho bisogno di preparare un'altra immagine prima di disegnare il testo, un'immagine che deve essere grande abbastanza per posizionare il testo avvolto. Questo è un tentativo di replicare come un iPhone visualizza messaggi SMS, con un baloon su entrambi i lati dello schermo in una casella a scorrimento di altezza variabile (TScrollingWinControl è la mia base).Calcolo della dimensione del testo prima di disegnare su una tela

+3

Usa DrawText e lasciare che il sistema di fare la parola avvolgendo –

risposta

32

Utilizzare la (quasi) onnipotente funzione DrawText utilizzando un rettangolo iniziale, e le bandiere DT_WORDBREAK (nel senso che la stringa dovrebbe essere word-wrapped) e DT_CALCRECT:

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; 

Grazie alla bandiera DT_CALCRECT, il primo DrawText non disegna nulla, ma modifica solo l'altezza di r in modo che possa contenere l'intera stringa S (o riduca la larghezza di r se S si adatta a una singola riga; inoltre, se S contiene una parola che n Ot adattarsi su una sola riga, la larghezza di r sarà aumentata). Quindi puoi fare quello che vuoi con r, e quindi puoi disegnare la stringa per davvero.

Prova questo, ad esempio:

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 deluso la conversazione non era in Svedese ...... ;-) –

+0

Fantastico, in realtà l'ho scoperto solo prima di trovare questa risposta ... Grazie mille, questo funzionerà alla grande in questo componente. Ora, se posso avere qualche consiglio, quale è l'ereditarietà migliore per questo componente: TScrollingWinControl/TImage (canvas diretto) o TScrollingWinControl/TDrawGrid (tela griglia)? Ovviamente deve essere in grado di scorrere facilmente verso l'alto e verso il basso - Ho una versione che funziona con un TDrawGrid in un TScrollBox - ma ho bisogno di un'eredità più diretta. –

+0

Ciao Andreas - Ottima risposta come al solito! – Ampere

Problemi correlati