改进 Link 标签 - 使用系统手形光标并更改 Link 颜色
Improve LinkLabel - Use system hand Cursor and Change Link Color
LinkLabel
控件有一些烦人的问题:
- 默认情况下,它不使用任何系统颜色(即
Color.Blue
而不是 SystemColors.HotTrack
LinkColor
属性)
- 它使用旧的、丑陋的、有别名的手形光标
我找到了以下声称可以解决光标问题的答案 here:
using System.Runtime.InteropServices;
namespace System.Windows.Forms {
public class LinkLabelEx : LinkLabel {
private const int IDC_HAND = 32649;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName);
private static readonly Cursor SystemHandCursor = new Cursor(LoadCursor(IntPtr.Zero, IDC_HAND));
protected override void OnMouseMove(MouseEventArgs e) {
base.OnMouseMove(e);
// If the base class decided to show the ugly hand cursor
if(OverrideCursor == Cursors.Hand) {
// Show the system hand cursor instead
OverrideCursor = SystemHandCursor;
}
}
}
}
但是,这个解决方案并不完美。例如,旧的、丑陋的光标在悬停在其上时会在显示正确的光标之前闪烁一帧。
我也在ComCtl32.dll中看到原生的SysLink
控件没有问题,但是我找不到好的在 C#/WinForms 中使用它的解决方案。但是无论如何我更喜欢纯 .NET 解决方案。
如何通过解决上述问题使LinkLabel
控制更好?
关于颜色,该控件具有允许您更改 link 颜色的属性:LinkColor
、ActiveLinkColor
、VisitedLinkColor
和 DisabledLinkColor
.
这些属性的默认值来自存储在 HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Settings
注册表项中的 Internet Explorer 设置。
要使用不同的颜色,您可以根据自己的喜好设置这些属性。例如,您可以将 LinkColor
设置为 SystemColors.HotTrack
或遵循 w3org 的颜色建议,并使用 #0000EE
作为默认 link 颜色和 #551A8B
对于已访问的 link 和 #FF0000
对于活跃的 links.
关于 blinking,这是因为您共享的代码是在基础 class 更改了光标后在鼠标移动时设置光标。因此,在设置新游标之前有可能 blinking 基础 class 游标。解决问题需要处理WM_SETCURSOR
,必要时将光标设置为系统手形光标。
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class MyLinkLabel : LinkLabel
{
public MyLinkLabel()
{
this.LinkColor = Color.FromArgb(0x00, 0x66, 0xCC);
this.VisitedLinkColor = Color.FromArgb(0x80, 0x00, 0x80);
this.ActiveLinkColor = Color.FromArgb(0xFF, 0x00, 0x00);
}
const int IDC_HAND = 32649;
const int WM_SETCURSOR = 0x0020;
const int HTCLIENT = 1;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName);
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern IntPtr SetCursor(HandleRef hcursor);
static readonly Cursor SystemHandCursor =
new Cursor(LoadCursor(IntPtr.Zero, IDC_HAND));
protected override void WndProc(ref Message msg)
{
if (msg.Msg == WM_SETCURSOR)
WmSetCursor(ref msg);
else
base.WndProc(ref msg);
}
void WmSetCursor(ref Message m)
{
if (m.WParam == (IsHandleCreated ? Handle : IntPtr.Zero) &&
(unchecked((int)(long)m.LParam) & 0xffff) == HTCLIENT)
{
if (OverrideCursor != null)
{
if (OverrideCursor == Cursors.Hand)
SetCursor(new HandleRef(SystemHandCursor, SystemHandCursor.Handle));
else
SetCursor(new HandleRef(OverrideCursor, OverrideCursor.Handle));
}
else
{
SetCursor(new HandleRef(Cursor, Cursor.Handle));
}
}
else
{
DefWndProc(ref m);
}
}
}
LinkLabel
控件有一些烦人的问题:
- 默认情况下,它不使用任何系统颜色(即
Color.Blue
而不是SystemColors.HotTrack
LinkColor
属性) - 它使用旧的、丑陋的、有别名的手形光标
我找到了以下声称可以解决光标问题的答案 here:
using System.Runtime.InteropServices;
namespace System.Windows.Forms {
public class LinkLabelEx : LinkLabel {
private const int IDC_HAND = 32649;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName);
private static readonly Cursor SystemHandCursor = new Cursor(LoadCursor(IntPtr.Zero, IDC_HAND));
protected override void OnMouseMove(MouseEventArgs e) {
base.OnMouseMove(e);
// If the base class decided to show the ugly hand cursor
if(OverrideCursor == Cursors.Hand) {
// Show the system hand cursor instead
OverrideCursor = SystemHandCursor;
}
}
}
}
但是,这个解决方案并不完美。例如,旧的、丑陋的光标在悬停在其上时会在显示正确的光标之前闪烁一帧。
我也在ComCtl32.dll中看到原生的SysLink
控件没有问题,但是我找不到好的在 C#/WinForms 中使用它的解决方案。但是无论如何我更喜欢纯 .NET 解决方案。
如何通过解决上述问题使LinkLabel
控制更好?
关于颜色,该控件具有允许您更改 link 颜色的属性:LinkColor
、ActiveLinkColor
、VisitedLinkColor
和 DisabledLinkColor
.
这些属性的默认值来自存储在 HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Settings
注册表项中的 Internet Explorer 设置。
要使用不同的颜色,您可以根据自己的喜好设置这些属性。例如,您可以将 LinkColor
设置为 SystemColors.HotTrack
或遵循 w3org 的颜色建议,并使用 #0000EE
作为默认 link 颜色和 #551A8B
对于已访问的 link 和 #FF0000
对于活跃的 links.
关于 blinking,这是因为您共享的代码是在基础 class 更改了光标后在鼠标移动时设置光标。因此,在设置新游标之前有可能 blinking 基础 class 游标。解决问题需要处理WM_SETCURSOR
,必要时将光标设置为系统手形光标。
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class MyLinkLabel : LinkLabel
{
public MyLinkLabel()
{
this.LinkColor = Color.FromArgb(0x00, 0x66, 0xCC);
this.VisitedLinkColor = Color.FromArgb(0x80, 0x00, 0x80);
this.ActiveLinkColor = Color.FromArgb(0xFF, 0x00, 0x00);
}
const int IDC_HAND = 32649;
const int WM_SETCURSOR = 0x0020;
const int HTCLIENT = 1;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName);
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern IntPtr SetCursor(HandleRef hcursor);
static readonly Cursor SystemHandCursor =
new Cursor(LoadCursor(IntPtr.Zero, IDC_HAND));
protected override void WndProc(ref Message msg)
{
if (msg.Msg == WM_SETCURSOR)
WmSetCursor(ref msg);
else
base.WndProc(ref msg);
}
void WmSetCursor(ref Message m)
{
if (m.WParam == (IsHandleCreated ? Handle : IntPtr.Zero) &&
(unchecked((int)(long)m.LParam) & 0xffff) == HTCLIENT)
{
if (OverrideCursor != null)
{
if (OverrideCursor == Cursors.Hand)
SetCursor(new HandleRef(SystemHandCursor, SystemHandCursor.Handle));
else
SetCursor(new HandleRef(OverrideCursor, OverrideCursor.Handle));
}
else
{
SetCursor(new HandleRef(Cursor, Cursor.Handle));
}
}
else
{
DefWndProc(ref m);
}
}
}