C # modifier la hauteur de L'élément ListView/de la rangée
je veux changer la hauteur de L'élément/de la rangée dans listview.
j'ai cherché partout et j'ai pensé que, pour changer la hauteur j'ai besoin d'utiliser LBS_OWNERDRAWFIXED
ou MeasureItem
ou quelque chose comme ça.
Le problème est que je ne sais pas exactement quoi faire et comment l'utiliser..
Quelqu'un peut m'aider avec ça?
Edit:
Je ne peux pas utiliser le hack ImageList parce que j'utilise le SmallImageList pour de vrai et j'ai besoin de différents hauteur de la ligne à partir de la taille des images de la liste D'images.
Merci!
6 réponses
C'est peut-être fait en utilisant le SmallImageList
affaire-vous avez juste à être prudent. ObjectListView -- un wrapper open source autour D'un standard .NET ListView
-- utilise cette astuce pour implémenter avec succès un RowHeight
propriété.
si vous voulez 32 pixels pour chaque ligne, attribuez un ImageList
qui est de 16x32 (Largeur x hauteur), puis positionnez chacune de vos images au milieu vertical de la hauteur de 32 pixels.
cette image d'écran montre des lignes de 32 pixels et le mot emballage qui est possible en raison de l'espace supplémentaire:
ObjectListView
fait tout ce travail pour vous. En fait, si vous essayez de faire quelque chose avec une ListView, vous devriez sérieusement regarder en utilisant un ObjectListView
à la place. Il rend beaucoup de choses difficiles (par exemple, le tri par type de colonne, des infobulles personnalisées) triviales, et plusieurs choses impossibles (par exemple, des superpositions, des groupes sur des listes virtuelles) possibles.
Pour les personnes qui ont encore de la difficulté avec cela, voici le code que j'utilise:
private void SetHeight(ListView listView, int height)
{
ImageList imgList = new ImageList();
imgList.ImageSize = new Size(1, height);
listView.SmallImageList = imgList;
}
Pour utiliser cela, il suffit de faire:
SetHeight(lvConnections, 25);
Vous devez utiliser un peu un hack. Le truc est d'utiliser une liste d'images dans la propriété StateImageList. Le ListView ajustera la hauteur de l'élément en fonction de la hauteur de la propriété ImageSize de L'ImageList. Vous n'avez pas besoin de spécifier une image pour vos articles, mais utiliser la StateImageList forcera le ListView à s'ajuster. Dans l'exemple ci-dessous, j'ai paramétré la taille de la liste d'images à 32x32, résultant ainsi en un ListViewItem(s) de hauteur 32px.
la hauteur de ligne par défaut D'un ListView (en mode report view) est calculée en fonction de la taille de police de la commande.
donc pour sélectionner la hauteur de la ligne, Choisissez une police avec la bonne hauteur dans les propriétés de ListView. Par exemple, sélectionnez MS Sans Serif 18.
alors vous pouvez changer la police utilisée par tous les éléments: lorsque vous insérez un nouvel élément, définissez sa propriété de police.
pour optimiser l'assignation de police, vous devez déclarer la police item comme un membre privé de la forme:
Private Font stdfont = new Font( "Consolas", 9.0f, FontStyle.Regular );
puis en ajoutant des éléments:
ListViewItem i = new ListViewItem( "some text" );
i.Font = stdfont;
MyListView.Items.Add( i );
cette astuce est la seule facile permettant d'avoir une plus petite hauteur de ligne ;) I. E. réglez la taille de police de control à 7 et la taille de police de items à 10. (Testé avec VS 2008 )
malheureusement personne n'a répondu à votre question initiale comment utiliser LBS_OWNERDRAWFIXED
pendant toutes ces années.
la réponse que vous avez acceptée est l'intégration d'un énorme projet (avec des démos et de la documentation 3,3 MB). Mais juste pour définir la hauteur de ligne d'un ListView, ceci est surchargé.
l'autre solution suggérée ici (ajout d'une liste Imagel) ne fonctionne qu'à augmentation la hauteur de ligne. Mais il ne permet pas vraiment RowHeight indépendant de l'image hauteur. En outre, la hauteur de ligne par défaut dépend du système d'exploitation. Par exemple, sur Windows 7, les lignes sont beaucoup plus hautes que sur XP. Vous ne pouvez pas les rendre plus serrés, mais plus élevés.
Mais avec très peu de lignes, vous pouvez faire ce que vous voulez. Il suffit de copier-coller la classe suivante:
using System;
using System.Drawing;
using System.Diagnostics;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace ExtendedControls
{
public class ListViewEx : ListView
{
#region Windows API
/*
struct MEASUREITEMSTRUCT
{
public int CtlType; // Offset = 0
public int CtlID; // Offset = 1
public int itemID; // Offset = 2
public int itemWidth; // Offset = 3
public int itemHeight; // Offset = 4
public IntPtr itemData;
}
*/
[StructLayout(LayoutKind.Sequential)]
struct DRAWITEMSTRUCT
{
public int ctlType;
public int ctlID;
public int itemID;
public int itemAction;
public int itemState;
public IntPtr hWndItem;
public IntPtr hDC;
public int rcLeft;
public int rcTop;
public int rcRight;
public int rcBottom;
public IntPtr itemData;
}
// LVS_OWNERDRAWFIXED: The owner window can paint ListView items in report view.
// The ListView control sends a WM_DRAWITEM message to paint each item. It does not send separate messages for each subitem.
const int LVS_OWNERDRAWFIXED = 0x0400;
const int WM_SHOWWINDOW = 0x0018;
const int WM_DRAWITEM = 0x002B;
const int WM_MEASUREITEM = 0x002C;
const int WM_REFLECT = 0x2000;
#endregion
bool mb_Measured = false;
int ms32_RowHeight = 14;
/// <summary>
/// Constructor
/// </summary>
public ListViewEx()
{
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
}
/// <summary>
/// Sets the row height in Details view
/// This property appears in the Visual Studio Form Designer
/// </summary>
[Category("Appearance")]
[Description("Sets the height of the ListView rows in Details view in pixels.")]
public int RowHeight
{
get { return ms32_RowHeight; }
set
{
if (!DesignMode) Debug.Assert(mb_Measured == false, "RowHeight must be set before ListViewEx is created.");
ms32_RowHeight = value;
}
}
protected override CreateParams CreateParams
{
get
{
CreateParams k_Params = base.CreateParams;
k_Params.Style |= LVS_OWNERDRAWFIXED;
return k_Params;
}
}
/// <summary>
/// The messages WM_MEASUREITEM and WM_DRAWITEM are sent to the parent control rather than to the ListView itself.
/// They come here as WM_REFLECT + WM_MEASUREITEM and WM_REFLECT + WM_DRAWITEM
/// They are sent from Control.WmOwnerDraw() --> Control.ReflectMessageInternal()
/// </summary>
protected override void WndProc(ref Message k_Msg)
{
base.WndProc(ref k_Msg); // FIRST
switch (k_Msg.Msg)
{
case WM_SHOWWINDOW: // called when the ListView becomes visible
{
Debug.Assert(View == View.Details, "ListViewEx supports only Details view");
Debug.Assert(OwnerDraw == false, "In ListViewEx do not set OwnerDraw = true");
break;
}
case WM_REFLECT + WM_MEASUREITEM: // called once when the ListView is created, but only in Details view
{
mb_Measured = true;
// Overwrite itemHeight, which is the fifth integer in MEASUREITEMSTRUCT
Marshal.WriteInt32(k_Msg.LParam + 4 * sizeof(int), ms32_RowHeight);
k_Msg.Result = (IntPtr)1;
break;
}
case WM_REFLECT + WM_DRAWITEM: // called for each ListViewItem to be drawn
{
DRAWITEMSTRUCT k_Draw = (DRAWITEMSTRUCT) k_Msg.GetLParam(typeof(DRAWITEMSTRUCT));
using (Graphics i_Graph = Graphics.FromHdc(k_Draw.hDC))
{
ListViewItem i_Item = Items[k_Draw.itemID];
Color c_BackColor = i_Item.BackColor;
if (i_Item.Selected) c_BackColor = SystemColors.Highlight;
if (!Enabled) c_BackColor = SystemColors.Control;
using (SolidBrush i_BackBrush = new SolidBrush(c_BackColor))
{
// Erase the background of the entire row
i_Graph.FillRectangle(i_BackBrush, i_Item.Bounds);
}
for (int S=0; S<i_Item.SubItems.Count; S++)
{
ListViewItem.ListViewSubItem i_SubItem = i_Item.SubItems[S];
// i_Item.SubItems[0].Bounds contains the entire row, rather than the first column only.
Rectangle k_Bounds = (S>0) ? i_SubItem.Bounds : i_Item.GetBounds(ItemBoundsPortion.Label);
// You can use i_Item.ForeColor instead of i_SubItem.ForeColor to get the same behaviour as without OwnerDraw
Color c_ForeColor = i_SubItem.ForeColor;
if (i_Item.Selected) c_ForeColor = SystemColors.HighlightText;
if (!Enabled) c_ForeColor = SystemColors.ControlText;
TextFormatFlags e_Flags = TextFormatFlags.NoPrefix | TextFormatFlags.EndEllipsis | TextFormatFlags.VerticalCenter | TextFormatFlags.SingleLine;
switch (Columns[S].TextAlign)
{
case HorizontalAlignment.Center: e_Flags |= TextFormatFlags.HorizontalCenter; break;
case HorizontalAlignment.Right: e_Flags |= TextFormatFlags.Right; break;
}
TextRenderer.DrawText(i_Graph, i_SubItem.Text, i_SubItem.Font, k_Bounds, c_ForeColor, e_Flags);
}
}
break;
}
}
}
} // class
} // namespace
après avoir ajouté un ListViewEx à votre formulaire, vous verrez une nouvelle propriété dans le Visual Studio Forms Designer qui permet de définir la hauteur de la rangée dans pixels:
la valeur que vous entrez là sera la hauteur de la ligne en pixels et elle sera respectée exattement sur tous les systèmes d'exploitation. Je l'ai testé sur Windows XP, 7 et 10:
de plus, ma classe A deux autres avantages par rapport à la ListView originale: elle dessine scintillement et il respecte l' ForeColor et Police définir ListViewSubItem
qui est ignorée par le ListView original de Microsoft. Vous pouvez donc dessiner chaque cellule avec une couleur et une police différentes.
IMPORTANT: comme dit le MSDN LBS_OWNERDRAWFIXED
a été conçue pour plus de détails, voir (Report view). Mon code fonctionne uniquement pour ce mode et c'est parce que Microsoft a conçu comme ça.
Veuillez noter que le paramètreListView.OwnerDraw = true
est une chose complètement différente que d'utiliser LVS_OWNERDRAWFIXED
.
Je l'ai fait ne pas mettre en œuvre le dessin icônes, parce que je n'en ai pas besoin. Mais vous pouvez facilement ajouter ce.
Plasmabubble a la bonne idée. Ceci développe sur cela et est ce que j'utilise pour utiliser une ligne-largeur étroite pour les articles.
L'espacage de ligne dans une ListView dépend de la police de la ListView et ne peut pas être modifié. Cependant, vous pouvez définir la police des éléments dans ListView à quelque chose de plus grand que la police de ListView.
Si vous voulez qu'il soit proportionnel, créer une police basée sur l'élément de la police. Je veux la hauteur de l'article 90% de la normale, quelle que soit la police choisi.
quand j'ai peuplé la liste j'ai utilisé une police stockée dans les paramètres mais vous pouvez aussi utiliser une police littérale comme "Consolas".
lvResults.Font =
new Font(Properties.Settings.Default.usrHookFont.FontFamily,
(float)(Properties.Settings.Default.usrHookFont.Size * .9));
foreach (HookSet item in resultSet)
{
ListViewItem lvi = new ListViewItem();
lvi.Font = Properties.Settings.Default.usrHookFont;
<dot><dot><dot>
}