2010-12-15 15 views
9

Ich verwende den folgenden Code ein transparentes Symbol zu machen:Rendern eines transparenten Cursors in Bitmap, der Alphakanal erhält?

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

leider Bitmap Ich bin nicht in der Lage eine transparente Cursor zu machen! Es funktioniert, wenn ich Cursor direkt auf den Formularbereich zeichne, aber es gibt ein Problem, wenn ich Cursor zu Bitmap zeichne. Jeder Rat wird sehr geschätzt.

alt text

+0

Ja, GDI + hat bekannte Probleme den Alphakanal zu bewahren, wenn Symbole zeichnen. Vielleicht kennt jemand eine Problemumgehung, aber ich vermute, dass der beste Weg, um hier zu gehen, die Verwendung von GDI ist. –

+0

Hmm ... Es ist schade, denn ich möchte mit verwaltetem Code bleiben. Weißt du, wenn Windows 7 weiterhin GDI verwendet, render die Transparenz-Cursor? –

+2

Sieht vertraut aus. Zuordnung ist hier erforderlich. Sie könnten tatsächlich eine bessere Antwort bekommen, wenn Sie sich darum kümmern. –

Antwort

8

Die Lösung, die Sie jetzt haben, nicht vollständig mit verwaltetem Code nicht bleiben. Ihr eigener Kommentar sagt, dass Sie P/Invoking LoadCursorFromFile von user32.dll sind. Und unabhängig davon ist die Verwendung der Win32-API wirklich nichts, vor dem Sie Angst haben sollten.

Wie ich in einem Kommentar erwähnte, ist das, was Sie versuchen, oft problematisch mit GDI + -Zeichnungsfunktionen, wie die meisten von denen von .NET Framework bereitgestellt. Die Aufgabe wird durch die Verwendung von GDI wesentlich erleichtert. Sie können den folgenden Code verwenden, um eine Bitmap aus einem Cursor zu erstellen (oder das Symbol, sie sind im Grunde austauschbar), die den Alphakanal nicht respektiert:

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

Wenn dieser Code nicht kompilieren, stellen Sie sicher, dass Sie haben using Anweisungen für System.Drawing, System.Drawing.Imaging und System.Runtime.InteropServices hinzugefügt. Denken Sie auch daran, die Form1_Paint-Methode als Handler für das Ereignis Paint Ihres Formulars zu verkabeln.

Es ist zu arbeiten getestet:

cursor, drawn from bitmap complete with alpha channel

+0

Cody, vielen Dank! Arbeite wie ein Zauber! –

+0

Hallo geniales Stück Code dort. Wenn ich BitmapFromCursor aufrufe, erhalte ich einen "generischen Fehler in GDI +". in der Zeile "Bitmap bmp = Bitmap.FromHbitmap (ii.hbmColor);". Wer weiß, was es verursacht und wie man es beheben kann? – Neaox

+0

Ok, also habe ich herausgefunden, dass ii.hbmColor einen Nullzeiger zurückgibt. Wer weiß, warum das so ist und wie man es repariert? – Neaox

2

@Cody Grau, das ist nicht Bits mit Cursor mit geringer Farbe arbeiten.

Eine Alternative ist Icon.ExtractAssociatedIcon stattdessen zu verwenden:

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

Hoffnung, dass jemand hilft ...

Verwandte Themen