Tag:开源控件 , 源码下载 , 控件开发 , 控件美化 , 窗体换肤 , Skin , QQ表情 , Windows API , GDI+编程 , SQLite , Socket , 控件透明 , 下拉控件 , HTML 解析器 , 图片水印 , ScrollBar(滚动条) , Google Sitemap , 数据库 , SQL , WinForm , P/Invoke , WinForm控件美化扩展系列 , ListViewEx

 
您的位置: >> 首页 >> C# 视角 >> C# WinForm控件美化扩展系列之ListView(4)-实现所有样式的美化

C# WinForm控件美化扩展系列之ListView(4)-实现所有样式的美化

2009-10-26  来自:CS 程序员之窗  字体大小:【  
  • 摘要:完成对ListView各种显示样式(LargeIcon、SmallIcon、List、Tile、Details)和边框、列表头的美化,修正FullRowSelect为Flase的绘制方法。

先看效果:





 

.NET自带的ListView控件本身就有部分BUG,例如当设置显示模式设为Tile(平铺)样式的时候,选择不同的项,就会有些选择后的背景没有完全刷新,会留下部分聚焦框。在美化的过程中,我尽量注意了这些问题,但是也没有做过多的测试,也有可能存在一些问题,首先说一下到目前已经实现了的和没有实现的功能。

实现的功能:

1、  换边框颜色。

2、  当显示模式为Details List时,间隔的项显示不同的背景色。

3、  当显示模式为Details时,对列表头的美化。

4、  各种显示样式(LargeIconSmallIconListTileDetails)的项选择后的背景美化。

没有实现的功能:

1、  不支持显示CheckBox。这个不是不能画出来,问题是获取不到CheckBox显示的位置,因为只有点击的是系统默认的CheckBox的位置,那个项才会被选中,自己绘制的CheckBox跟默认的的位置不对的话,点击了是没用的。所以就没有支持CheckBox

对各个项的绘制,可以通过GetBounds方法得到图标和文本的所在位置和大小,就是没有获取CheckBox的。LargeIconSmallIconList显示样式的绘制比较容易,Details样式的绘制需要注意的FullRowSelect不同设置时背景的绘制,Tile样式的文本绘制麻烦些,需要分别计算每个SubItem的文本的位置和大小。图标的绘制在项不选中的情况下很简单,选中后要实现想系统自带的那种效果需要要到API函数:ImageList_GetIcon,具体的方法,来看看全部的绘制代码吧:

#region Draw Methods

internal void DrawItemInternal(DrawListViewItemEventArgs e)
{
if (base.View == View.Details)
{
return;
}

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 ||
!string.IsNullOrEmpty(item.ImageKey));
bool bSelected =
(itemState
& ListViewItemStates.Selected) != 0;

if (bDrawImage)
{
DrawImage(g, item, bSelected);
}

if (!string.IsNullOrEmpty(item.Text))
{
Rectangle textRect
=
item.GetBounds(ItemBoundsPortion.Label);
DrawBackground(g, e.ItemIndex, textRect, bSelected);
DrawText(g, item, textRect, bSelected);
}
}

private void DrawImage(
Graphics g,
ListViewItem item,
bool selected)
{
ImageList imageList
= item.ImageList;
Size imageSize
= imageList.ImageSize;
Rectangle imageRect
= item.GetBounds(ItemBoundsPortion.Icon);

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

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_SELECTED);
g.DrawIcon(Icon.FromHandle(hIcon), imageRect);
NativeMethods.DestroyIcon(hIcon);
}
else
{
Image image
= imageList.Images[imageIndex];

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:
case View.List:
rect.Inflate(
-1, 0);
break;
}

if (selected)
{
Color baseColor
= _selectedColor;
Color borderColor
= _selectedColor;
Color innerBorderColor
=
Color.FromArgb(
150, 255, 255, 255);

RenderBackgroundInternal(
g,
rect,
baseColor,
borderColor,
innerBorderColor,
0.45f,
true,
LinearGradientMode.Vertical);
}
else
{
if (base.View == View.List)
{
Color backColor
= itemIndex % 2 == 0 ?
_rowBackColor1 : _rowBackColor2;

using (SolidBrush brush = new SolidBrush(backColor))
{
g.FillRectangle(brush, rect);
}
}
}
}

private void DrawText(
Graphics g,
ListViewItem item,
Rectangle textRect,
bool selected)
{
StringFormat sf
= StringFormat.GenericTypographic;
switch (base.View)
{
case View.LargeIcon:
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);
sf.Alignment
= StringAlignment.Near;
sf.LineAlignment
= StringAlignment.Center;
sf.Trimming
= StringTrimming.EllipsisCharacter;
sf.FormatFlags
&= ~(StringFormatFlags.LineLimit);
break;
case View.Tile:
textRect.Inflate(
-2, 0);
sf.Alignment
= StringAlignment.Near;
sf.LineAlignment
= StringAlignment.Center;
sf.Trimming
= StringTrimming.EllipsisCharacter;
sf.FormatFlags
|= StringFormatFlags.NoWrap;
break;
}

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

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

using (Brush brush = new SolidBrush(subItem.ForeColor))
{
g.DrawString(
subItemText,
subItem.Font,
brush,
sunItemTextRect,
sf);
}
sunItemTextRect.Y
+= height;
if (bBreak)
{
break;
}
}
}
}

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;

bool bDrawImage = false;
bool bFistItem = false;
int imageIndex = -1;

if (e.ColumnIndex == 0)
{
bFistItem
= true;
if (item.ImageList != null)
{
if(item.ImageIndex != -1)
{
imageIndex
= item.ImageIndex;
}
else if (!string.IsNullOrEmpty(item.ImageKey))
{
imageIndex
=
item.ImageList.Images.IndexOfKey(item.ImageKey);
}

if(imageIndex != -1)
{
bDrawImage
= true;
}
}
}

Rectangle backRect
= bounds;
Rectangle imageRect
= Rectangle.Empty;
if (bDrawImage)
{
imageRect
= item.GetBounds(ItemBoundsPortion.Icon);
backRect
= item.GetBounds(ItemBoundsPortion.Label);
backRect.X
+= 2;
backRect.Width
-= 2;
}

if (bSelected &&
(
base.FullRowSelect ||
(
!base.FullRowSelect && bFistItem)))
{
backRect.Height
--;
Color baseColor
= _selectedColor;
Color borderColor
= _selectedColor;
Color innerBorderColor
= Color.FromArgb(150, 255, 255, 255);

RenderBackgroundInternal(
g,
backRect,
baseColor,
borderColor,
innerBorderColor,
0.45f,
false,
LinearGradientMode.Vertical);

if (!base.FullRowSelect && bFistItem)
{
backRect.Width
--;
using (Pen pen = new Pen(borderColor))
{
g.DrawRectangle(pen, backRect);
}
backRect.Width
++;
}
else
{
Point[] points
= new Point[4];
points[
0] = new Point(backRect.X, backRect.Y);
points[
1] = new Point(backRect.Right, backRect.Y);
points[
2] = new Point(backRect.Right, backRect.Bottom);
points[
3] = new Point(backRect.X, backRect.Bottom);
using (Pen pen = new Pen(borderColor))
{
if (bFistItem)
{
g.DrawLine(pen, points[
0], points[1]);
g.DrawLine(pen, points[
0], points[3]);
g.DrawLine(pen, points[
2], points[3]);
}
if (e.ColumnIndex == ColumnCount - 1)
{
points[
1].X--;
points[
2].X--;
g.DrawLine(pen, points[
0], points[1]);
g.DrawLine(pen, points[
1], points[2]);
g.DrawLine(pen, points[
2], points[3]);
}
else
{
g.DrawLine(pen, points[
0], points[1]);
g.DrawLine(pen, points[
2], points[3]);
}
}
}
}
else
{
Color backColor
= e.ItemIndex % 2 == 0 ?
_rowBackColor1 : _rowBackColor2;

using (SolidBrush brush = new SolidBrush(backColor))
{
g.FillRectangle(brush, backRect);
}
}

TextFormatFlags flags
= GetFormatFlags(e.Header.TextAlign);
if (bDrawImage)
{
g.InterpolationMode
= InterpolationMode.HighQualityBicubic;
if (bSelected)
{
IntPtr hIcon
= NativeMethods.ImageList_GetIcon(
item.ImageList.Handle,
imageIndex,
(
int)NativeMethods.ImageListDrawFlags.ILD_SELECTED);
g.DrawIcon(Icon.FromHandle(hIcon), imageRect);
NativeMethods.DestroyIcon(hIcon);
}
else
{
Image image
= item.ImageList.Images[imageIndex];
g.DrawImage(
image,
imageRect,
0,
0,
image.Width,
image.Height,
GraphicsUnit.Pixel);
}

Rectangle textRect
= new Rectangle(
imageRect.Right
+ 3,
bounds.Y,
bounds.Width
- imageRect.Right - 3,
bounds.Height);

TextRenderer.DrawText(
g,
item.Text,
item.Font,
textRect,
item.ForeColor,
flags);
}
else
{
bounds.X
+= 3;
TextRenderer.DrawText(
g,
e.SubItem.Text,
e.SubItem.Font,
bounds,
e.SubItem.ForeColor,
flags);
}
}

#endregion

声明:

本文版权归作者和CS 程序员之窗所有,欢迎转载,转载必须保留以下版权信息,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

作者:Starts_2000

出处:CS 程序员之窗 http://www.csharpwin.com

你可以免费使用或修改提供的源代码,但请保留源代码中的版权信息,详情请查看:

CS程序员之窗开源协议 http://www.csharpwin.com/csol.html

作者:starts_2000