我想做这个这样(附图)的控件,应该从哪个控件来继承 ( 积分: 50 )

  • 主题发起人 主题发起人 QSmile
  • 开始时间 开始时间
Q

QSmile

Unregistered / Unconfirmed
GUEST, unregistred user!
图在这里: http://www.lzxjz.com/redfox/test1.gif

这是我做的。我是从 TListBox 继承来的。

我是想做一个这样的控件。数据我加入了 List 了。但数据有长有短,长的就要自动分行。短的当然就不用了。Item 的高度也就是不同的。
但控件的宽度在运行时是可能改变的。

原来我是用 ListBox 的 MeasureItem 事件中来计算 Item 的高。但这个事件只会触发一次。就是数据第一次加入 ListBox 后会触发一次,改变宽度后不会再触发了。

这样改变宽度后就可能长的数据最后有些看不到了。
我希望改变宽度后 Item 的高度也可以适时的改变。

我应该如何做?或不用ListBox 大侠给我提供一个思路也可。
Thanks
 
图在这里: http://www.lzxjz.com/redfox/test1.gif

这是我做的。我是从 TListBox 继承来的。

我是想做一个这样的控件。数据我加入了 List 了。但数据有长有短,长的就要自动分行。短的当然就不用了。Item 的高度也就是不同的。
但控件的宽度在运行时是可能改变的。

原来我是用 ListBox 的 MeasureItem 事件中来计算 Item 的高。但这个事件只会触发一次。就是数据第一次加入 ListBox 后会触发一次,改变宽度后不会再触发了。

这样改变宽度后就可能长的数据最后有些看不到了。
我希望改变宽度后 Item 的高度也可以适时的改变。

我应该如何做?或不用ListBox 大侠给我提供一个思路也可。
Thanks
 
试试文本框
 
1、可以计算ScrollWidth把横向的滚动条弄出来么!
2、实在喜欢多行的LIST!看下面,一个很不错的,和你的要求非常接近!
{
==================================================================================
TILB
INDENTED LISTBOX COMPONENT V 1.3 Feb-97
By Santiago Portela: sportela@cece.es
Please feel free to copy, modify or distribute this component
==================================================================================
This component displays multiline items in a list box.
Changes to version 1.2 Oct-96:

- Supported linebreak char: '/' . Any line containing '/' will be splitted

- New Font2 property instead of style&color

- Component Name is changed to TILB, to allow using previous version
=================================================================================

TlistBox Descendant. 5 new properties:
indent
PosIndent
DrawLines
DrawLineColor
FontHeader


indent property
inone wraps each item to the number of lines required.

itab split each line where '|' (#124) is found. First part
is displayed aligned to the leftmost part of the component;
second part is displayed left aligned to the indent position
(the indent position is set in property PosIndent).
Text is wrapped to the number of lines required.

iline Same as itab, but instead of spliting vertically the
component, first part is displayed in first line and
second part in the following lines.

Default is inone

PosIndent property
integer Used only when Indent is itab. PosIndent is the position
(in pixels) inside the control where second part of
itms are left aligned.

Default is 48

DrawLines property
boolean Used with itab, iline. If TRUE, a line is drawed below
each item.

DrawLineColor property
Tcolor Color of lines if DrawLine is TRUE.


FontHeader property Font for first part


*BUGS* *BUGS* *BUGS* *BUGS* *BUGS* *BUGS* *BUGS* *BUGS* *BUGS* *BUGS* *BUGS*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

1.If component's font is changed, please refill items list, otherwise the
height of lines is still calculated upon previous font.

2.VERY CAREFULL setting width too small. Component may hang up.

==================================================================================
}

unit Ilb;

interface


uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls;

type
TEnumType = (inone,itab,iline);

type
TILB = class(TListBox)
private

Findent:TEnumType; {--- indent option---}
Fi:integer; {--- indent position--}
lista:tstringlist; {--- working list----}
alto:integer; {--default char height--}
LineColor:TColor;
DoDrawLines:boolean; {-- wether draw lines or not--}
FFont2:TFont;
Procedure SetFont2(value:tfont);
Procedure SetIndent(i:TEnumType); {-- sets Findent---}
Function GetIndent:TEnumType; {-- retrieves Findent--}
Procedure SetFi(i:integer); {--sets Fi--}
Function GetFi:integer; {--retrieves Fi--}

protected
Procedure DrawItem(Index:integer;R:trect;State:TownerDrawState);override;
{-- Custom drawing of items in the list---}
Procedure MeasureItem(Index:integer;var altura:integer);override;
{-- Callback to calculate each item height in the list--}
public
constructor Create(owner:tcomponent);override;
destructor Destroy;override;
published
Property DrawLineColor:TColor read LineColor write LineColor;
Property DrawLines:boolean read DoDrawLines write DoDrawLines;
Property FontHeader:tfont read ffont2 write SetFont2;
property Indent:TenumType read GetIndent write SetIndent ;
property PosIndent:integer read GetFi write SetFi;
end;

procedure Register;

implementation

{---------------------------------------------------------------------------}
Procedure rtrim(var ax:string); { rtrim eliminates training whitespaces at the end of the string}
var i:integer;
begin
i:=length(ax);
while((i>0) and (ax=' ')) do dec(i);
ax:=copy(ax,1,i);
end;

function izqc(ax:string;c:char):string;
begin
if pos(c,ax)=0 then izqc:=''
else izqc:=copy(ax,1,pos(c,ax)-1);
end;

function derc(ax:string;c:char):string;
begin
if pos(c,ax)=0 then derc:=''
else derc:=copy(ax,pos(c,ax)+1,length(ax)-pos(c,ax));
end;


Procedure wrapone(ax:string;tl:tstrings;can:tcanvas;n:integer);
var i,j,k,m,q:integer;
bx,cx,qx:string;
hecho:boolean;
hd:HDC;
begin
rtrim(ax);
hecho:=false;
q:=1;
repeat
inc(q);
if q>100 then hecho:=true;
k:=can.textwidth(ax);
if k<=n then begin {---When widht holds in line --}
tl.add(ax);
hecho:=true;
end
else begin {---When widht exceeds line --}
m:=1;
bx:=ax[m];
while (can.textwidth(bx)<n) do begin
inc(m);
bx:=bx+ax[m];
end;
bx:=copy(ax,1,m);
cx:=copy(ax,m+1,length(ax)-m);
while (bx[m]<>' ') do begin
cx:=bx[m]+cx;
dec(m);
end;
bx:=copy(bx,1,m);
tl.add(bx);
ax:=cx;
end;
until hecho;
end;


Procedure wrapx(ax:string;tl:tstrings;can:tcanvas;n:integer);
var i,j,k,m,q:integer;
bx,cx,qx:string;
hecho:boolean;
hd:HDC;
begin
rtrim(ax);
tl.clear;
{-------- Line break control-----}
hecho:=false;
repeat
q:=pos('/',ax);
if q>0 then begin
qx:=izqc(ax,'/');
wrapone(qx,tl,can,n);
ax:=derc(ax,'/');
end
else begin
if ax<>'' then wrapone(ax,tl,can,n);
hecho:=true;
end;
until hecho;
end;


{----------------------------------------------------------------------------}


Constructor TILB.Create(owner:tcomponent);
var i:integer;
begin
inherited create(owner);
ffont2:=tfont.create;
Left := 20;
Top := 20;
Width := 100;
Height := 100;
ItemHeight := font.height+2;
ParentFont := False;
Style := lbOwnerDrawVariable;
Indent := itab;
PosIndent := 48;
DrawLines := True;
DrawLineColor:=clSilver;
lista:=tstringlist.create;
end;

destructor TILB.Destroy;
begin
lista.clear;
lista.destroy;
ffont2.destroy;
inherited destroy;
end;

Procedure TILB.SetFont2(value:tfont);
begin
ffont2.assign(value);
end;

Procedure TILB.SetIndent(i:TEnumType);
begin
if Findent<>i then begin
Findent:=i;
Style := lbOwnerDrawVariable;
invalidate;
end;
end;

Function TILB.GetIndent:TEnumType;
begin
GetIndent:=Findent;
end;

Procedure TILB.SetFi(i:integer);
begin
if Fi<>i then begin
Fi:=i;
invalidate;
end;
end;

Function TILB.GetFi:integer;
begin
GetFi:=Fi;
end;



Procedure TILB.MeasureItem(Index:integer;var altura:integer);
var
al,ancho:integer;
nlines:integer;
ax,bx:string;
postab:integer;

begin
inherited MeasureItem(Index,altura);
al:=altura;
postab:=pos(#124,items[index]);
if postab>0 then begin
ax:=copy(items[index],1,postab-1);
bx:=copy(items[index],postab+1,length(items[index])-postab);
end
else begin
ax:=' ';
bx:=items[index];
end;
canvas.font:=font;
with canvas do begin
if width<=posindent then posindent:=width div 2;
nlines:=1;
alto:=canvas.textheight('|_罬');
case indent of
inone:begin
wrapx(items[index],lista,canvas,width-20);
nlines:=lista.count;
end;
itab:begin
wrapx(bx,lista,canvas,width-posindent-20);
nlines:=lista.count;
end;
iline:begin
wrapx(bx,lista,canvas,width-20);
nlines:=lista.count+1;
end;
end;
end;
altura:=nlines*alto;
canvas.font:=FontHeader;
if abs(canvas.textheight('|_罬'))>altura then altura:=abs(canvas.textheight('|_罬'));
if al>altura then altura:=al;
end;

Procedure TILB.DrawItem(Index:integer;R:trect;State:TownerDrawState);
var
ax,bx:string;
i,j:integer;
postab:integer;
c1,c2:tcolor;
begin


canvas.font:=font;

postab:=pos(#124,items[index]);
if postab>0 then begin
ax:=copy(items[index],1,postab-1);
bx:=copy(items[index],postab+1,length(items[index])-postab);
end
else begin
ax:=' ';
bx:=items[index];
end;

if odselected in state then begin
c1:=rgb(not getrvalue(font.color),not getgvalue(font.color),not getbvalue(font.color));
c2:=rgb(not getrvalue(fontheader.color),not getgvalue(fontheader.color),not getbvalue(fontheader.color));
end
else begin
c1:=font.color;
c2:=fontheader.color;
end;


with Canvas do { draw on the control canvas, not on the form }
begin
FillRect(R); { clear the rectangle }

case indent of
inone:begin
settextcolor(canvas.handle,c1);
wrapx(items[index],lista,canvas,width-20);
for i:=0 to lista.count-1 do
TextOut(R.Left +1, R.Top+i*alto, lista.strings);
end;
itab:begin
wrapx(bx,lista,canvas,width-posindent-20);
lista.add(ax);
canvas.font:=FontHeader;
settextcolor(canvas.handle,c2);
TextOut(r.left,r.top,lista.strings[lista.count-1]);
canvas.font:=Self.font;
settextcolor(canvas.handle,c1);
for i:=0 to lista.count-2 do
TextOut(R.Left +posindent, R.Top+i*alto, lista.strings);
if DoDrawLines then begin
canvas.pen.color:=DrawLineColor;
MoveTo(R.Left , R.bottom-1);
LineTo(R.right, R.bottom-1);
end;
end;
iline:begin
wrapx(bx,lista,canvas,width-20);
lista.add(ax);
canvas.font:=fontheader;
settextcolor(canvas.handle,c2);
TextOut(r.left,r.top,lista.strings[lista.count-1]);
canvas.font:=self.font;
settextcolor(canvas.handle,c1);
for i:=0 to lista.count-2 do
TextOut(R.Left , R.Top+(i+1)*alto, lista.strings);
if DoDrawLines then begin
canvas.pen.color:=DrawLineColor;
MoveTo(R.Left , R.bottom-1);
LineTo(R.right, R.bottom-1);
end;

end;
end;
end;

end;




procedure Register;
begin
RegisterComponents('Samples', [TILB]);
end;

end.
 
楼上的控件好象不太行
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部