2010-12-15 14 views
9

uso el siguiente código para hacer que un icono transparente:Cómo renderizar un cursor transparente al mapa de bits preservando el canal alfa?

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

Desafortunadamente no soy capaz de hacer que un cursor transparente de mapa de bits! Funciona cuando dibujo Cursor directamente en el lienzo del formulario, pero hay un problema cuando dibujo el Cursor en el mapa de bits. Cualquier consejo es muy apreciado.

alt text

+0

problemas Sí, GDI + ha conocido que preservan el canal alfa en la elaboración de los iconos. Tal vez alguien sepa de una solución alternativa, pero sospecho que la mejor manera de hacerlo es usar GDI. –

+0

Hmm ... Es una lástima, porque me gustaría quedarme con el código administrado. ¿Sabes que si Windows 7 aún usa GDI, renderiza los cursores de transparencia? –

+2

Parece familiar. La atribución es obligatoria aquí. En realidad, puede obtener una mejor respuesta si se ocupa de esto. –

Respuesta

8

La solución que tienes ahora no se queda por completo con el código administrado. Tu propio comentario dice que estás P/Invocando LoadCursorFromFile desde user32.dll. Y a pesar de todo, usar la API de Win32 no es realmente nada de lo que tengas miedo.

Como mencioné en un comentario, lo que intenta hacer a menudo es problemático con las funciones de dibujo de GDI +, como la mayoría de las proporcionadas por .NET Framework. La tarea se hace mucho más fácil mediante el uso de GDI en su lugar. Se puede utilizar el siguiente código para crear un mapa de bits de un cursor (o icono, que son básicamente intercambiables) que hace respetar el canal alfa:

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

Si este código no compila, asegúrese de que ha agregado using declaraciones para System.Drawing, System.Drawing.Imaging y System.Runtime.InteropServices. Recuerde también conectar el método Form1_Paint como el controlador para el evento Paint de su formulario.

se prueba para trabajar:

cursor, drawn from bitmap complete with alpha channel

+0

Cody, ¡muchas gracias! ¡Trabajar como un encanto! –

+0

Hola increíble pieza de código allí. Cuando llamo a BitmapFromCursor obtengo un "Se produjo un error genérico en GDI +". en la línea "Bitmap bmp = Bitmap.FromHbitmap (ii.hbmColor);". ¿Alguien sabe qué podría estar causándole y cómo solucionarlo? – Neaox

+0

Ok, así que me he dado cuenta de que ii.hbmColor está devolviendo un puntero nulo. ¿Alguien sabe por qué podría ser eso y cómo solucionarlo? – Neaox

2

@Cody gris, que no funciona con los cursores tiene bits de color bajas.

Una alternativa es utilizar Icon.ExtractAssociatedIcon lugar:

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

la esperanza de que ayude a alguien ...

Cuestiones relacionadas