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

464 lines
16 KiB

  1. #if NETFX || NETCORE
  2. using System;
  3. using System.Drawing;
  4. using System.Windows.Forms;
  5. using System.Runtime.InteropServices;
  6. using System.Drawing.Drawing2D;
  7. namespace Apewer.Surface
  8. {
  9. internal class BlockShadow : BaseForm
  10. {
  11. #region definition
  12. private BlockForm _parent;
  13. #endregion
  14. #region this
  15. public void Constructor()
  16. {
  17. this.Optimize();
  18. _parent.TopMost = TopMost = _parent.TopMost;
  19. _parent.BringToFront();
  20. this.Location = new Point(_parent.Location.X - 100, _parent.Location.Y - 100);
  21. this.Width = _parent.Width + 200;
  22. this.Height = _parent.Height + 200;
  23. this.TopMost = _parent.TopMost;
  24. this.ShowInTaskbar = false;
  25. this.FormBorderStyle = FormBorderStyle.None;
  26. this.Icon = _parent.Icon;
  27. this.ShowIcon = _parent.ShowIcon;
  28. this.Text = _parent.Text;
  29. FormsUtility.UpdateShadow(this, ShadowImage(Width, Height));
  30. FormsUtility.MousePenetration(this);
  31. this.Paint += Event_This_Paint;
  32. _parent.LocationChanged += new EventHandler(Main_LocationChanged);
  33. _parent.SizeChanged += new EventHandler(Main_SizeChanged);
  34. _parent.VisibleChanged += new EventHandler(Main_VisibleChanged);
  35. _parent.ResizeBegin += Event_Form_ResizeBegin;
  36. _parent.ResizeEnd += Event_Form_Resizeend;
  37. }
  38. public BlockShadow(BlockForm graceForm)
  39. {
  40. _parent = graceForm;
  41. Constructor();
  42. }
  43. #endregion
  44. #region base
  45. protected override CreateParams CreateParams
  46. {
  47. get
  48. {
  49. CreateParams cParms = base.CreateParams;
  50. cParms.ExStyle |= 0x00080000; // WS_EX_LAYERED
  51. return cParms;
  52. }
  53. }
  54. #endregion
  55. #region event
  56. private void Event_This_Paint(object sender, PaintEventArgs e)
  57. {
  58. }
  59. private void Event_Form_Resizeend(object sender, EventArgs e)
  60. {
  61. //this.Visible = true;
  62. }
  63. private void Event_Form_ResizeBegin(object sender, EventArgs e)
  64. {
  65. //this.Visible = false;
  66. }
  67. private void Main_LocationChanged(object sender, EventArgs e)
  68. {
  69. Location = new Point(_parent.Left - 100, _parent.Top - 100);
  70. }
  71. private void Main_SizeChanged(object sender, EventArgs e)
  72. {
  73. this.Size = new Size(_parent.Width + 200, _parent.Height + 200);
  74. FormsUtility.UpdateShadow(this, ShadowImage(Width, Height));
  75. }
  76. private void Main_VisibleChanged(object sender, EventArgs e)
  77. {
  78. this.Visible = _parent.Visible;
  79. }
  80. #endregion
  81. #region shadow
  82. private Bitmap ShadowImage(int width, int height, bool focus = true)
  83. {
  84. return ShadowImage_1(width, height, focus);
  85. }
  86. private Bitmap ShadowImage_2(int width, int height, bool focus = true)
  87. {
  88. var bitmap = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
  89. var g = Graphics.FromImage(bitmap);
  90. g.Clear(Color.FromArgb(0, 0, 0, 0));
  91. g.SmoothingMode = SmoothingMode.HighQuality;
  92. g.CompositingMode = CompositingMode.SourceCopy;
  93. int w = _parent.Width + 200;
  94. int h = _parent.Height + 200;
  95. if ((w > Screen.PrimaryScreen.Bounds.Width) || (h > Screen.PrimaryScreen.Bounds.Height))
  96. {
  97. //using (var vp = new Pen(bordercolor)) vg.DrawRectangle(vp, 100, 100, Width - 200, Height - 200);
  98. g.Dispose();
  99. return bitmap;
  100. }
  101. for (int i = 0; i < 100; i++)
  102. {
  103. var rect = new Rectangle(i, i, w - (i * 2), h - (i * 2));
  104. var path = FormsUtility.CreatePath(rect, 99 - i);
  105. var alpha = GetAlpha(99 - i);
  106. var pen = new Pen(Color.FromArgb(alpha, 0, 0, 0));
  107. // var vbrush = new SolidBrush(Color.FromArgb(valpha, 0, 0, 0));
  108. g.DrawRectangle(pen, rect);
  109. //vg.DrawPath(vpen, vpath);
  110. //vg.FillPath(vbrush, vpath);
  111. //vbrush.Dispose();
  112. pen.Dispose();
  113. path.Dispose();
  114. }
  115. //for (int i = 0; i < 100; i++)
  116. //{
  117. // var vrect = new Rectangle(i, i, 100 - i, 100 - i);
  118. // var valpha = getalpha(99 - i);
  119. // using (var vbrush = new SolidBrush(Color.FromArgb(valpha, 0, 0, 0)))
  120. // {
  121. // vg.FillPie(vbrush, vrect, 180, 90);
  122. // vg.FillPie(vbrush, new Rectangle(0,0,100,100));
  123. // }
  124. //}
  125. //using (var vbrush = new SolidBrush(Color.Transparent))
  126. //{
  127. // vg.FillRectangle(vbrush, new Rectangle(100, 100, vwidth - 200, vheight - 200));
  128. //}
  129. //using (var vbrush = new SolidBrush(Color.Transparent))
  130. //{
  131. // vg.FillRectangle(vbrush, new Rectangle(100, 100, vwidth - 200, vheight - 200));
  132. //}
  133. g.Dispose();
  134. return bitmap;
  135. }
  136. private Bitmap ShadowImage_1(int width, int height, bool focus = true)
  137. {
  138. var bitmap = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
  139. var g = Graphics.FromImage(bitmap);
  140. g.Clear(Color.FromArgb(0, 0, 0, 0));
  141. int w = _parent.Width + 200;
  142. int h = _parent.Height + 200;
  143. if ((w > Screen.PrimaryScreen.Bounds.Width) || (h > Screen.PrimaryScreen.Bounds.Height))
  144. {
  145. //using (var vp = new Pen(bordercolor)) vg.DrawRectangle(vp, 100, 100, Width - 200, Height - 200);
  146. g.Dispose();
  147. return bitmap;
  148. }
  149. // 边角距离补偿
  150. int cornerOffset = 2;
  151. // 上
  152. for (int y = 0; y <= 99; y++)
  153. {
  154. double length = 100 - y;
  155. using (var pen = new Pen(Color.FromArgb(GetAlpha(length), 0, 0, 0))) g.DrawLine(pen, 100, y, width - 101, y);
  156. }
  157. // 下
  158. for (int y = height - 100; y <= height - 2; y++)
  159. {
  160. double length = y - (height - 101);
  161. using (var pen = new Pen(Color.FromArgb(GetAlpha(length), 0, 0, 0))) g.DrawLine(pen, 100, y, width - 101, y);
  162. }
  163. // 左
  164. for (int x = 0; x <= 99; x++)
  165. {
  166. double length = 100 - x;
  167. using (var pen = new Pen(Color.FromArgb(GetAlpha(length), 0, 0, 0))) g.DrawLine(pen, x, 100, x, height - 101);
  168. }
  169. // 右
  170. for (int x = width - 100; x <= width - 2; x++)
  171. {
  172. double length = x - (width - 101);
  173. using (var pen = new Pen(Color.FromArgb(GetAlpha(length), 0, 0, 0))) g.DrawLine(pen, x, 100, x, height - 101);
  174. }
  175. // 左上
  176. for (int x = 0; x <= 99; x++)
  177. {
  178. for (int y = 0; y <= 99; y++)
  179. {
  180. double vx = 100 - x; double vy = 100 - y;
  181. double vl = Math.Sqrt((vx * vx) + (vy * vy)) + cornerOffset;
  182. bitmap.SetPixel(x, y, Color.FromArgb(GetAlpha(vl), 0, 0, 0));
  183. }
  184. }
  185. // 右上
  186. for (int x = width - 100; x <= width - 1; x++)
  187. {
  188. for (int y = 0; y <= 99; y++)
  189. {
  190. double vx = 100 - (width - x); double vy = 100 - y;
  191. double vl = Math.Sqrt((vx * vx) + (vy * vy)) + cornerOffset;
  192. bitmap.SetPixel(x, y, Color.FromArgb(GetAlpha(vl), 0, 0, 0));
  193. }
  194. }
  195. // 左下
  196. for (int x = 0; x <= 99; x++)
  197. {
  198. for (int y = height - 100; y <= height - 1; y++)
  199. {
  200. double vx = 100 - x; double vy = 100 - (height - y);
  201. double vl = Math.Sqrt((vx * vx) + (vy * vy)) + cornerOffset;
  202. bitmap.SetPixel(x, y, Color.FromArgb(GetAlpha(vl), 0, 0, 0));
  203. }
  204. }
  205. // 右下
  206. for (int x = width - 100; x <= width - 1; x++)
  207. {
  208. for (int y = height - 100; y <= height - 1; y++)
  209. {
  210. double vx = 100 - (width - x); double vy = 100 - (height - y);
  211. double vl = Math.Sqrt((vx * vx) + (vy * vy)) + cornerOffset;
  212. bitmap.SetPixel(x, y, Color.FromArgb(GetAlpha(vl), 0, 0, 0));
  213. }
  214. }
  215. g.Dispose();
  216. return bitmap;
  217. }
  218. private static int GetAlpha(double length, bool focus = true)
  219. {
  220. // 返回值。
  221. double alpha = 0;
  222. // 参数。
  223. if (length < 0) length = 0;
  224. if (length > 100) length = 100;
  225. // 常数。
  226. double alphaMax = 0; // 0 <= x <=255
  227. // 过程变量。
  228. double x = 0, y = 0, xMax = 0, yMax = 0, lMax = 0, tanMax = 0, ratio = 0; ;
  229. // 选择方法。
  230. int method = 1; // flat from 4
  231. switch (method)
  232. {
  233. case 0: // 穷举
  234. ratio = 0.5;
  235. int vlint = (int)length;
  236. switch (vlint)
  237. {
  238. case 0: return 40;
  239. case 1: return 39;
  240. case 2: return 38;
  241. case 3: return 37;
  242. case 4: return 36;
  243. case 5: return 36;
  244. case 6: return 35;
  245. case 7: return 34;
  246. case 8: return 33;
  247. case 9: return 33;
  248. case 10: return 32;
  249. case 11: return 31;
  250. case 12: return 30;
  251. case 13: return 30;
  252. case 14: return 29;
  253. case 15: return 28;
  254. case 16: return 28;
  255. case 17: return 27;
  256. case 18: return 26;
  257. case 19: return 26;
  258. case 20: return 25;
  259. case 21: return 24;
  260. case 22: return 24;
  261. case 23: return 23;
  262. case 24: return 23;
  263. case 25: return 22;
  264. case 26: return 21;
  265. case 27: return 21;
  266. case 28: return 20;
  267. case 29: return 20;
  268. case 30: return 19;
  269. case 31: return 19;
  270. case 32: return 18;
  271. case 33: return 17;
  272. case 34: return 17;
  273. case 35: return 16;
  274. case 36: return 16;
  275. case 37: return 15;
  276. case 38: return 15;
  277. case 39: return 14;
  278. case 40: return 14;
  279. case 41: return 13;
  280. case 42: return 13;
  281. case 43: return 12;
  282. case 44: return 12;
  283. case 45: return 12;
  284. case 46: return 11;
  285. case 47: return 11;
  286. case 48: return 10;
  287. case 49: return 10;
  288. case 50: return 10;
  289. case 51: return 9;
  290. case 52: return 9;
  291. case 53: return 8;
  292. case 54: return 8;
  293. case 55: return 8;
  294. case 56: return 7;
  295. case 57: return 7;
  296. case 58: return 7;
  297. case 59: return 6;
  298. case 60: return 6;
  299. case 61: return 6;
  300. case 62: return 5;
  301. case 63: return 5;
  302. case 64: return 5;
  303. case 65: return 4;
  304. case 66: return 4;
  305. case 67: return 4;
  306. case 68: return 4;
  307. case 69: return 3;
  308. case 70: return 3;
  309. case 71: return 3;
  310. case 72: return 3;
  311. case 73: return 2;
  312. case 74: return 2;
  313. case 75: return 2;
  314. case 76: return 2;
  315. case 77: return 2;
  316. case 78: return 1;
  317. case 79: return 1;
  318. case 80: return 1;
  319. case 81: return 1;
  320. case 82: return 1;
  321. case 83: return 1;
  322. case 84: return 1;
  323. case 85: return 0;
  324. case 86: return 0;
  325. case 87: return 0;
  326. case 88: return 0;
  327. case 89: return 0;
  328. case 90: return 0;
  329. case 91: return 0;
  330. case 92: return 0;
  331. case 93: return 0;
  332. case 94: return 0;
  333. case 95: return 0;
  334. case 96: return 0;
  335. case 97: return 0;
  336. case 98: return 0;
  337. case 99: return 0;
  338. case 100: return 0;
  339. }
  340. break;
  341. case 1: // 正比例
  342. ratio = 0.2;
  343. alpha = (100 - length) * ratio;
  344. break;
  345. case 2: // 正切函数
  346. alphaMax = 55;
  347. tanMax = 0.45; // 0 < x < 0.5
  348. alpha = (Math.Tan(Math.PI * tanMax * ((100 - length) / 100)) / Math.Tan(Math.PI * tanMax)) * alphaMax;
  349. break;
  350. case 3: // 正弦函数
  351. lMax = 40;
  352. if (length <= lMax)
  353. {
  354. y = (lMax - length) * (lMax - length);
  355. alphaMax = 30;
  356. xMax = Math.PI / 2;
  357. x = ((lMax - length) / lMax) * xMax;
  358. if (x < 0) x = 0;
  359. if (x > Math.PI / 2) x = Math.PI / 2;
  360. alpha = (Math.Sin(Math.PI * 1.5 + x) + 1) * alphaMax;
  361. }
  362. else alpha = 0;
  363. break;
  364. case 4: // 平方函数
  365. lMax = 100;
  366. if (length <= lMax)
  367. {
  368. alphaMax = 40;
  369. y = (lMax - length) * (lMax - length);
  370. alpha = (y / (lMax * lMax)) * alphaMax;
  371. }
  372. else alpha = 0;
  373. break;
  374. case 5: // 幂函数
  375. lMax = 40;
  376. if (length <= lMax)
  377. {
  378. alphaMax = 1;
  379. ratio = 1.1;
  380. x = lMax - length;
  381. y = Math.Pow(ratio, x);
  382. yMax = Math.Pow(ratio, lMax);
  383. alpha = (y / yMax) * alphaMax;
  384. }
  385. else alpha = 0;
  386. break;
  387. case 6:
  388. if (length <= 40) alpha = 40 - length;
  389. else alpha = 0;
  390. break;
  391. }
  392. if (alpha < 0) alpha = 0; if (alpha > 255) alpha = 255;
  393. return (int)alpha;
  394. }
  395. #endregion
  396. }
  397. }
  398. #endif