2010-12-15 92 views
9

我用下面的代码来呈现透明图标:如何将透明光标渲染为保存Alpha通道的位图?

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

可惜我无法呈现透明光标为位图!它在我直接将Cursor绘制到窗体画布时起作用,但当我将Cursor绘制到位图时出现问题。 任何意见是高度赞赏。

alt text

+0

呀,GDI +已经知道问题绘制图标时,可以保留Alpha通道。也许有人知道解决方法,但我怀疑最好的方法是使用GDI代替。 – 2010-12-15 16:06:58

+0

嗯......很可惜,因为我想留在托管代码中。你知道吗,如果Windows 7仍然使用GDI来渲染透明度游标? – 2010-12-15 16:27:26

+2

看起来很熟悉。此处需要署名。如果你注意到这一点,你可能会得到更好的答案。 – 2010-12-15 16:40:02

回答

8

你现在不能完全使用托管代码住宿解决方案。你自己的评论说你是来自user32.dll的P/Invoking LoadCursorFromFile。无论如何,使用Win32 API确实不值得你担心。

正如我在评论中提到的那样,您尝试执行的操作通常与GDI +绘图函数有关,就像.NET Framework提供的大多数绘图函数一样。通过使用GDI,任务变得更容易。 您可以使用下面的代码创建从游标位图(或图标,它们基本上是可以互换),做尊重Alpha通道:

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

如果此代码不能编译,确保您已为System.DrawingSystem.Drawing.ImagingSystem.Runtime.InteropServices添加了using对帐单。同时请记住将Form1_Paint方法连接为表单的Paint事件的处理程序。

据测试工作:

cursor, drawn from bitmap complete with alpha channel

+0

科迪,非常感谢!像魅力一样工作! – 2010-12-17 16:13:19

+0

嗨真棒一块代码。当我调用BitmapFromCursor时,我得到一个“GDI +中发生的通用错误”。就行“位图bmp = Bitmap.FromHbitmap(ii.hbmColor);”。任何人都知道什么可能会导致它,以及如何解决它? – Neaox 2012-12-13 23:30:28

+0

好吧,所以我想通了ii.hbmColor返回一个空指针。任何人都知道为什么会这样以及如何解决它? – Neaox 2012-12-13 23:45:35

2

@Cody灰,不具有低色位游标工作。

另一种方法是使用Icon.ExtractAssociatedIcon代替:

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

希望帮助别人......

相关问题