使用LinkLabel时发现鼠标移过去变颜色,居然还需要自己写代码。
而且即使用鼠标事件MouseEnter,也是不能完美解决问题的。
所以扩展了一个属性,并借鉴了xtreme中的控件的方法,写了这个控件。
大致思想:
使用反射获得了两个域
//get visualregion and linkfont by reflection
Type type = typeof(LinkLabel.Link);
_visualRegion = type.GetField("visualRegion", BindingFlags.Instance | BindingFlags.NonPublic);
type = typeof(LinkLabel);
_hoverLinkFont = type.GetField("hoverLinkFont", BindingFlags.Instance | BindingFlags.NonPublic);
利用鼠标事件,同时建立了一个时钟,检测鼠标是否离开了控件范围内。
mCheckHoverTimer = new Timer();
在以下事件中检查 CheckHoverLink();//check hover link index
OnMouseMove
CheckHoverTimer_Tick
最后重写OnPaint部分。
下面是源代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Reflection;
using System.ComponentModel;
using System.Globalization;
namespace Hob.Toolbox.Controls
{
/// <summary>
/// 扩展的超链接控件,继承自LinkLabel
/// 2007.08.21 扩展HoverActived属性
/// 当鼠标移动控件上时,如果HoverActived=true,那么显示颜色ActiveLinkColor
/// </summary>
public class HyperLink : LinkLabel
{
/// <summary>
/// constructor
/// </summary>
public HyperLink()
{
//init checkhover timer
mCheckHoverTimer = new Timer();
mCheckHoverTimer.Interval = 10;//10ms
mCheckHoverTimer.Tick += CheckHoverTimer_Tick;
//get visualregion and linkfont by reflection
Type type = typeof(LinkLabel.Link);
_visualRegion = type.GetField("visualRegion", BindingFlags.Instance | BindingFlags.NonPublic);
type = typeof(LinkLabel);
_hoverLinkFont = type.GetField("hoverLinkFont", BindingFlags.Instance | BindingFlags.NonPublic);
}
#region HoverActived field
bool mHoverActived;
/// <summary>
/// mouse move hover link color
/// </summary>
[Category("Appearance"), Description("Be actived when mouse hover")]
public bool HoverActived
{
get
{
return mHoverActived;
}
set
{
mHoverActived = value;
Invalidate();
}
}
#endregion
Timer mCheckHoverTimer;//check hover timer
//hover link and activeLink
LinkLabel.Link mhoverLink = null;
LinkLabel.Link mactiveLink = null;
/// <summary>
/// override OnMouseMove
/// </summary>
/// <param name="e"></param>
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);//call base
if (mhoverLink == null)
CheckHoverLink(e.X, e.Y);//check hover link index
else
mCheckHoverTimer.Enabled = true;//start timer
}
/// <summary>
/// override OnMouseDown
/// </summary>
/// <param name="e"></param>
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
mactiveLink = PointInLink(e.X, e.Y);
}
/// <summary>
/// override OnMouseUp
/// </summary>
/// <param name="e"></param>
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
mactiveLink = null;
}
#region CheckHoverLink
/// <summary>
/// check hover link overload 1
/// </summary>
void CheckHoverLink()
{
//get mouse position
Point point = MousePosition;
point = this.PointToClient(point);
CheckHoverLink(point.X, point.Y);
}
/// <summary>
/// check hover link overload 2
/// </summary>
void CheckHoverLink(int x, int y)
{
LinkLabel.Link oldlink = mhoverLink;//save old hover index
mhoverLink = PointInLink(x, y);
if (mhoverLink == null)
mCheckHoverTimer.Enabled = false;//stop timer
if (oldlink != mhoverLink)//change
Invalidate();//redraw
}
#endregion
/// <summary>
/// check hover timer tick
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void CheckHoverTimer_Tick(Object sender, EventArgs e)
{
CheckHoverLink();//check hover link index
}
/// <summary>
/// get link visual region
/// </summary>
FieldInfo _visualRegion;
Region GetVisualRegion(LinkLabel.Link link)
{
object result = _visualRegion.GetValue(link);
return (Region)result;
}
/// <summary>
/// get hover link font
/// </summary>
FieldInfo _hoverLinkFont;
Font GetHoverLinkFont()
{
object result = _hoverLinkFont.GetValue(this);
return (Font)result;
}
/// <summary>
/// get is one link
/// </summary>
/// <returns></returns>
bool _IsOneLink()
{
if (((this.Links == null) || (this.Links.Count != 1)) || (this.Text == null))
{
return false;
}
StringInfo info = new StringInfo(this.Text);
return ((this.LinkArea.Start == 0) && (this.LinkArea.Length == info.LengthInTextElements));
}
/// <summary>
/// repaint
/// </summary>
/// <param name="e"></param>
protected override void OnPaint(PaintEventArgs e)
{
//call base
base.OnPaint(e);
if (Text.Length == 0 || !Enabled || mhoverLink == null
|| mhoverLink == mactiveLink) return;//do nothing
//draw hover link
if (mHoverActived)
{
//get linkfont and visualregion
Graphics dc = e.Graphics;
bool bOne = _IsOneLink();
Font linkFont = GetHoverLinkFont();
if (linkFont != null)
{
if (!bOne)
dc.Clip = GetVisualRegion(mhoverLink);
dc.DrawString(Text, linkFont, new SolidBrush(ActiveLinkColor),
ClientRectangle.Left, ClientRectangle.Top);
}
}
}
}
}