Оригинальный вопрос (см. Обновление ниже)
У меня есть программа WinForms, которая нуждается в приличном прокручиваемом элементе управления значками с большими значками (на самом деле, размером с пиктограмму 128x128 или более), которые можно щелкнуть до полусвета или дважды щелкнуть, чтобы выполнить какое-либо действие. Предпочтительно, чтобы было минимальное потраченное впустую пространство (под каждым значком могли бы потребоваться короткие заголовки файлов; если имя файла слишком длинное, я могу добавить многоточие).
(источник: updike.org)
Я попытался использовать ListView с LargeIcon (по умолчанию .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-битных (выглядит как системные цвета?), хотя отладчик показывает, что изображения вставляются в ImageList как 24bpp System.Drawing.Bitmap's:
(источник: 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();
}