在WinForms / .NET中更改光标热点

9

我正在从图像资源中创建一个运行时光标。新光标的热点始终设置为16x16(32x32图像)。是否可以在运行时更改热点,还是需要创建.cur文件?

我正在运行时从图像资源创建光标。新光标的热点总是设置为16x16(32x32像素的图像)。是否可以在运行时更改热点位置,还是需要创建.cur文件?

3个回答

28

当然可以。以下是我的实用函数,您可以根据需要进行编辑 :)

    public struct IconInfo
    {
        public bool fIcon;
        public int xHotspot;
        public int yHotspot;
        public IntPtr hbmMask;
        public IntPtr hbmColor;
    }
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);
    [DllImport("user32.dll")]
    public static extern IntPtr CreateIconIndirect(ref IconInfo icon);

    /// <summary>
    /// Create a cursor from a bitmap without resizing and with the specified
    /// hot spot
    /// </summary>
    public static Cursor CreateCursorNoResize(Bitmap bmp, int xHotSpot, int yHotSpot)
    {
        IntPtr ptr = bmp.GetHicon();
        IconInfo tmp = new IconInfo();
        GetIconInfo(ptr, ref tmp);
        tmp.xHotspot = xHotSpot;
        tmp.yHotspot = yHotSpot;
        tmp.fIcon = false;
        ptr = CreateIconIndirect(ref tmp);
        return new Cursor(ptr);
    }


    /// <summary>
    /// Create a 32x32 cursor from a bitmap, with the hot spot in the middle
    /// </summary>
    public static Cursor CreateCursor(Bitmap bmp)
    {
        int xHotSpot = 16;
        int yHotSpot = 16;

        IntPtr ptr = ((Bitmap)ResizeImage(bmp, 32, 32)).GetHicon();
        IconInfo tmp = new IconInfo();
        GetIconInfo(ptr, ref tmp);
        tmp.xHotspot = xHotSpot;
        tmp.yHotspot = yHotSpot;
        tmp.fIcon = false;
        ptr = CreateIconIndirect(ref tmp);
        return new Cursor(ptr);
    }

哦,天啊,我已经花了几个毫无结果的小时在.ico文件中更改位,试图制作一个带有正确热点的彩色.cur文件 - 现在我只需使用最初的png文件。真是一种解脱。 - Usurer

2

既然这是一个.NET问题,而不是特定的C#问题,因此在此提供Nick代码的VB.NET转换(以节省其他人的麻烦)。

Module IconUtility
Structure IconInfo
    Public fIcon As Boolean
    Public xHotspot As Integer
    Public yHotspot As Integer
    Public hbmMask As IntPtr
    Public hbmColor As IntPtr
End Structure

Private Declare Function GetIconInfo Lib "user32.dll" (hIcon As IntPtr, ByRef pIconInfo As IconInfo) As Boolean
Private Declare Function CreateIconIndirect Lib "user32.dll" (ByRef icon As IconInfo) As IntPtr

' Create a cursor from a bitmap without resizing and with the specified hot spot
Public Function CreateCursorNoResize(bmp As System.Drawing.Bitmap, xHotSpot As Integer, yHotSpot As Integer) As Cursor
    Dim ptr As IntPtr = bmp.GetHicon
    Dim tmp As IconInfo = New IconInfo()
    GetIconInfo(ptr, tmp)
    tmp.xHotspot = xHotSpot
    tmp.yHotspot = yHotSpot
    tmp.fIcon = False
    ptr = CreateIconIndirect(tmp)
    Return New Cursor(ptr)
End Function
End Module

0

看一下MSDN上的这篇文章。似乎有几个可能的解决方案(使用P/Invoke),你应该能够复制粘贴并使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接