Delphi 在TListView中居中显示子项图像
是否可以将Delphi 在TListView中居中显示子项图像,delphi,tlistview,subitem,Delphi,Tlistview,Subitem,是否可以将子项图像的绘图固定在t视图中,以便它们不会如图所示在左侧被切断? 好吧,彼得·范·怀克,我举了一个简单的例子,说明了如何让所有者绘制TListView组件,以便在子项中居中显示图像 答案已重写。为了减少答案的大小,我删除了未使用和错误的部分。以前的版本可以在问题编辑历史记录中找到。 下面的图片代表了新代码的工作。 一个橙色行是选定的行。 选定行上的图像周围为白色。这不是一个bug-它是一个带有这种填充的源图像 有一个代码允许执行与图片上相同的操作: procedure TForm1.
子项
图像的绘图固定在t视图
中,以便它们不会如图所示在左侧被切断?好吧,彼得·范·怀克,我举了一个简单的例子,说明了如何让所有者绘制
TListView
组件,以便在子项中居中显示图像
答案已重写。为了减少答案的大小,我删除了未使用和错误的部分。以前的版本可以在问题编辑历史记录中找到。
下面的图片代表了新代码的工作。一个橙色行是选定的行。
选定行上的图像周围为白色。这不是一个bug-它是一个带有这种填充的源图像 有一个代码允许执行与图片上相同的操作:
procedure TForm1.ListView1DrawItem(Sender: TCustomListView; Item: TListItem; Rect: TRect;
State: TOwnerDrawState);
var
Bmp: TBitmap;
Image: TBitmap;
R: TRect;
CenterH: Integer;
CenterV: Integer;
ImageIndex: Integer;
ItemWidth: Integer;
i: Integer;
begin
// Set initial legth of point at the end of which image will be drawn.
// Column 0 is a "fixed" column
ItemWidth := Sender.Column[0].Width;
R := Rect;
Bmp := TBitmap.Create;
try
Image := TBitmap.Create;
try
Bmp.SetSize(R.Width, R.Height);
// Make fill for item
if Item.Selected then
Bmp.Canvas.Brush.Color := clWebOrange
else
Bmp.Canvas.Brush.Color := clMoneyGreen;
Bmp.Canvas.FillRect(Bmp.Canvas.ClipRect);
// Output image associated with 'fixed' column
TListView(Sender).SmallImages.GetBitmap(Item.ImageIndex, Image);
CenterH := (Sender.Column[0].Width - Image.Width) div 2;
CenterV := (R.Height - Image.Height) div 2;
Bmp.Canvas.Draw(CenterH, CenterV, Image);
// Output text
Bmp.Canvas.TextOut(CenterH + Image.Width + 6, 6, Item.Caption);
// Draw sub-items
for i:=0 to Item.SubItems.Count - 1 do
begin
// Obtain index of image
ImageIndex := Item.SubItemImages[i];
// Get associated image
TListView(Sender).SmallImages.GetBitmap(ImageIndex, Image);
// Center image
CenterH := (Sender.Column[i+1].Width - Image.Width) div 2;
CenterV := (R.Height - Image.Height) div 2;
// Output image
Bmp.Canvas.Draw(ItemWidth + CenterH, CenterV, Image);
// Increase point where image started to be drawn
Inc(ItemWidth, Sender.Column[i+1].Width);
end;
// Draw ready item's image onto sender's canvas
Sender.Canvas.Draw(R.Left, R.Top, Bmp);
finally
Image.Free;
end;
finally
Bmp.Free;
end;
end;
要应用此代码,必须激活OwnerDraw
属性
请参阅这篇文章,它将导致docs.embarcadero
。我还想展示上面一个链接的引用:
将OwnerDraw设置为true,以允许列表视图接收OnDrawItem事件,而不是列表项的默认呈现
p.S.在调整列的大小后,可能会出现一些
图形瑕疵
——只要尝试以隐藏(列的最小可能大小)和显示图像的方式调整列的大小(列的任何大小将超过关联图像的大小),您就会明白我的意思
p.S.S.画一个我留给你作为家庭作业的子项目的文本;) 也许,只有
OwnerDraw
属性允许您自己将图标居中。请添加MCVE以复制此图标,好吗?就个人而言,我认为没有定制图纸是不可能的,但我想你的评论是写给我的,所以我必须解释一下我的评论的意义。当我建议使用OwnerDraw
属性时,我打算将其与OwnerDraw事件一起使用。在我看来,“使用OwnerDraw财产”这句话正是我前面描述的意思。我相信彼得·范怀克有足够的经验来理解这一点;)@迪玛,对不起,不,不,不是对你,我会用那个@thing:)它是对OP的,因为他们会收到关于“问题线程”中任何通信的通知,即使没有那个@thing。好的,但回到主题上来,就个人而言,我不认为有办法在这个控制子项中水平(或者甚至垂直)居中图像,正如你所指出的(对不起,没有投票支持你的评论,但我认为这也是答案)。@Dima,不用担心:)无论如何,答案很好!(投票通过后,将进行回顾:)谢谢您的全面回答!我已经试过了,它可以很好地用于带有图标的列。我现在对包含文本的列有一些问题,无法以不同的字体显示它们。而且,当鼠标移动到包含文本的列上时,这些列看起来会变成黑色。