Подтвердить что ты не робот

Отображение значков миниатюр 128x128 пикселей или больше в сетке в ListView

Оригинальный вопрос (см. Обновление ниже)

У меня есть программа WinForms, которая нуждается в приличном прокручиваемом элементе управления значками с большими значками (на самом деле, размером с пиктограмму 128x128 или более), которые можно щелкнуть до полусвета или дважды щелкнуть, чтобы выполнить какое-либо действие. Предпочтительно, чтобы было минимальное потраченное впустую пространство (под каждым значком могли бы потребоваться короткие заголовки файлов; если имя файла слишком длинное, я могу добавить многоточие).

finished version of listview with proper colors, spacing, etc.
(источник: updike.org)

Я попытался использовать ListView с LargeIcon (по умолчанию .View), и результаты разочаровывают:

screenshot showing tiny icons in 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++;
        }

Мне нужны большие значки с небольшим пустым пространством, а не большое пустое пространство с смущающе маленькими значками.

  1. Есть ли элемент управления .NET, который делает то, что мне нужно?
    • Есть ли любимый сторонний контроль, который это делает?
    • Если нет, какой контроль лучше всего унаследовать и настроить, чтобы он работал?
    • Должен ли я сломаться и создать собственный элемент управления (с которым у меня есть большой опыт... просто не хочу идти к такому крайнему состоянию, поскольку это несколько связано).

Я нашел этот учебник о OwnerDraw, но работа с ним в основном составляет номер 3 или 4 выше, так как эта демонстрация просто показывает, как оживить строки в подробном представлении.

Обновить

Добавление строки

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

до того, как цикл for исправил проблему с размером, но теперь изображения палитрированы до 8-битных (выглядит как системные цвета?), хотя отладчик показывает, что изображения вставляются в ImageList как 24bpp System.Drawing.Bitmap's:

large icons, finally
(источник: updike.org)

  1. Как я могу (могу ли я?) Заставить изображения отображаться в полном 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), но я рад, что смог в конце его укротить:

alt text
(источник: 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();
}
4b9b3361

Ответ 1

Для обновления:

  • Задайте глубину цвета списка изображений в дополнение к размеру изображения (ilist.ColorDepth = ColorDepth.Depth24Bit)
  • WinForms ListView не имеет возможности изменять расстояние между значками, однако его можно легко сделать с помощью Win32. Вам нужно отправить LVM_SETICONSPACING в свой ListView (есть много руководств по использованию функции SendMessage win32 в .net, поэтому я думаю, что это направление должно вам будет достаточно).

Ответ 2

Вы можете использовать FlowLayoutPanel и обрезать в нем графические ящики. Установите размер изображения размером 128x128, а sizemode - на "zoom" (это позволит изменить размер изображения без потери соотношения сторон). Вы даже можете программно добавить изображения.

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

Поскольку вам нужно иметь ярлык под изображением, вы можете создать Usercontrol, как пастор сказал, что все, что у него есть, это подкатегория и ярлык. Тогда это будет контрольный экземпляр, который вы добавили бы в свою панель flowlayout.

Ответ 3

ObjectListView (оболочка с открытым исходным кодом вокруг .NET ListView) позволяет легко настраивать представление Tile. Посмотрите на представление "Комплекс" на демоверсии, переключитесь на представление "Плитка", когда пользовательский розыгрыш включен: владелец обращается с изображением плитки http://objectlistview.sourceforge.net/cs/_images/tileview-ownerdrawn.png

Если вам нужно только изображение 128x128 плюс некоторые текстовые данные, вам даже не нужно будет его рисовать. Вы могли бы дать ему большой мюслик, а затем пометить, какие фрагменты текстовой информации вы хотите показать на Плитке, используя IsTileViewColumn.

Ответ 4

Отказ от ответственности: я работаю для Atalasoft

В нашем .NET Imaging SDK есть элемент управления эскизами изображений, DotImage

Ответ 5

Создание настраиваемого элемента управления будет не слишком плохим. Я бы наследовал от Panel или Usercontrol, так как считаю, что автоматически добавляет полосы прокрутки для контента.

Динамическое добавление контейнеров (например, PictureBoxes) и титров для каждого изображения, обработка события mousedown или mouseclick для контейнера и, возможно, рисование красного квадрата вокруг него, чтобы показать, что он выбран. "Самая сложная" часть будет передискретизировать изображение до 128x128, если они еще не того размера, и даже это может быть легко с GDI +.