2010-12-15 76 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(); 

希望幫助別人......

相關問題