From 81dcad5df5c992c2457772e2618e959e586bf648 Mon Sep 17 00:00:00 2001 From: Zch Date: Sat, 24 Mar 2018 21:32:48 +0800 Subject: [PATCH] fix #1768 Move PerPixelAlphaForm's code into QRCodeSplashForm to avoid 2 derived class of Form in same file. Before: QRCodeSplashForm -> PerPixelAlphaForm -> Form After: QRCodeSplashForm -> Form --- shadowsocks-csharp/View/QRCodeSplashForm.cs | 149 +++++++++----------- 1 file changed, 65 insertions(+), 84 deletions(-) diff --git a/shadowsocks-csharp/View/QRCodeSplashForm.cs b/shadowsocks-csharp/View/QRCodeSplashForm.cs index 3bf48888..50b4ccd4 100755 --- a/shadowsocks-csharp/View/QRCodeSplashForm.cs +++ b/shadowsocks-csharp/View/QRCodeSplashForm.cs @@ -12,12 +12,13 @@ using System.Diagnostics; namespace Shadowsocks.View { - public class QRCodeSplashForm : PerPixelAlphaForm + public class QRCodeSplashForm : Form { public Rectangle TargetRect; public QRCodeSplashForm() { + FormBorderStyle = FormBorderStyle.None; this.Load += QRCodeSplashForm_Load; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; this.BackColor = System.Drawing.Color.White; @@ -69,16 +70,6 @@ namespace Shadowsocks.View brush = new SolidBrush(Color.FromArgb(30, Color.Red)); } - protected override CreateParams CreateParams - { - get - { - CreateParams cp = base.CreateParams; - cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style - return cp; - } - } - void timer_Tick(object sender, EventArgs e) { double percent = (double)sw.ElapsedMilliseconds / 1000.0 / (double)ANIMATION_TIME; @@ -148,6 +139,69 @@ namespace Shadowsocks.View flashStep++; } } + + // PerPixelAlphaForm.cs + // http://www.codeproject.com/Articles/1822/Per-Pixel-Alpha-Blend-in-C + // Rui Lopes + protected override CreateParams CreateParams + { + get + { + CreateParams cp = base.CreateParams; + cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style + return cp; + } + } + + public void SetBitmap(Bitmap bitmap) + { + SetBitmap(bitmap, 255); + } + + /// Changes the current bitmap with a custom opacity level. Here is where all happens! + public void SetBitmap(Bitmap bitmap, byte opacity) + { + if (bitmap.PixelFormat != PixelFormat.Format32bppArgb) + throw new ApplicationException("The bitmap must be 32ppp with alpha-channel."); + + // The idea of this is very simple, + // 1. Create a compatible DC with screen; + // 2. Select the bitmap with 32bpp with alpha-channel in the compatible DC; + // 3. Call the UpdateLayeredWindow. + + IntPtr screenDc = Win32.GetDC(IntPtr.Zero); + IntPtr memDc = Win32.CreateCompatibleDC(screenDc); + IntPtr hBitmap = IntPtr.Zero; + IntPtr oldBitmap = IntPtr.Zero; + + try + { + hBitmap = bitmap.GetHbitmap(Color.FromArgb(0)); // grab a GDI handle from this GDI+ bitmap + oldBitmap = Win32.SelectObject(memDc, hBitmap); + + Win32.Size size = new Win32.Size(bitmap.Width, bitmap.Height); + Win32.Point pointSource = new Win32.Point(0, 0); + Win32.Point topPos = new Win32.Point(Left, Top); + Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION(); + blend.BlendOp = Win32.AC_SRC_OVER; + blend.BlendFlags = 0; + blend.SourceConstantAlpha = opacity; + blend.AlphaFormat = Win32.AC_SRC_ALPHA; + + Win32.UpdateLayeredWindow(Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, Win32.ULW_ALPHA); + } + finally + { + Win32.ReleaseDC(IntPtr.Zero, screenDc); + if (hBitmap != IntPtr.Zero) + { + Win32.SelectObject(memDc, oldBitmap); + //Windows.DeleteObject(hBitmap); // The documentation says that we have to use the Windows.DeleteObject... but since there is no such method I use the normal DeleteObject from Win32 GDI and it's working fine without any resource leak. + Win32.DeleteObject(hBitmap); + } + Win32.DeleteDC(memDc); + } + } } @@ -224,77 +278,4 @@ namespace Shadowsocks.View [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)] public static extern int DeleteObject(IntPtr hObject); } - - - public class PerPixelAlphaForm : Form - { - // http://www.codeproject.com/Articles/1822/Per-Pixel-Alpha-Blend-in-C - // Rui Lopes - - public PerPixelAlphaForm() - { - // This form should not have a border or else Windows will clip it. - FormBorderStyle = FormBorderStyle.None; - } - - public void SetBitmap(Bitmap bitmap) - { - SetBitmap(bitmap, 255); - } - - /// Changes the current bitmap with a custom opacity level. Here is where all happens! - public void SetBitmap(Bitmap bitmap, byte opacity) - { - if (bitmap.PixelFormat != PixelFormat.Format32bppArgb) - throw new ApplicationException("The bitmap must be 32ppp with alpha-channel."); - - // The idea of this is very simple, - // 1. Create a compatible DC with screen; - // 2. Select the bitmap with 32bpp with alpha-channel in the compatible DC; - // 3. Call the UpdateLayeredWindow. - - IntPtr screenDc = Win32.GetDC(IntPtr.Zero); - IntPtr memDc = Win32.CreateCompatibleDC(screenDc); - IntPtr hBitmap = IntPtr.Zero; - IntPtr oldBitmap = IntPtr.Zero; - - try - { - hBitmap = bitmap.GetHbitmap(Color.FromArgb(0)); // grab a GDI handle from this GDI+ bitmap - oldBitmap = Win32.SelectObject(memDc, hBitmap); - - Win32.Size size = new Win32.Size(bitmap.Width, bitmap.Height); - Win32.Point pointSource = new Win32.Point(0, 0); - Win32.Point topPos = new Win32.Point(Left, Top); - Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION(); - blend.BlendOp = Win32.AC_SRC_OVER; - blend.BlendFlags = 0; - blend.SourceConstantAlpha = opacity; - blend.AlphaFormat = Win32.AC_SRC_ALPHA; - - Win32.UpdateLayeredWindow(Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, Win32.ULW_ALPHA); - } - finally - { - Win32.ReleaseDC(IntPtr.Zero, screenDc); - if (hBitmap != IntPtr.Zero) - { - Win32.SelectObject(memDc, oldBitmap); - //Windows.DeleteObject(hBitmap); // The documentation says that we have to use the Windows.DeleteObject... but since there is no such method I use the normal DeleteObject from Win32 GDI and it's working fine without any resource leak. - Win32.DeleteObject(hBitmap); - } - Win32.DeleteDC(memDc); - } - } - - protected override CreateParams CreateParams - { - get - { - CreateParams cp = base.CreateParams; - cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style - return cp; - } - } - } }