Mega Code Archive

 
Categories / Delphi / VCL
 

TListBox with WordWrap

Title: TListBox with WordWrap Question: TListBox gives no possibility to wrap lines. If there is a long line it is invisible since scrolling is enabled. With the help of two events of TListBox it is possible to display wrapped lines without changing the number of total lines. Answer: TListBox gives the possibility to draw items yourself. There also the possibility to set a custom height for every single item. For doing so Style has to be set to lbOwnerDrawVariable. Then there are two events that can be used. OnMeasureItem is for telling Delphi the height of the item and OnDrawItem for drawing the item. Now wrapped text can be displayed: First it is necessary to obtain the actual size of wrapped then. Second the text has to be drawn on the canvas of the ListBox. Neither the item itself nor the number of items in the TListBox has to be changed with means that the rest of the source needs not to be changed. Here is the code: type TWrapRecord=record Height:Integer; Lines: array of string; end; function WrapText(Canvas:TCanvas; Text:string; const MaxWidth:integer):TWrapRecord; var S:string; CurrWidth:integer; begin SetLength(Result.Lines,0); Result.Height:=0; CurrWidth:=MaxWidth; Text:=Text+' '; repeat S:=copy(Text,1,pos(' ',Text)-1); Delete(Text,1,pos(' ',Text)); if (Canvas.TextWidth(S+' ')+CurrWidth)then begin with Result do Lines[High(Lines)]:=Lines[High(Lines)] + ' ' +S; Inc(CurrWidth, Canvas.TextWidth(S+' ')); end else with Result do begin if length(Lines)0 then Inc(Height,Canvas.TextHeight(Lines[High(Lines)])); SetLength(Lines,length(Lines)+1); Lines[High(Lines)]:=S; CurrWidth:=Canvas.TextWidth(S); end; until length(TrimRight(Text))=0; with Result do Inc(Height,Canvas.TextHeight(Lines[High(Lines)])); end; procedure TForm1.ListBoxMeasureItem(Control: TWinControl; Index: Integer; var Height: Integer); var WrapRecord:TWrapRecord; begin with Control as TListBox do begin Canvas.Font.Assign(Font); WrapRecord:=WrapText(Canvas,Items[Index],ClientWidth); if WrapRecord.Heightthen WrapRecord.Height:=ItemHeight; end; Height:=WrapRecord.Height; end; procedure TForm1.ListBoxDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); var WrapRecord:TWrapRecord; i,y:integer; begin with Control as TListBox do begin Canvas.Font.Assign(Font); Canvas.FillRect(Rect); WrapRecord:=WrapText(Canvas,Items[Index],ClientWidth); y:=Rect.Top; for i:=Low(WrapRecord.Lines) to High(WrapRecord.Lines) do begin Canvas.TextOut(Rect.Left,y,WrapRecord.Lines[i]); Inc(y,Canvas.TextHeight(WrapRecord.Lines[i])); end; end; end; procedure TForm1.FormCreate(Sender: TObject); begin ListBox.OnMeasureItem:=ListBoxMeasureItem; ListBox.OnDrawItem:=ListBoxDrawItem; ListBox.Style:=lbOwnerDrawVariable; end;