Affichage des vignettes de 128x128 pixels ou plus dans une grille dans ListView

question originale (voir Mise à jour ci-dessous)

j'ai un programme WinForms qui a besoin d'un contrôle d'icône scrollable décent avec de grandes icônes (128x128 ou plus grandes vignettes, vraiment) qui peut être cliqué à hilight ou double cliqué pour effectuer une certaine action. De préférence, il y aurait un minimum d'espace perdu (de courtes légendes du nom de fichier pourraient être nécessaires sous chaque icône; si le nom de fichier est trop long, je peux ajouter une ellipse).

version finale de listview avec les couleurs appropriées, l'espacement, etc. http://www.updike.org/images/listview-great.png

j'ai essayé D'utiliser une ListView avec LargeIcon (par défaut .Vue) et les résultats sont décevants:

capture d'écran montrant de minuscules icônes en vue LargeIcon http://www.updike.org/images/listview-poor.png

peut-être que je gonfle mal la commande? Code:

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

j'ai besoin de grandes icônes avec peu d'espace vide, pas le grand espace vide avec embarrassante de petites icônes.

  1. y a-t-il un contrôle. net qui fait ce dont j'ai besoin?
    • Est-il un favori des tiers qui fait cela?
    • dans la négative, quel contrôle serait le mieux à hériter et à modifier pour que cela fonctionne?
    • devrais-je me décomposer et faire un contrôle personnalisé (avec lequel j'ai beaucoup d'expérience... Je ne veux juste pas aller à cet extrême puisque c'est quelque peu impliqué).

j'ai trouvé ce tutoriel sur OwnerDraw mais travailler à partir de cela revient essentiellement au nombre 3 ou 4 ci-dessus puisque cette démo montre juste comment pimenter les lignes dans la vue des détails.

mise à Jour

ajouter la ligne

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

avant que la boucle for ne règle le problème de taille, mais maintenant les images sont palettisées en 8 bits (ressemble à des couleurs système?) même si le débogueur montre que les images sont insérées dans L'ImageList en 24bpp Système.Dessin.Bitmap:

de grandes icônes, enfin http://www.updike.org/images/listview-poor2.png

  1. Comment puis-je (puis-je?) faire apparaître les images en pleine couleur 24 bits?
    • l'espacement autour des icônes est encore assez inutile... comment puis-je régler ce problème? Puis-Je?

mise à Jour 2

en ajoutant la ligne

ilist.ColorDepth = ColorDepth.Depth24Bit;

suivant après le réglage de ilist.- Image, j'ai suivi conseil d'arbitre et modification de l'espacement:

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

La liste de contrôle peut ne pas être parfait ou ont les valeurs par défaut je m'attends (comme un Espacement de propriété), mais je suis content d'avoir pu l'apprivoiser, à la fin:

texte alternatif http://www.updike.org/images/listview-great.png

au fait, pour maintenir le bon rapport d'aspect pour les vignettes, j'ai dû faire mes propres bitmaps 128x128, effacer l'arrière-plan pour correspondre au contrôle, et centrer ceux images:

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();
}
44
demandé sur Jared Updike 2009-07-09 03:47:27

5 réponses

pour mise à jour:

  1. définir la profondeur de couleur de la liste des images en plus de la taille de l'image (ilist.ColorDepth = ColorDepth.Depth24Bit)
  2. WinForms ListView n'a pas la possibilité de changer l'espacement des icônes, cependant il peut être facilement fait en utilisant Win32. Vous devez envoyer LVM_SETICONSPACING à votre ListView (il y a beaucoup de tutoriels sur la façon d'utiliser la fonction win32 de SendMessage dans .net, donc je pense que cette direction doit être suffisante pour vous).
13
répondu arbiter 2009-07-09 08:40:58

Vous pouvez utiliser le FlowLayoutPanel et y déposer des boîtes de photos. Réglez la picturebox à une taille de 128x128 et le sizemode à 'zoom' (cela prend soin de redimensionner votre image sans perte de rapport d'aspect). Vous pouvez même programmer l'ajout des pictureboxes.

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

depuis que vous avez besoin d'avoir un label sous la picturebox, vous pouvez créer un Usercontrol comme Pastor a dit que tout ce qu'il a est une picturebox et un label sous elle. Alors que serait l'instance de contrôle vous ajoutez à votre flowlayoutpanel.

5
répondu jvanderh 2009-07-09 00:19:18

ObjectListView (un wrapper open source autour d'une ListView.Net) permet de dessiner facilement une vue de tuile sur mesure. Jetez un coup d'oeil à la vue complexe de la démo, passez à la vue des carreaux lorsque le tirage personnalisé est activé: vue de la tuile tirée par le propriétaire http://objectlistview.sourceforge.net/cs/_images/tileview-ownerdrawn.png

si vous vouliez seulement une image 128x128 plus quelques détails de texte, vous n'auriez même pas besoin de le faire dessiner par le propriétaire. Vous pourriez lui donner une grande liste d'images, et puis marquez quels bits d'information textuelle vous vouliez afficher sur la tuile, en utilisant IsTileViewColumn.

5
répondu Grammarian 2009-07-13 09:07:40

avertissement: je travaille pour Atalasoft

il y a un contrôle de vignette d'image dans notre SDK. net Imaging, DotImage

2
répondu Lou Franco 2009-07-09 00:23:50

faire un contrôle personnalisé ne serait pas trop mal. J'hériterais du panneau ou D'un Usercontrol car je crois que les deux ajoutent automatiquement des barres de défilement pour le contenu.

ajouter dynamiquement des conteneurs (comme des boîtes de Photos) et des légendes pour chaque image, manipuler l'événement mousedown ou mouseclick pour le conteneur et peut-être dessiner un carré rouge autour de lui pour montrer qu'il est sélectionné. La partie "le plus dur" serait de rééchantillonner l'image à 128x128 si elles ne sont pas déjà de cette taille et même cela peut facilement être avec GDI+.

1
répondu 2009-07-09 00:03:16