You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

QRCodeSplashForm.cs 11 kB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Text;
  7. using System.Windows.Forms;
  8. using System.Drawing.Imaging;
  9. using System.Runtime.InteropServices;
  10. using System.Diagnostics;
  11. namespace Shadowsocks.View
  12. {
  13. public class QRCodeSplashForm : PerPixelAlphaForm
  14. {
  15. public Rectangle TargetRect;
  16. public QRCodeSplashForm()
  17. {
  18. this.Load += QRCodeSplashForm_Load;
  19. this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
  20. this.BackColor = System.Drawing.Color.White;
  21. this.ClientSize = new System.Drawing.Size(1, 1);
  22. this.ControlBox = false;
  23. this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
  24. this.MaximizeBox = false;
  25. this.MinimizeBox = false;
  26. this.Name = "QRCodeSplashForm";
  27. this.ShowIcon = false;
  28. this.ShowInTaskbar = false;
  29. this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
  30. this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
  31. this.TopMost = true;
  32. }
  33. private Timer timer;
  34. private int flashStep;
  35. private static double FPS = 1.0 / 15 * 1000; // System.Windows.Forms.Timer resolution is 15ms
  36. private static double ANIMATION_TIME = 0.5;
  37. private static int ANIMATION_STEPS = (int)(ANIMATION_TIME * FPS);
  38. Stopwatch sw;
  39. int x;
  40. int y;
  41. int w;
  42. int h;
  43. Bitmap bitmap;
  44. Graphics g;
  45. Pen pen;
  46. SolidBrush brush;
  47. private void QRCodeSplashForm_Load(object sender, EventArgs e)
  48. {
  49. SetStyle(ControlStyles.SupportsTransparentBackColor, true);
  50. this.BackColor = Color.Transparent;
  51. flashStep = 0;
  52. x = 0;
  53. y = 0;
  54. w = Width;
  55. h = Height;
  56. sw = Stopwatch.StartNew();
  57. timer = new Timer();
  58. timer.Interval = (int)(ANIMATION_TIME * 1000 / ANIMATION_STEPS);
  59. timer.Tick += timer_Tick;
  60. timer.Start();
  61. bitmap = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
  62. g = Graphics.FromImage(bitmap);
  63. pen = new Pen(Color.Red, 3);
  64. brush = new SolidBrush(Color.FromArgb(30, Color.Red));
  65. }
  66. protected override CreateParams CreateParams
  67. {
  68. get
  69. {
  70. CreateParams cp = base.CreateParams;
  71. cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style
  72. return cp;
  73. }
  74. }
  75. void timer_Tick(object sender, EventArgs e)
  76. {
  77. double percent = (double)sw.ElapsedMilliseconds / 1000.0 / (double)ANIMATION_TIME;
  78. if (percent < 1)
  79. {
  80. // ease out
  81. percent = 1 - Math.Pow((1 - percent), 4);
  82. x = (int)(TargetRect.X * percent);
  83. y = (int)(TargetRect.Y * percent);
  84. w = (int)(TargetRect.Width * percent + this.Size.Width * (1 - percent));
  85. h = (int)(TargetRect.Height * percent + this.Size.Height * (1 - percent));
  86. //codeRectView.Location = new Point(x, y);
  87. //codeRectView.Size = new Size(w, h);
  88. pen.Color = Color.FromArgb((int)(255 * percent), Color.Red);
  89. brush.Color = Color.FromArgb((int)(30 * percent), Color.Red);
  90. g.Clear(Color.Transparent);
  91. g.FillRectangle(brush, x, y, w, h);
  92. g.DrawRectangle(pen, x, y, w, h);
  93. SetBitmap(bitmap);
  94. }
  95. else
  96. {
  97. if (flashStep == 0)
  98. {
  99. timer.Interval = 100;
  100. g.Clear(Color.Transparent);
  101. SetBitmap(bitmap);
  102. }
  103. else if (flashStep == 1)
  104. {
  105. timer.Interval = 50;
  106. g.FillRectangle(brush, x, y, w, h);
  107. g.DrawRectangle(pen, x, y, w, h);
  108. SetBitmap(bitmap);
  109. }
  110. else if (flashStep == 1)
  111. {
  112. g.Clear(Color.Transparent);
  113. SetBitmap(bitmap);
  114. }
  115. else if (flashStep == 2)
  116. {
  117. g.FillRectangle(brush, x, y, w, h);
  118. g.DrawRectangle(pen, x, y, w, h);
  119. SetBitmap(bitmap);
  120. }
  121. else if (flashStep == 3)
  122. {
  123. g.Clear(Color.Transparent);
  124. SetBitmap(bitmap);
  125. }
  126. else if (flashStep == 4)
  127. {
  128. g.FillRectangle(brush, x, y, w, h);
  129. g.DrawRectangle(pen, x, y, w, h);
  130. SetBitmap(bitmap);
  131. }
  132. else
  133. {
  134. sw.Stop();
  135. timer.Stop();
  136. pen.Dispose();
  137. brush.Dispose();
  138. bitmap.Dispose();
  139. this.Close();
  140. }
  141. flashStep++;
  142. }
  143. }
  144. }
  145. // class that exposes needed win32 gdi functions.
  146. class Win32
  147. {
  148. [StructLayout(LayoutKind.Sequential)]
  149. public struct Point
  150. {
  151. public Int32 x;
  152. public Int32 y;
  153. public Point(Int32 x, Int32 y) { this.x = x; this.y = y; }
  154. }
  155. [StructLayout(LayoutKind.Sequential)]
  156. public struct Size
  157. {
  158. public Int32 cx;
  159. public Int32 cy;
  160. public Size(Int32 cx, Int32 cy) { this.cx = cx; this.cy = cy; }
  161. }
  162. [StructLayout(LayoutKind.Sequential, Pack = 1)]
  163. struct ARGB
  164. {
  165. public byte Blue;
  166. public byte Green;
  167. public byte Red;
  168. public byte Alpha;
  169. }
  170. [StructLayout(LayoutKind.Sequential, Pack = 1)]
  171. public struct BLENDFUNCTION
  172. {
  173. public byte BlendOp;
  174. public byte BlendFlags;
  175. public byte SourceConstantAlpha;
  176. public byte AlphaFormat;
  177. }
  178. public const Int32 ULW_COLORKEY = 0x00000001;
  179. public const Int32 ULW_ALPHA = 0x00000002;
  180. public const Int32 ULW_OPAQUE = 0x00000004;
  181. public const byte AC_SRC_OVER = 0x00;
  182. public const byte AC_SRC_ALPHA = 0x01;
  183. [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
  184. public static extern int UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);
  185. [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
  186. public static extern IntPtr GetDC(IntPtr hWnd);
  187. [DllImport("user32.dll", ExactSpelling = true)]
  188. public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
  189. [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
  190. public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
  191. [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
  192. public static extern int DeleteDC(IntPtr hdc);
  193. [DllImport("gdi32.dll", ExactSpelling = true)]
  194. public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
  195. [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
  196. public static extern int DeleteObject(IntPtr hObject);
  197. }
  198. public class PerPixelAlphaForm : Form
  199. {
  200. // http://www.codeproject.com/Articles/1822/Per-Pixel-Alpha-Blend-in-C
  201. // Rui Lopes
  202. public PerPixelAlphaForm()
  203. {
  204. // This form should not have a border or else Windows will clip it.
  205. FormBorderStyle = FormBorderStyle.None;
  206. }
  207. public void SetBitmap(Bitmap bitmap)
  208. {
  209. SetBitmap(bitmap, 255);
  210. }
  211. /// <para>Changes the current bitmap with a custom opacity level. Here is where all happens!</para>
  212. public void SetBitmap(Bitmap bitmap, byte opacity)
  213. {
  214. if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
  215. throw new ApplicationException("The bitmap must be 32ppp with alpha-channel.");
  216. // The idea of this is very simple,
  217. // 1. Create a compatible DC with screen;
  218. // 2. Select the bitmap with 32bpp with alpha-channel in the compatible DC;
  219. // 3. Call the UpdateLayeredWindow.
  220. IntPtr screenDc = Win32.GetDC(IntPtr.Zero);
  221. IntPtr memDc = Win32.CreateCompatibleDC(screenDc);
  222. IntPtr hBitmap = IntPtr.Zero;
  223. IntPtr oldBitmap = IntPtr.Zero;
  224. try
  225. {
  226. hBitmap = bitmap.GetHbitmap(Color.FromArgb(0)); // grab a GDI handle from this GDI+ bitmap
  227. oldBitmap = Win32.SelectObject(memDc, hBitmap);
  228. Win32.Size size = new Win32.Size(bitmap.Width, bitmap.Height);
  229. Win32.Point pointSource = new Win32.Point(0, 0);
  230. Win32.Point topPos = new Win32.Point(Left, Top);
  231. Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION();
  232. blend.BlendOp = Win32.AC_SRC_OVER;
  233. blend.BlendFlags = 0;
  234. blend.SourceConstantAlpha = opacity;
  235. blend.AlphaFormat = Win32.AC_SRC_ALPHA;
  236. Win32.UpdateLayeredWindow(Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, Win32.ULW_ALPHA);
  237. }
  238. finally
  239. {
  240. Win32.ReleaseDC(IntPtr.Zero, screenDc);
  241. if (hBitmap != IntPtr.Zero)
  242. {
  243. Win32.SelectObject(memDc, oldBitmap);
  244. //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.
  245. Win32.DeleteObject(hBitmap);
  246. }
  247. Win32.DeleteDC(memDc);
  248. }
  249. }
  250. protected override CreateParams CreateParams
  251. {
  252. get
  253. {
  254. CreateParams cp = base.CreateParams;
  255. cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style
  256. return cp;
  257. }
  258. }
  259. }
  260. }