2013-08-21 2 views
0

У меня есть путь к файлу .cur ("%SystemRoot%\cursors\aero_arrow.cur"), который я хочу отобразить в элементе управления изображением. Поэтому мне нужно преобразовать Cursor в ImageSource. Я попробовал как CursorConverter, так и ImageSourceConverter, но не повезло. Я также попытался создать Graphics из курсора, а затем преобразовать его в Bitmap, но это тоже не сработало. Затем я нашел принятый ответ в этой теме: http://social.msdn.microsoft.com/Forums/vstudio/en-US/87ee395c-9134-4196-bcd8-3d8e8791ff27/is-there-any-way-convert-cursor-to-iconКак преобразовать курсор в ImageSource

Теперь самое смешное, что я не могу создать новый экземпляр System.Windows.Form.Cursor, не имеющий ни пути к файлу, ни потока, поскольку он выдает следующее исключение:

System.Runtime.InteropServices.COMException (0x800A01E1): исключение из HRESULT : 0x800A01E1 (CTL_E_INVALIDPICTURE) при System.Windows.Forms.UnsafeNativeMethods.IPersistStream.Load (IStream PSTM) в System.Windows .Forms.Cursor.LoadPicture (поток IStream)

Так может ли кто-нибудь сказать мне лучший способ конвертировать System.Windows.Input.Cursor в ImageSource?

А как насчет курсоров? Если я правильно помню System.Windows.Input.Cursor не поддерживает анимированные курсоры, то как я могу показать их пользователю? Преобразуя их в gif, а затем используя 3d-библиотеки gif?

ответ

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 - это то, что я могу 't получить, чтобы создать новый экземпляр курсора с помощью дескриптора IntPtr ...

Редактировать: Указанный выше метод НЕ работает с курсорами, имеющими низкие цветовые разряды. Альтернатива является использование Icon.ExtractAssociatedIcon вместо:

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

Надеется, что кто-то помогает ...