2009-06-01 9 views
11

Quando si modifica la didascalia di TLabel nella finestra di progettazione del modulo, viene ridimensionata la TLabel. C'è un modo in cui posso ottenere un TMemo per farlo, in fase di runtime?Posso creare una dimensione TMemo per il testo che contiene?

Mi piacerebbe essere in grado di prendere un TMemo, assegnare qualcosa alla sua proprietà .lines.text, e poi dirgli di ridimensionare se stesso e non superare una certa larghezza, anche se può arrivare alto quanto vuole . Qualcuno sa come farlo?

risposta

6

Impostare la WordWrap proprietà del TMemo true, scaricare il testo in esso, contare le linee, e impostare l'altezza al prodotto del numero di linea e l'altezza della linea, ma è necessario conoscere la linea altezza.

TMemo non espone una proprietà di altezza riga, ma se non si modifica il carattere o la dimensione del carattere in fase di esecuzione, è possibile determinare l'altezza della linea in modo sperimentale in fase di progettazione.

Ecco il codice che ho utilizzato per impostare l'altezza dello TMemo con un'altezza di riga di 13 pixel. Ho anche scoperto che avevo bisogno di una piccola costante per tenere conto dei bordi superiore e inferiore dello TMemo. Ho limitato l'altezza a 30 linee (396 pixel) per tenerlo sul modulo.

// Memo.WordWrap = True (at design time) 
Memo.Text := <ANY AMOUNT OF TEXT>; 
Memo.Height := Min(19 + Memo.Lines.Count * 13, 396); 

Se è assolutamente necessario estrarre l'altezza della linea dall'oggetto in fase di esecuzione, allora si potrebbe utilizzare Someone's answer. In alternativa, è possibile utilizzare TRichEdit, che ha la proprietà SelAttributes contenente una proprietà Height che fornisce l'altezza della riga.

-Al.

+0

Avrei dovuto pensarci. Sono troppo abituato a lavorare con TStringLists, che fanno interruzioni di riga in CRLF, che non mi è mai venuto in mente che la proprietà WordWrap avrebbe effettivamente messo linee avvolte su stringhe .Lines diverse. Grazie! –

+0

Font.Height contiene un numero negativo che conta il numero di pixel in una riga di testo. Puoi anche chiamare Canvas.TextExtent per calcolare l'altezza del testo. –

7

Questo funziona bene per me. La costante aggiunta (8) potrebbe variare a seconda che si stia utilizzando un bordo e/o una smussatura, sperimentando con essa.

procedure TForm1.Memo1Change(Sender: TObject); 
var 
    LineHeight: Integer; 
    DC: HDC; 
    SaveFont : HFont; 
    Metrics : TTextMetric; 
    Increase: Integer; 
    LC: Integer; 
begin 
    DC := GetDC(Memo1.Handle); 
    SaveFont := SelectObject(DC, Memo1.Font.Handle); 
    GetTextMetrics(DC, Metrics); 
    SelectObject(DC, SaveFont); 
    ReleaseDC(Memo1.Handle, DC); 
    LineHeight := Metrics.tmHeight; 
    Increase := Memo1.Height; 
    LC := Memo1.Lines.Count; 
    if LC < 1 then 
    LC := 1; 
    Memo1.Height := LC * LineHeight + 8; 
    Increase := Memo1.Height - Increase; 
    Memo1.Parent.Height := Memo1.Parent.Height + Increase; 
end; 
+0

Bella risposta. Ho scelto l'altro perché era più semplice, ma funziona abbastanza bene. A proposito, non devi preoccuparti del +8; puoi semplicemente assegnare ClientHeight e lasciare che il sistema si occupi del confine. –

+0

So che questo è vecchio, ma ho provato il suggerimento di @MasonWheeler e non ha mai funzionato correttamente. Credo che ClientHeight includa il riempimento interno del Memo. Quindi, anche impostando ClientHeight è necessario effettuare una chiamata a EM_GETRECT per calcolare realmente la regolazione della dimensione. – Tony

1
procedure TTmpMessage.edMsgChange (Sender: TObject); 
var 
    LineHeight : Integer; 
    DC   : HDC; 
    SaveFont : HFont; 
    Metrics : TTextMetric; 
begin 
    DC := GetDC (TRxRichEdit (Sender).Handle); 
    SaveFont := SelectObject (DC, TRxRichEdit (Sender).Font.Handle); 
    GetTextMetrics (DC, Metrics); 
    SelectObject (DC, SaveFont); 
    ReleaseDC (TRxRichEdit (Sender).Handle, DC); 
    LineHeight := Metrics.tmHeight; 
    Height := TRxRichEdit (Sender).Lines.Count * LineHeight + 32; 
end; 
2

Ho implementato un auto-coltivazione TMemo come un bel esempio di LiveBindings (uno dei pochi esempi utili potevo venire con per LiveBindings in VCL).

una citazione da mia Delphi XE2 Development Essentials manuale didattico:.

"Per costruire questo esempio, posizionare un componente TMemo su una forma VCL, aprire la proprietà LiveBindings, e selezionare l'opzione‘Nuovo LiveBinding’Scegli il . TBindExpression scelta Aprire BindExpressionMemo11 nel Inspector e impostare SourceComponent a Memo1 e SourceExpression a Lines.Count * 22. per ottenere un risultato migliore in fase di esecuzione, impostare SourceExpression l'espressione più precisa

Font.Size - 4 + (Lines.Count + 1) * -1 * (Font.Height - 3)

Infine, nel gestore eventi OnChange del TMemo, scrivere una riga di codice:

BindingsList1.Notify (Sender, '');

Questo è tutto. Compilati e corri a vedere il promemoria crescente in azione.alta

[Schermate]

Inizialmente, il controllo TMemo sarà due righe (la riga con i contenuti, e una linea successiva), e ogni volta che ha colpito entrare o word wrapping noi avanza alla riga successiva, la controllo TMemo crescerà in altezza (in crescita verso il basso in realtà, in modo da assicurarsi di lasciare sufficiente spazio sul modulo per la TMemo di espandersi) "

Groetjes, Bob Swart

+0

Ero davvero entusiasta di questa risposta, ma non sembra più un'opzione a partire da XE10 Berlin. – Tony

0

E perché non solo:.

Memo1.Height := Memo1.ContentBounds.Height + 5; 
+0

perché non è fmx –

Problemi correlati