Wyświetlanie ikon miniatur o wymiarach 128x128 pikseli lub większych w siatce w widoku listy

Oryginalne pytanie (Patrz aktualizacja poniżej)

Mam program WinForms, który potrzebuje przyzwoitej przewijalnej kontroli ikon z dużymi ikonami (128x128 lub większe miniatury, naprawdę), które można kliknąć, aby hilight lub dwukrotnie kliknąć, aby wykonać jakąś akcję. Najlepiej byłoby, gdyby zmarnowane miejsce było minimalne (pod każdą ikoną mogą być potrzebne krótkie podpisy pod nazwą pliku; jeśli nazwa pliku jest zbyt długa, Mogę dodać wielokropek).

Gotowa wersja listview z odpowiednimi kolorami, odstępami itp. http://www.updike.org/images/listview-great.png

Próbowałem użyć ListView z LargeIcon (domyślnie .Widok) i wyniki są rozczarowujące:

Zrzut ekranu pokazujący małe ikony w dużym widoku http://www.updike.org/images/listview-poor.png

Być może wypełniam kontrolę nieprawidłowo? Kod:

        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++;
        }

Potrzebuję dużych ikon z małą pustą przestrzenią, a nie dużej pustej przestrzeni z żenująco małymi ikonami.

  1. czy istnieje. NET kontrola, która robi to, czego potrzebuję?
    • czy istnieje ulubiona Kontrola strony trzeciej, która to robi?
    • Jeśli nie, którą kontrolę najlepiej odziedziczyć i dostosować, aby działała?
    • Czy powinienem się zepsuć i zrobić niestandardową kontrolę (z którą mam duże doświadczenie... po prostu nie chcę iść do tej skrajności, ponieważ jest to nieco zaangażowane).

Znalazłem ten tutorial o OwnerDraw ale praca z tego w zasadzie wynosi 3 lub 4 powyżej, ponieważ to demo pokazuje tylko, jak urozmaicić wiersze w widoku szczegółów.

Update

Dodawanie linii

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

Wcześniej pętla for naprawiła problem z rozmiarem, ale teraz obrazy są zmieniane na 8-bitowe (wygląda jak kolory systemowe?), mimo że debugger pokazuje, że obrazy są wstawiane do ImageList jako system 24bpp.Rysunek.Bitmapy:

Duże ikony, wreszcie http://www.updike.org/images/listview-poor2.png

  1. Jak mogę (can Ja?) aby obrazy były wyświetlane w pełnym 24-bitowym kolorze?
    • odstępy wokół ikon są nadal raczej marnotrawne... jak to naprawić? Mogę?

Update 2

Wraz z dodaniem linii

ilist.ColorDepth = ColorDepth.Depth24Bit;

Następny po ustawieniu ilist.ImageSize, posłuchałem Rady arbitra i zmieniłem odstępy:

[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);

Kontrola ListView może nie być idealna lub ma domyślne wartości, których bym oczekiwał (jak właściwość spacji), ale cieszę się, że mogłem ją oswoić, w end:

Alt text http://www.updike.org/images/listview-great.png

Przy okazji, aby zachować odpowiedni współczynnik proporcji dla miniatur, musiałem zrobić własne bitmapy 128x128, wyczyścić tło, aby pasowało do kontrolki i wyśrodkować te obrazy:

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();
}
Author: Jared Updike, 2009-07-09

5 answers

Dla aktualizacji:

  1. Ustawia głębię kolorów listy obrazów oprócz rozmiaru obrazu (ilist.ColorDepth = ColorDepth.Depth24Bit)
  2. WinForms ListView nie ma możliwości zmiany odstępów ikon, jednak można to łatwo zrobić za pomocą Win32. Musisz wysłać LVM_SETICONSPACING do ListView (istnieje wiele samouczków jak używać funkcji SendMessage win32 w. Net, więc myślę, że ten kierunek musi Ci wystarczyć).
 13
Author: arbiter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-09 08:40:58

Możesz użyć FlowLayoutPanel i wrzucić do niego pictureboxy. Ustaw picturebox na rozmiar 128x128, a sizemode na "zoom" (to zajmie się zmianą rozmiaru obrazu bez utraty proporcji). Możesz nawet programowo dodawać pictureboxy.

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

Ponieważ musisz mieć etykietę pod picturebox, możesz utworzyć Usercontrol, tak jak Pastor powiedział, że wszystko, co ma to picturebox i etykieta pod nim. Wtedy będzie to instancja kontrolna, którą dodałbyś do swojego flowlayoutpanel.

 5
Author: jvanderh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-09 00:19:18

ObjectListView (open source wrapper wokół. NET ListView) ułatwia niestandardowe rysowanie widoku kafelka. Zobacz Widok złożony w wersji demonstracyjnej, przełącz się na widok kafelkowy, gdy jest włączone rysowanie niestandardowe: owner drawed tile view http://objectlistview.sourceforge.net/cs/_images/tileview-ownerdrawn.png

Gdybyś chciał tylko obraz 128x128 plus jakieś szczegóły tekstu, nie musiałbyś nawet rysować go. Możesz dać mu dużą listę obrazów, a następnie zaznaczyć, które fragmenty informacje tekstowe, które chcesz pokazać na kafelku, używając IsTileViewColumn.

 5
Author: Grammarian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-13 09:07:40

Zastrzeżenie: pracuję dla Atalasoft

W naszym. NET Imaging SDK znajduje się kontrolka miniatur obrazu, DotImage
 2
Author: Lou Franco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-09 00:23:50

Wykonanie niestandardowej kontroli nie byłoby takie złe. Chciałbym dziedziczyć z panelu lub kontrolera użytkownika, ponieważ wierzę, że oba automatycznie dodają paski przewijania dla treści.

Dynamiczne dodawanie kontenerów (takich jak PictureBoxes) i podpisów dla każdego obrazu, Obsługa zdarzenia mousedown lub mousclick dla kontenera i być może rysowanie wokół niego czerwonego kwadratu, aby pokazać, że został wybrany. "Najtrudniejszą" częścią byłoby ponowne próbkowanie obrazu do 128x128, jeśli nie są jeszcze tego rozmiaru, a nawet to może łatwo być z GDI+.

 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-09 00:03:16