简体   繁体   English

在TListView中将子项目图像居中

[英]Center subitem images in a TListView

Is it possible to fix the drawing of subitem images in a TListView so that they are not cut-off on the left hand side as shown in the image? 是否可以在TListView固定subitem图像的绘制,以使它们不会像图像中所示的那样在左侧被切除?
在此处输入图片说明

Well, Pieter van Wyk , I did minimal example of how you can owner-draw your TListView component in order to center images in sub-items. 好吧, Pieter van Wyk ,我做了一个最小的示例,说明如何所有者绘制TListView组件以将图像居中于子项中。

Answer has been rewritten. 答案已被重写。 In order to decrease size of answer I had deleted unused and wrong parts. 为了减小答案的大小,我删除了未使用和错误的部分。 Previous versions may be found in history of question editing. 以前的版本可以在问题编辑的历史记录中找到。

Picture below represents work of the new code. 下图显示了新代码的工作。
One orange row is a selected row. 橙色行是选定的行。 在此处输入图片说明
Images on selected row have white color around it. 所选行上的图像周围带有白色。 It is not a bug - it is a source image with such fill. 这不是错误-它是具有此类填充的源图像。

There is the code that allows to do the same thing as on the picture: 有一些代码可以执行与图片相同的操作:

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;

To apply this code you must activate OwnerDraw property . 要应用此代码,必须激活OwnerDraw属性

See this TListView.OwnerDraw Property that leads to docs.embarcadero . 请参见导致docs.embarcadero TListView.OwnerDraw属性 I also would like to show a quote from a link above: 我还想显示来自上面链接的报价:

Set OwnerDraw to true to allow the list view to receive the OnDrawItem event instead of the default rendering of list items. 将OwnerDraw设置为true以允许列表视图接收OnDrawItem事件,而不是列表项的默认呈现。

PS PS
After column has been resized, there could be some graphical artifacts - just try to resize column in a way to hide (minimal possible size of column) and show image (any size of column that will exceeds size of associated image) and you will see what I meant. 调整列的大小后,可能会出现一些graphical artifacts -只需尝试以隐藏(最小列的可能大小)和显示图像(任何超出关联图像大小的列的大小)的方式来调整列的大小,您将看到我的意思

PSS PSS
Drawing a text of sub-items I leave to you as a homework ;) 绘制子项目的文本,我留给您作为作业;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM