当前位置:
文档之家› C# WinForm控件美化扩展系列之ListView
C# WinForm控件美化扩展系列之ListView
!string.IsNullOrEmpty(item.ImageKey)); bool bSelected = (itemState & ListViewItemStates.Selected) != 0;
if (bDrawImage) { DrawImage(g, item, bSelected); }
height = TextRenderer.MeasureText( g, subItem.Text, subItem.Font).Height; sunItemTextRect.Height = height; if (sunItemTextRect.Bottom > textRect.Bottom) { sunItemTextRect.Height = textRect.Bottom - sunItemTextRect.Y; bBreak = true; }
int imageIndex = item.ImageIndex != -1 ? item.ImageIndex : imageList.Images.IndexOfKey(item.ImageKey);
if (selected) { IntPtr hIcon = NativeMethods.ImageList_GetIcon( imageList.Handle, imageIndex, (int)NativeMethods.ImageListDrawFlags.ILD_SELECTE D); g.DrawIcon(Icon.FromHandle(hIcon), imageRect); NativeMethods.DestroyIcon(hIcon); } else { Image image = imageList.Images[imageIndex];
个 SubItem 的文本的位置和大小。图标的绘制在项不选中的情况下很简单,选中后要实现想系统 自带的那种效果需要要到 API 函数: ImageList_GetIcon, 具体的方法, 来看看全部的绘制代码吧:
#region Draw Methods
internal void DrawItemInternal(DrawListViewItemEventArgs e) { if (base.View == View.Details) { return; }
RenderBackgroundInternal( g, rect, baseColor, borderColor, innerBorderColor, 0.45f, true,
LinearGradientMode.Vertical); } else { if (base.View == View.List) { Color backColor = itemIndex % 2 == 0 ? _rowBackColor1 : _rowBackColor2;
if (base.View != View.Tile || item.SubItems.Count == 1) { using (Brush brush = new SolidBrush(item.ForeColor)) { g.DrawString(
item.Text, item.Font, brush, textRect, sf); } } else { string subItemText = "A"; int height; bool bBreak = false; Rectangle sunItemTextRect = textRect; foreach (ListViewItem.ListViewSubItem subItem in item. SubItems) { if (!string.IsNullOrEmpty(subItem.Text)) { subItemText = subItem.Text; }
private void DrawImage( Graphics g,
ListViewItem item, bool selected) { ImageList imageList = item.ImageList; Size imageSize = imageList.ImageSize; Rectangle imageRect = item.GetBounds(ItemBoundsPortion.Ico n);
Graphics g = e.Graphics; ListViewItem item = e.Item; ListViewItemStates itemState = e.State; ImageList imageList = item.ImageList;
e.DrawBackground();
bool bDrawImage = (imageList != null) && (item.ImageIndex != -1 ||
using (Brush brush = new SolidBrush(subItem.ForeCo lor)) { g.DrawString( subItemText, subItem.Font, brush, sunItemTextRect, sf);
} sunItemTextRect.Y += height; if (bBreak) { break; } } } }
if (imageRect.Width > imageSize.Width) { imageRect.X += (imageRect.Width - imageSize.Width) / 2; imageRect.Width = imageSize.Width; }
if (imageRect.Height > imageSize.Height) { imageRect.Y += (imageRect.Height - imageSize.Height) / 2; imageRect.Height = imageSize.Height; }
先看效果:
.NET 自带的 ListView 控件本身就有部分 BUG,例如当设置显示模式设为 Tile(平铺)样式 的时候,选择不同的项,就会有些选择后的背景没有完全刷新,会留下部分聚焦框。在美化的过 程中,我尽量注意了这些问题,但是也没有做过多的测试,也有可能存在一些问题,首先说一下 到目前已经实现了的和没有实现的功能。 实现的功能: 1、 换边框颜色。 2、 当显示模式为 Details 和 List 时,间隔的项显示不同的背景色。 3、 当显示模式为 Details 时,对列表头的美化。 4、 各种显示样式(LargeIcon、SmallIcon、 List、Tile、Details)的项选择后的背景美化。 没有实现的功能: 1、 不支持显示 CheckBox。这个不是不能画出来,问题是获取不到 CheckBox 显示的位置, 因为只有点击的是系统默认的 CheckBox 的位置,那个项才会被选中,自己绘制的 Che ckBox 跟默认的的位置不对的话,点击了是没用的。所以就没有支持 CheckBox。 对各个项的绘制,可以通过 GetBounds 方法得到图标和文本的所在位置和大小,就是没有获 取 CheckBox 的。LargeIcon、SmallIcon、List 显示样式的绘制比较容易,Details 样式的绘制需 要注意的 FullRowSelect 不同设置时背景的绘制,Tile 样式的文本绘制麻烦些,需要分别计算每
g.DrawImage( image, imageRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel); } }
private void DrawBackground( Graphics g, int itemIndex, Rectangle rect, bool selected) { switch (base.View) { case View.SmallIcon:
if (!string.IsNullOrEmpty(item.Text)) { Rectangle textRect = item.GetBounds(bel); DrawBackground(g, e.ItemIndex, textRect, bSelected); DrawText(g, item, textRect, bSelected); } }
case View.List: rect.Inflate(-1, 0); break; }
if (selected) { ColoorderColor = _selectedColor; Color innerBorderColor = Color.FromArgb(150, 255, 255, 255);
private void DrawSubItemDetails( DrawListViewSubItemEventArgs e) { Rectangle bounds = e.Bounds; ListViewItemStates itemState = e.ItemState; Graphics g = e.Graphics; ListViewItem item = e.Item; bool bSelected = (itemState & ListViewItemStates.Selected) != 0;
using (SolidBrush brush = new SolidBrush(backColo r)) { g.FillRectangle(brush, rect); } } } }
private void DrawText( Graphics g,
ListViewItem item, Rectangle textRect, bool selected) { StringFormat sf = StringFormat.GenericTypographic; switch (base.View) { case rgeIcon: sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Near; sf.Trimming = StringTrimming.EllipsisCharacter; sf.FormatFlags &= ~(StringFormatFlags.LineLimit); if (selected) { sf.FormatFlags &= ~StringFormatFlags.NoWrap; } break; case View.List: case View.SmallIcon: textRect.Inflate(-1, 0);