Как сделать Прозрачный Курсор в Растровом изображении, сохраняя альфа-канал? - PullRequest
9 голосов
/ 15 декабря 2010

Я использую код ниже, чтобы сделать прозрачный значок:

    private void button1_Click(object sender, EventArgs e)
    {
        // using LoadCursorFromFile from user32.dll
        var cursor = NativeMethods.LoadCustomCursor(@"d:\Temp\Cursors\Cursors\aero_busy.ani");

        // cursor -> bitmap
        Bitmap bitmap = new Bitmap(48, 48, PixelFormat.Format32bppArgb);
        Graphics gBitmap = Graphics.FromImage(bitmap);
        cursor.DrawStretched(gBitmap, new Rectangle(0, 0, 32, 32));

        // 1. Draw bitmap on a form canvas
        Graphics gForm = Graphics.FromHwnd(this.Handle);
        gForm.DrawImage(bitmap, 50, 50);

        // 2. Draw cursor directly to a form canvas
        cursor.Draw(gForm, new Rectangle(100, 50, 32, 32));

        cursor.Dispose();
    }

К сожалению, я не могу отобразить прозрачный курсор в растровое изображение! Это работает, когда я рисую Курсор непосредственно на холсте формы, но есть проблема, когда я рисую Курсор в растровом изображении. Любой совет высоко ценится.

alt text

Ответы [ 2 ]

9 голосов
/ 15 декабря 2010

Решение, которое у вас есть сейчас, не полностью зависит от управляемого кода.Ваш собственный комментарий говорит, что вы P / Invoking LoadCursorFromFile от user32.dll.И, тем не менее, использование Win32 API - это действительно то, чего вам не следует бояться.

Как я уже упоминал в комментарии, то, что вы пытаетесь сделать, часто проблематично с функциями рисования GDI +, как большинство из предоставленных.NET Framework.Задача значительно упрощается благодаря использованию GDI. Вы можете использовать следующий код для создания растрового изображения из курсора (или значка, они в основном взаимозаменяемы), который соответствует альфа-каналу:

[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);
    }
}

Если этот код не 'Для компиляции убедитесь, что вы добавили using операторов для System.Drawing, System.Drawing.Imaging и System.Runtime.InteropServices.Также не забудьте подключить метод Form1_Paint в качестве обработчика для события Paint вашей формы.

Проверено на работу:

cursor, drawn from bitmap complete with alpha channel

2 голосов
/ 23 августа 2013

@ Коди Грей, это НЕ работает с курсорами, имеющими биты низкого цвета.

Альтернативой является использование Icon.ExtractAssociatedIcon вместо:

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

Надеюсь, это кому-нибудь поможет ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...