gpt4 book ai didi

delphi - TListbox - 操纵图像和文本的布局?

转载 作者:行者123 更新时间:2023-12-03 14:47:39 27 4
gpt4 key购买 nike

我一直在尝试使用 TListBox 控件、绘制图像和更改字体样式等。我想稍微加强一下,并尝试通过缩进和多级缩进来更多地操作项目。

看看这张图片以获得更好的想法:

enter image description here

这个想法是列表中位于起始项和结束项之间的项应相应缩进。

因此,为了给出一个想法,我在 Paint 中编辑了屏幕截图,因此它看起来像这样:

enter image description here

解决这个问题的方法是什么?我的想法是迭代列表框并在两个单独的变量中返回开始和结束项目的数量,然后以某种方式确定其他项目在哪里以及它们之间是否适合 - 但我的逻辑从来都不是那么好:(

为了便于使用,我在下面提供了代码来展示如何绘制图像和样式:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ImgList, ComCtrls;

type
TForm1 = class(TForm)
ImageList1: TImageList;
PageControl1: TPageControl;
TabSheet1: TTabSheet;
ListBox1: TListBox;
TabSheet2: TTabSheet;
ListBox2: TListBox;
TabSheet3: TTabSheet;
ListBox3: TListBox;
procedure FormCreate(Sender: TObject);
procedure ListBox1MeasureItem(Control: TWinControl; Index: Integer;
var Height: Integer);
procedure ListBox1DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
procedure ListBox2MeasureItem(Control: TWinControl; Index: Integer;
var Height: Integer);
procedure ListBox2DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
procedure ListBox3MeasureItem(Control: TWinControl; Index: Integer;
var Height: Integer);
procedure ListBox3DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

// assign quick identifiers to image indexes
const
imgLayout = 0;
imgCalculator = 1;
imgComment = 2;
imgTime = 3;
imgStart = 4;
imgEnd = 5;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
ListStyle: TListBoxStyle;
begin
// set the listbox style here
ListStyle := lbOwnerDrawVariable;
ListBox1.Style := ListStyle;
ListBox2.Style := ListStyle;
ListBox3.Style := ListStyle;
end;

{******************************************************************************}

procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
var
TextPosition: Integer;
Images: TImageList;
begin
TListBox(Control).Canvas.FillRect(Rect);
Images := ImageList1;

// draw the images
if TListBox(Control).Items.Strings[Index] = 'Layout' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgLayout);
end else
if TListBox(Control).Items.Strings[Index] = 'Calculator' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top,
imgCalculator);
end else
if TListBox(Control).Items.Strings[Index] = 'Comment' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgComment);
end else
if TListBox(Control).Items.Strings[Index] = 'Time' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgTime);
end;

// positions the text
TextPosition := (Rect.Bottom - Rect.Top - TListBox(Control).Canvas.TextHeight
(Text)) div 2;

// displays the text
TListBox(Control).Canvas.TextOut(Rect.Left + Images.Width + 8,
Rect.Top + TextPosition, TListBox(Control).Items.Strings[index]);
end;

procedure TForm1.ListBox1MeasureItem(Control: TWinControl; Index: Integer;
var Height: Integer);
begin
Height := ImageList1.Height;
end;

{******************************************************************************}

procedure TForm1.ListBox2DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
var
TextPosition: Integer;
Images: TImageList;
begin
TListBox(Control).Canvas.FillRect(Rect);
Images := ImageList1;

// draw the images
if TListBox(Control).Items.Strings[Index] = 'Layout' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgLayout);
TListBox(Control).Canvas.Font.Style := [fsBold];
end else
if TListBox(Control).Items.Strings[Index] = 'Calculator' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top,
imgCalculator);
TListBox(Control).Canvas.Font.Color := clBlue;
TListBox(Control).Canvas.Font.Style := [fsItalic];
end else
if TListBox(Control).Items.Strings[Index] = 'Comment' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgComment);
TListBox(Control).Canvas.Font.Color := clRed;
end else
if TListBox(Control).Items.Strings[Index] = 'Time' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgTime);
end;

// positions the text
TextPosition := (Rect.Bottom - Rect.Top - TListBox(Control).Canvas.TextHeight
(Text)) div 2;

// displays the text
TListBox(Control).Canvas.TextOut(Rect.Left + Images.Width + 8,
Rect.Top + TextPosition, TListBox(Control).Items.Strings[index]);
end;

procedure TForm1.ListBox2MeasureItem(Control: TWinControl; Index: Integer;
var Height: Integer);
begin
Height := ImageList1.Height;
end;

{******************************************************************************}

procedure TForm1.ListBox3DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
var
TextPosition: Integer;
Images: TImageList;
begin
TListBox(Control).Canvas.FillRect(Rect);
Images := ImageList1;

// draw the images
if TListBox(Control).Items.Strings[Index] = 'Layout' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgLayout);
end else
if TListBox(Control).Items.Strings[Index] = 'Calculator' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top,
imgCalculator);
end else
if TListBox(Control).Items.Strings[Index] = 'Comment' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgComment);
end else
if TListBox(Control).Items.Strings[Index] = 'Time' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgTime);
end else
if TListBox(Control).Items.Strings[Index] = 'Start' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top,
imgStart);
TListBox(Control).Canvas.Font.Style := [fsBold];
end else
if TListBox(Control).Items.Strings[Index] = 'End' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgEnd);
TListBox(Control).Canvas.Font.Style := [fsBold];
end;

// positions the text
TextPosition := (Rect.Bottom - Rect.Top - TListBox(Control).Canvas.TextHeight
(Text)) div 2;

// displays the text
TListBox(Control).Canvas.TextOut(Rect.Left + Images.Width + 8,
Rect.Top + TextPosition, TListBox(Control).Items.Strings[index]);
end;

procedure TForm1.ListBox3MeasureItem(Control: TWinControl; Index: Integer;
var Height: Integer);
begin
Height := ImageList1.Height;
end;

{******************************************************************************}

end.

我希望获得一些关于如何确定操纵这些项目的提示。我知道我可以更改位图和文本的放置位置,但它正在识别某个项目是否位于组之间,以及它是否设置了正确的缩进级别。

我希望这是有道理的,这就是为什么我放了一些模拟图片。

谢谢:)

PS,抱歉,我从不写小帖子!

使用工作演示进行更新

我已经接受了 Sertac 的回答,感谢 Sertac,我的回答非常完美。

为了帮助其他可能正在查看的人 - 并且因为我一直在学习 OOP,所以我想展示我的代码,看看它是否有任何好处:)

我制作了 2 个单元,Lib.pas 包含列表项的类,Unit1.pas 是 Form1 单元(我缩短了单元 1,以便更清楚地了解发生了什么):

Lib.pas

unit Lib;

interface

uses
Classes, StdCtrls;

type
TMyListData = class(TObject)
public
fCaption: string;
fImageIndex: integer;
public
property Caption: string read fCaption write fCaption;
property ImageIndex: integer read fImageIndex write fImageIndex;

constructor Create;
destructor Destroy; override;
end;

type
TLayoutItem = class(TMyListData);
TCalculatorItem = class(TMyListData);
TCommentItem = class(TMyListData);
TTimeItem = class(TMyListData);
TStartItem = class(TMyListData);
TEndItem = class(TMyListData);

const
imgLayout = 0;
imgCalculator = 1;
imgComment = 2;
imgTime = 3;
imgStart = 4;
imgEnd = 5;

procedure NewLayoutItem(aListBox: TListBox);
procedure NewCalculatorItem(aListBox: TListBox);
procedure NewCommentItem(aListBox: TListBox);
procedure NewTimeItem(aListBox: TListBox);
procedure NewStartItem(aListBox: TListBox);
procedure NewEndItem(aListBox: TListBox);
procedure DeleteItem(aListBox: TListBox; aIndex: integer);
procedure CalculateIndents(aListBox: TListBox);

implementation

{ TMyListData }

constructor TMyListData.Create;
begin
inherited Create;
end;

destructor TMyListData.Destroy;
begin
inherited;
end;

procedure NewLayoutItem(aListBox: TListBox);
var
Obj: TLayoutItem;
begin
Obj := TLayoutItem.Create;
try
Obj.Caption := 'Layout';
Obj.ImageIndex := imgLayout;

aListBox.AddItem(Obj.Caption, Obj);
finally
Obj.Free;
end;

CalculateIndents(aListBox);
end;

procedure NewCalculatorItem(aListBox: TListBox);
var
Obj: TCalculatorItem;
begin
Obj := TCalculatorItem.Create;
try
Obj.Caption := 'Calculator';
Obj.ImageIndex := imgCalculator;

aListBox.AddItem(Obj.Caption, Obj);
finally
Obj.Free;
end;

CalculateIndents(aListBox);
end;

procedure NewCommentItem(aListBox: TListBox);
var
Obj: TCommentItem;
begin
Obj := TCommentItem.Create;
try
Obj.Caption := 'Comment';
Obj.ImageIndex := imgComment;

aListBox.AddItem(Obj.Caption, Obj);
finally
Obj.Free;
end;

CalculateIndents(aListBox);
end;

procedure NewTimeItem(aListBox: TListBox);
var
Obj: TTimeItem;
begin
Obj := TTimeItem.Create;
try
Obj.Caption := 'Time';
Obj.ImageIndex := imgTime;

aListBox.AddItem(Obj.Caption, Obj);
finally
Obj.Free;
end;

CalculateIndents(aListBox);
end;

procedure NewStartItem(aListBox: TListBox);
var
Obj: TStartItem;
begin
Obj := TStartItem.Create;
try
Obj.Caption := 'Start';
Obj.ImageIndex := imgStart;

aListBox.AddItem(Obj.Caption, Obj);
finally
Obj.Free;
end;

CalculateIndents(aListBox);
end;

procedure NewEndItem(aListBox: TListBox);
var
Obj: TEndItem;
begin
Obj := TEndItem.Create;
try
Obj.Caption := 'End';
Obj.ImageIndex := imgEnd;

aListBox.AddItem(Obj.Caption, Obj);
finally
Obj.Free;
end;

CalculateIndents(aListBox);
end;


procedure DeleteItem(aListBox: TListBox; aIndex: integer);
begin
aListBox.Items.Delete(aIndex);
aListBox.Items.Objects[aIndex] := nil;

CalculateIndents(aListBox);
end;

procedure CalculateIndents(aListBox: TListBox);
var
i: Integer;
Indent: Integer;
begin
Indent := 0;

for i := 0 to aListBox.Items.Count - 1 do
begin
if aListBox.Items[i] = 'End' then
Dec(Indent);

if Indent > -1 then
aListBox.Items.Objects[i] := Pointer(Indent);

if aListBox.Items[i] = 'Start' then
Inc(Indent);
end;

for i := aListBox.Items.Count - 1 downto 0 do
begin
if (aListBox.Items[i] = 'End') and (Indent = -1) then
begin
DeleteItem(aListBox, i);
Break;
end;
end;
end;

end.

Unit1.pas

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ImgList, ComCtrls, Buttons;

type
TForm1 = class(TForm)
ImageList1: TImageList;
lbMain: TListBox;
btnLayout: TBitBtn;
btnCalculator: TBitBtn;
btnComment: TBitBtn;
btnTime: TBitBtn;
btnStartGroup: TBitBtn;
btnEndGroup: TBitBtn;
btnDelete: TBitBtn;
procedure FormCreate(Sender: TObject);
procedure lbMainMeasureItem(Control: TWinControl; Index: Integer;
var Height: Integer);
procedure lbMainDrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
procedure btnLayoutClick(Sender: TObject);
procedure btnCalculatorClick(Sender: TObject);
procedure btnCommentClick(Sender: TObject);
procedure btnTimeClick(Sender: TObject);
procedure btnStartGroupClick(Sender: TObject);
procedure btnEndGroupClick(Sender: TObject);
procedure btnDeleteClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

uses
Lib;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
// set the listbox style here
lbMain.Style := lbOwnerDrawVariable;
end;

procedure TForm1.lbMainDrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
var
TextPosition: Integer;
Images: TImageList;
begin
TListBox(Control).Canvas.FillRect(Rect);
Images := ImageList1;

// draw the images
if TListBox(Control).Items.Strings[Index] = 'Layout' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4 +
8 * Integer(TListBox(Control).Items.Objects[Index]),
Rect.Top, imgLayout);
end
else if TListBox(Control).Items.Strings[Index] = 'Calculator' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4 +
8 * Integer(TListBox(Control).Items.Objects[Index]),
Rect.Top, imgCalculator);
end
else if TListBox(Control).Items.Strings[Index] = 'Comment' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4 +
8 * Integer(TListBox(Control).Items.Objects[Index]),
Rect.Top, imgComment);
end
else if TListBox(Control).Items.Strings[Index] = 'Time' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4 +
8 * Integer(TListBox(Control).Items.Objects[Index]),
Rect.Top, imgTime);
end
else if TListBox(Control).Items.Strings[Index] = 'Start' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4 +
8 * Integer(TListBox(Control).Items.Objects[Index]),
Rect.Top, imgStart);
end
else if TListBox(Control).Items.Strings[Index] = 'End' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4 +
8 * Integer(TListBox(Control).Items.Objects[Index]),
Rect.Top, imgEnd);
end;

// positions the text
TextPosition := (Rect.Bottom - Rect.Top - TListBox(Control).Canvas.TextHeight
(Text)) div 2;

// displays the text
TListBox(Control).Canvas.TextOut(
Rect.Left + Images.Width + 8 + 8 * Longint(TListBox(Control).Items.Objects[Index]),
Rect.Top + TextPosition, TListBox(Control).Items.Strings[index]);
end;

procedure TForm1.lbMainMeasureItem(Control: TWinControl; Index: Integer;
var Height: Integer);
begin
Height := ImageList1.Height;
end;

procedure TForm1.btnLayoutClick(Sender: TObject);
begin
NewLayoutItem(lbMain);
end;

procedure TForm1.btnCalculatorClick(Sender: TObject);
begin
NewCalculatorItem(lbMain);
end;

procedure TForm1.btnCommentClick(Sender: TObject);
begin
NewCommentItem(lbMain);
end;

procedure TForm1.btnTimeClick(Sender: TObject);
begin
NewTimeItem(lbMain);
end;

procedure TForm1.btnStartGroupClick(Sender: TObject);
begin
NewStartItem(lbMain);
end;

procedure TForm1.btnEndGroupClick(Sender: TObject);
begin
NewEndItem(lbMain);
end;

procedure TForm1.btnDeleteClick(Sender: TObject);
begin
if lbMain.ItemIndex <> -1 then
begin
DeleteItem(lbMain, lbMain.ItemIndex);
end;
end;

end.

enter image description here

它可以做得更好,即根据 Items.Objects[] 属性分配图像索引,但这非常有效:)

最佳答案

一种方法是迭代项目并修改文本以指示缩进:

procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
Indent: Integer;
begin

...

Indent := 0;
for i := 0 to ListBox3.Items.Count - 1 do begin
if Pos('End', ListBox3.Items[i]) > 0 then
Dec(Indent);
if Indent > 0 then
ListBox3.Items[i] := StringOfChar(#32, 2 * Indent) + ListBox3.Items[i];
if Pos('Start', ListBox3.Items[i]) > 0 then
Inc(Indent);
end;
end;

由于项目的文本发生了变化,这种方法需要在绘制时相应地测试文本:

procedure TForm1.ListBox3DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
var
TextPosition: Integer;
Images: TImageList;
begin
TListBox(Control).Canvas.FillRect(Rect);
Images := ImageList1;

// draw the images
if Pos('Layout', TListBox(Control).Items.Strings[Index]) > 0 then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgLayout);
end else
if Pos('Calculator', TListBox(Control).Items.Strings[Index]) > 0 then
..

(使用这种方法,缩进图像需要做一些工作,计算项目文本中的前导空格,等等......)


如果尚未使用项目的对象,则更好的方法是将缩进存储为整数,并在绘制时使用该信息。例如。迭代时:

Indent := 0;
for i := 0 to ListBox3.Items.Count - 1 do begin
if ListBox3.Items[i] = 'Start' then
Inc(Indent);
ListBox3.Items.Objects[i] := Pointer(Indent);
if ListBox3.Items[i] = 'End' then
Dec(Indent);
end;

绘图时:

  ..
if TListBox(Control).Items.Strings[Index] = 'Layout' then
begin
Images.Draw(TListBox(Control).Canvas, Rect.Left + 4 +
8 * Integer(TListBox(Control).Items.Objects[Index]),
Rect.Top, imgLayout);

..
// displays the text
TListBox(Control).Canvas.TextOut(
Rect.Left + Images.Width + 8 + 8 * Longint(TListBox(Control).Items.Objects[Index]),
Rect.Top + TextPosition, TListBox(Control).Items.Strings[index]);
..

关于delphi - TListbox - 操纵图像和文本的布局?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8386376/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com