如何将Cursor转换为ImageSource

时间:2013-08-21 07:57:37

标签: c# .net wpf cursor imagesource

我想要在图像控件中显示.cur文件路径("%SystemRoot%\cursors\aero_arrow.cur")。所以我需要将Cursor转换为ImageSource。我尝试了CursorConverter和ImageSourceConverter,但没有运气。我也尝试从光标创建图形,然后将其转换为Bitmap,但这也无效。然后我在这个帖子中找到了接受的答案:http://social.msdn.microsoft.com/Forums/vstudio/en-US/87ee395c-9134-4196-bcd8-3d8e8791ff27/is-there-any-way-convert-cursor-to-icon

现在有趣的是,我无法创建System.Windows.Form.Cursor的新实例,既没有文件路径也没有流,因为它抛出以下异常:

  

System.Runtime.InteropServices.COMException(0x800A01E1):异常   来自HRESULT:0x800A01E1(CTL_E_INVALIDPICTURE)at   System.Windows.Forms.UnsafeNativeMethods.IPersistStream.Load(的IStream   pstm)在System.Windows.Forms.Cursor.LoadPicture(IStream stream)

那么有人能告诉我将System.Windows.Input.Cursor转换为ImageSource的最佳方式吗?

那个.ani游标怎么样?如果我没记错,System.Windows.Input.Cursor不支持动画游标,那么如何向用户显示呢?然后使用3d party gif库将它们转换为gif?

1 个答案:

答案 0 :(得分:2)

我在这个帖子中找到了解决方案:How to Render a Transparent Cursor to Bitmap preserving alpha channel?

所以这是代码:

[StructLayout(LayoutKind.Sequential)]    
private struct ICONINFO
{
    public bool fIcon;
    public int xHotspot;
    public int yHotspot;
    public IntPtr hbmMask;
    public IntPtr hbmColor;
}

[DllImport("user32")]
private static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO pIconInfo);

[DllImport("user32.dll")]
private static extern IntPtr LoadCursorFromFile(string lpFileName);

[DllImport("gdi32.dll", SetLastError = true)]
private static extern bool DeleteObject(IntPtr hObject);

private Bitmap BitmapFromCursor(Cursor cur)
{
    ICONINFO ii;
    GetIconInfo(cur.Handle, out ii);

    Bitmap bmp = Bitmap.FromHbitmap(ii.hbmColor);
    DeleteObject(ii.hbmColor);
    DeleteObject(ii.hbmMask);

    BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
    Bitmap dstBitmap = new Bitmap(bmData.Width, bmData.Height, bmData.Stride, PixelFormat.Format32bppArgb, bmData.Scan0);
    bmp.UnlockBits(bmData);

    return new Bitmap(dstBitmap);
}

private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
    //Using LoadCursorFromFile from user32.dll, get a handle to the icon
    IntPtr hCursor = LoadCursorFromFile("C:\\Windows\\Cursors\\Windows Aero\\aero_busy.ani");

    //Create a Cursor object from that handle
    Cursor cursor = new Cursor(hCursor);

    //Convert that cursor into a bitmap
    using (Bitmap cursorBitmap = BitmapFromCursor(cursor))
    {
        //Draw that cursor bitmap directly to the form canvas
        e.Graphics.DrawImage(cursorBitmap, 50, 50);
    }
}

它是为Win Forms编写的,并绘制了一个图像。但是也可以在wpf中使用,并引用System.Windows.Forms。然后你可以将该位图转换为位图源并在图像控件中显示...

我使用System.Windows.Forms.Cursor而不是System.Windows.Input.Cursor的原因是我无法使用IntPtr句柄创建一个新的游标实例...

编辑:上述方法不适用于颜色位较低的游标。 另一种方法是改为使用Icon.ExtractAssociatedIcon

System.Drawing.Icon i = System.Drawing.Icon.ExtractAssociatedIcon(@"C:\Windows\Cursors\arrow_rl.cur");
System.Drawing.Bitmap b = i.ToBitmap();

希望有人帮助......