在ListView的网格中显示128×128像素或更大的缩略图图标

原始问题(请参阅下面的更新)

我有一个WinForms程序,需要一个体面的可滚动图标控制与大图标(真正的128×128或更大的缩略图),可以点击高亮或双击执行某些操作。 最好是浪费最less的空间(每个图标下可能需要短文件名字幕;如果文件名太长,我可以添加省略号)。

完成版本的listview与适当的颜色,间距等http://www.updike.orghttp://img.dovov.comlistview-great.png

我尝试使用LargeIcon的ListView(默认.View),结果令人失望:

在LargeIcon视图中显示小图标的截图http://www.updike.orghttp://img.dovov.comlistview-poor.png

也许我是不正确地填充控件? 码:

ImageList ilist = new ImageList(); this.listView.LargeImageList = ilist; int i = 0; foreach (GradorCacheFile gcf in gc.files) { Bitmap b = gcf.image128; ilist.Images.Add(b); ListViewItem lvi = new ListViewItem("text"); lvi.ImageIndex = i; this.listView.Items.Add(lvi); i++; } 

我需要一些空的空间很大的图标,而不是大的空白空间以及尴尬的小图标。

  1. 有没有一个.NET控件,做我所需要的?
    • 有没有一个最喜欢的第三方控制这样做?
    • 如果不是,哪个控制最好inheritance和调整,使其工作?
    • 我应该分解,并制定一个自定义的控制(我有很多的经验…只是不想去那个极端,因为这是有点牵扯)。

我发现这个关于OwnerDraw的教程,但是从那里开始的工作基本上等于上面的数字3或者4,因为这个演示只是展示了如何在细节视图中增加行数。

更新

添加线

 ilist.ImageSize = new Size(128, 128); 

之前的for循环固定的大小问题,但现在的图像调色到8位(看起来像系统颜色?)即使debugging器显示图像插入ImageList作为24bpp System.Drawing.Bitmap的:

大图标,终于http://www.updike.orghttp://img.dovov.comlistview-poor2.png

  1. 我如何(可以吗?)使图像显示全部24位颜色?
    • 图标周围的空间还是比较浪费的……我该如何解决这个问题? 我可以吗?

更新2

随着添加线

 ilist.ColorDepth = ColorDepth.Depth24Bit; 

下一步设置ilist.ImageSize后,我遵循仲裁者的build议,并改变了间距:

 [DllImport("user32.dll")] public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); public int MakeLong(short lowPart, short highPart) { return (int)(((ushort)lowPart) | (uint)(highPart << 16)); } public void ListView_SetSpacing(ListView listview, short cx, short cy) { const int LVM_FIRST = 0x1000; const int LVM_SETICONSPACING = LVM_FIRST + 53; // http://msdn.microsoft.com/en-us/library/bb761176(VS.85).aspx // minimum spacing = 4 SendMessage(listview.Handle, LVM_SETICONSPACING, IntPtr.Zero, (IntPtr)MakeLong(cx, cy)); // http://msdn.microsoft.com/en-us/library/bb775085(VS.85).aspx // DOESN'T WORK! // can't find ListView_SetIconSpacing in dll comctl32.dll //ListView_SetIconSpacing(listView.Handle, 5, 5); } /////////////////////////////////////////////////////////// ListView_SetSpacing(this.listView, 128 + 12, 128 + 4 + 20); 

ListView控件可能不是完美的或者有我期望的默认值(比如一个Spacing属性),但是我很高兴我可以驯服它,最后:

替代文字http://www.updike.orghttp://img.dovov.comlistview-great.png

顺便说一句,要保持缩略图的正确高宽比,我必须制作自己的128×128位图,清除背景以匹配控件,并将这些图像居中:

 public void CenterDrawImage(Bitmap target, Color background, Bitmap centerme) { Graphics g = Graphics.FromImage(target); g.Clear(background); int x = (target.Width - centerme.Width) / 2; int y = (target.Height - centerme.Height) / 2; g.DrawImage(centerme, x, y); g.Dispose(); } 

更新:

  1. 设置图像列表的颜色深度除了图像大小(ilist.ColorDepth = ColorDepth.Depth24Bit)
  2. WinForms ListView没有改变图标间距的可能性,但可以使用Win32轻松完成。 您需要将LVM_SETICONSPACING发送到您的ListView(在.net中有很多教程如何使用SendMessage win32函数,所以我认为这个方向对您来说已经足够了)。

你可以使用FlowLayoutPanel并在其中放置图片框。 将图片框的大小设置为128×128,并将大小模式设置为“缩放”(这样可以在不损失高宽比的情况下resize)。 你甚至可以编程添加图片框。

 PictureBox pb = New Picturebox; pb.image = gcf.image128; FlowLayoutPanel1.Controls.Add(pb) 

因为你需要在picturebox下面有一个标签,所以你可以像Pastor一样创build一个UserControl,它所拥有的只是一个picturebox和一个标签。 那么这将是您将添加到您的flowlayoutpanel的控件实例。

ObjectListView (一个.NET ListView的开源包装器)可以很容易地自定义绘制Tile视图。 看看演示上的复杂视图,在启用自定义绘制时切换到平铺视图: 所有者绘制的平铺视图cs/_images/tileview-ownerdrawn.png

如果你只想要一个128×128图像加上一些文字细节,你甚至不需要所有者绘制它。 你可以给它一个大的图像列表,然后使用IsTileViewColumn标记你想在Tile上显示哪些文本信息。

免责声明:我为Atalasoft工作

在DotImage的 .NET Imaging SDK中有一个图像缩略图控件

进行自定义控制不会太糟糕。 我会inheritance面板或用户控件,因为我相信都会自动添加滚动条的内容。

为每个图像dynamic添加容器(如PictureBoxes)和标题,处理容器的mousedown或mouseclick事件,并可能围绕它绘制红色方框以显示它已被选中。 “最难”的部分是将图像重新采样到128×128,如果它们还不是那么大的话,甚至可以很容易地用GDI +。