我想在列表视图中更改项目/行的高度。
我搜索过每一个地方,并且我认为为了改变高度,我需要使用LBS_OWNERDRAWFIXED
或MeasureItem
或类似的东西。
问题是我不知道该做什么以及如何使用它。
任何人都可以帮我吗?
修改
我不能使用ImageList黑客,因为我使用SmallImageList是真实的,我需要从ImageList图像大小不同的行高。
谢谢!
答案 0 :(得分:23)
对于仍在努力解决这个问题的人来说,这是我使用的代码:
private void SetHeight(ListView listView, int height)
{
ImageList imgList = new ImageList();
imgList.ImageSize = new Size(1, height);
listView.SmallImageList = imgList;
}
要使用此功能,请执行以下操作:
SetHeight(lvConnections, 25);
答案 1 :(得分:15)
你必须使用一点黑客。诀窍是在StateImageList属性中使用图像列表。 ListView将根据ImageList的ImageSize属性的高度调整其项高度。您不必为项目指定图像,但只需使用StateImageList将强制ListView进行调整。在下面的示例中,我将图像列表大小设置为32x32,从而产生32px高度的ListViewItem。
答案 2 :(得分:14)
可以使用SmallImageList
技巧完成 - 你必须要小心。 ObjectListView - 围绕标准.NET ListView
的开源包装器 - 使用该技巧成功实现RowHeight
属性。
如果每行需要32个像素,请分配一个16x32(宽x高)的ImageList
,然后将每个图像放在32像素高度的垂直中间位置。
此屏幕截图显示了32像素的行和由于额外空间而可能的自动换行:
ObjectListView
这一切对你有用。事实上,如果您尝试使用ListView执行任何操作,则应认真考虑使用ObjectListView
。它使许多困难的事情(例如按列类型排序,自定义工具提示)变得微不足道,并且几个不可能的事情(例如叠加,虚拟列表上的组)成为可能。
答案 3 :(得分:4)
可悲的是,在这些年里,没有人回答你原来的问题如何使用LBS_OWNERDRAWFIXED
。
您接受的答案是整合一个庞大的项目(演示和文档3,3MB)。但是只是为了设置ListView的行高,这是过度浮动的。
此处建议的其他解决方法(添加ImageList)仅适用于增加行高。但它不允许真正设置RowHeight独立于图像高度。此外,默认行高取决于操作系统。例如,在Windows 7上,行数远高于XP。你不能选择让它们变得更紧,只有更高。
但只有很少的线条,你可以做你想要的。 只需复制并粘贴以下类:
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
将ListViewEx添加到表单后,您将在Visual Studio窗体设计器中看到一个新属性,允许以像素为单位设置行高:
您输入的值将是行高(以像素为单位),并且在所有操作系统上都会得到很好的尊重。我在Windows XP,7和10上测试过它:
此外,我的课程比原始ListView还有两个优势:它绘制无闪烁,并且它尊重 ForeColor 和 Font 设置ListViewSubItem
被原始Microsoft ListView忽略。因此,您可以使用不同的颜色和字体绘制每个单元格。
重要提示:正如MSDN所说,LBS_OWNERDRAWFIXED
的详细信息视图(报告视图)设计为 。我的代码仅适用于此模式,这是因为Microsoft已经设计了它。
另请注意,设置ListView.OwnerDraw = true
与使用LVS_OWNERDRAWFIXED
完全不同。
我没有实现绘图图标,因为我不需要它。但你可以轻松添加它。
答案 4 :(得分:3)
ListView的默认行高(在报表视图模式下)是根据控件的字体大小计算的。
因此,要选择行高,请在ListView属性中选择具有正确高度的字体。 例如,选择MS Sans Serif 18。
然后您可以更改所有项目使用的字体: 插入新项目时,请设置其字体属性。
要优化字体分配,您应该将项目字体声明为表单的私有成员:
Private Font stdfont = new Font( "Consolas", 9.0f, FontStyle.Regular );
然后添加项目时:
ListViewItem i = new ListViewItem( "some text" );
i.Font = stdfont;
MyListView.Items.Add( i );
这个技巧是唯一允许拥有SMALLER线高度的技巧;) 即将控件的字体大小设置为7,并将项目的字体大小设置为10。 (经VS 2008测试)
答案 5 :(得分:1)
Plasmabubble有正确的想法。这扩展了这一点,是我用来为项目使用窄线宽的。
ListView中的换行符取决于ListView的字体,无法更改。但是,您可以将ListView中的项目的字体设置为大于ListView的字体。
如果您希望它成比例,请根据项目的字体创建字体。 无论选择何种字体,我都希望项目高度为正常值的90%。
当我填充列表时,我使用了存储在设置中的字体,但您也可以使用像#34; Consolas&#34;这样的文字字体。
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>
}