原始问题(请参阅下面的更新)
我有一个 WinForms 程序,它需要一个体面的可滚动图标控件,带有大图标(实际上是 128x128 或更大的缩略图),可以单击以突出显示或双击以执行某些操作。最好是尽量减少浪费的空间(每个图标下方可能需要短文件名标题;如果文件名太长,我可以添加省略号)。
(来源:updike.org)
我尝试使用带有 LargeIcon 的 ListView(默认 .View),结果令人失望:
(来源:updike.org)
也许我错误地填充了控件?代码:
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++;
}
我需要带有小空白空间的大图标,而不是带有令人尴尬的小图标的大空白空间。
- 是否有一个 .NET 控件可以满足我的需要?
- 有没有最喜欢的第三方控件可以做到这一点?
- 如果不是,哪个控件最好继承和调整以使其工作?
- 我是否应该分解并制作一个自定义控件(我有丰富的经验......只是不想走极端,因为这有点涉及)。
我找到了关于 OwnerDraw 的本教程,但从那基本上相当于上面的 3 或 4 号,因为该演示只是展示了如何在详细信息视图中为行添加趣味。
更新
添加行
ilist.ImageSize = new Size(128, 128);
在 for 循环修复大小问题之前,但现在图像被调色板化为 8 位(看起来像系统颜色?),即使调试器显示图像作为 24bpp System.Drawing.Bitmap 插入到 ImageList 中:
(来源:updike.org)
- 我如何(我可以?)使图像以全 24 位颜色显示?
- 图标周围的间距仍然相当浪费......我该如何解决?我可以吗?
更新 2
随着添加线
ilist.ColorDepth = ColorDepth.Depth24Bit;
接下来在设置 ilist.ImageSize 之后,我按照仲裁者的建议更改了间距:
[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 属性),但我很高兴我能驯服它,最后:
(来源:updike.org)
顺便说一句,为了保持缩略图的正确纵横比,我必须制作自己的 128x128 位图,清除背景以匹配控件,并将这些图像居中:
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();
}