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.

467 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 argGraceForm)
  39. {
  40. _parent = argGraceForm;
  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 argWidth, int argHeight, bool argFocus = true)
  83. {
  84. return ShadowImage_1(argWidth, argHeight, argFocus);
  85. }
  86. private Bitmap ShadowImage_2(int argWidth, int argHeight, bool argFocus = true)
  87. {
  88. var vbitmap = new Bitmap(argWidth, argHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
  89. var vg = Graphics.FromImage(vbitmap);
  90. vg.Clear(Color.FromArgb(0, 0, 0, 0));
  91. vg.SmoothingMode = SmoothingMode.HighQuality;
  92. vg.CompositingMode = CompositingMode.SourceCopy;
  93. int vwidth = _parent.Width + 200;
  94. int vheight = _parent.Height + 200;
  95. if ((vwidth > Screen.PrimaryScreen.Bounds.Width) || (vheight > Screen.PrimaryScreen.Bounds.Height))
  96. {
  97. //using (var vp = new Pen(bordercolor)) vg.DrawRectangle(vp, 100, 100, Width - 200, Height - 200);
  98. vg.Dispose();
  99. return vbitmap;
  100. }
  101. for (int i = 0; i < 100; i++)
  102. {
  103. var vrect = new Rectangle(i, i, vwidth - (i * 2), vheight - (i * 2));
  104. var vpath = FormsUtility.CreatePath(vrect, 99 - i);
  105. var valpha = GetAlpha(99 - i);
  106. var vpen = new Pen(Color.FromArgb(valpha, 0, 0, 0));
  107. // var vbrush = new SolidBrush(Color.FromArgb(valpha, 0, 0, 0));
  108. vg.DrawRectangle(vpen, vrect);
  109. //vg.DrawPath(vpen, vpath);
  110. //vg.FillPath(vbrush, vpath);
  111. //vbrush.Dispose();
  112. vpen.Dispose();
  113. vpath.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. vg.Dispose();
  134. return vbitmap;
  135. }
  136. private Bitmap ShadowImage_1(int argWidth, int argHeight, bool argFocus = true)
  137. {
  138. var vbitmap = new Bitmap(argWidth, argHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
  139. var vg = Graphics.FromImage(vbitmap);
  140. vg.Clear(Color.FromArgb(0, 0, 0, 0));
  141. int vwidth = _parent.Width + 200;
  142. int vheight = _parent.Height + 200;
  143. if ((vwidth > Screen.PrimaryScreen.Bounds.Width) || (vheight > Screen.PrimaryScreen.Bounds.Height))
  144. {
  145. //using (var vp = new Pen(bordercolor)) vg.DrawRectangle(vp, 100, 100, Width - 200, Height - 200);
  146. vg.Dispose();
  147. return vbitmap;
  148. }
  149. // 边角距离补偿
  150. int vcorneroffset = 2;
  151. // 上
  152. for (int y = 0; y <= 99; y++)
  153. {
  154. double vl = 100 - y;
  155. using (var vp = new Pen(Color.FromArgb(GetAlpha(vl), 0, 0, 0))) vg.DrawLine(vp, 100, y, argWidth - 101, y);
  156. }
  157. // 下
  158. for (int y = argHeight - 100; y <= argHeight - 2; y++)
  159. {
  160. double vl = y - (argHeight - 101);
  161. using (var vp = new Pen(Color.FromArgb(GetAlpha(vl), 0, 0, 0))) vg.DrawLine(vp, 100, y, argWidth - 101, y);
  162. }
  163. // 左
  164. for (int x = 0; x <= 99; x++)
  165. {
  166. double vl = 100 - x;
  167. using (var vp = new Pen(Color.FromArgb(GetAlpha(vl), 0, 0, 0))) vg.DrawLine(vp, x, 100, x, argHeight - 101);
  168. }
  169. // 右
  170. for (int x = argWidth - 100; x <= argWidth - 2; x++)
  171. {
  172. double vl = x - (argWidth - 101);
  173. using (var vp = new Pen(Color.FromArgb(GetAlpha(vl), 0, 0, 0))) vg.DrawLine(vp, x, 100, x, argHeight - 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)) + vcorneroffset;
  182. vbitmap.SetPixel(x, y, Color.FromArgb(GetAlpha(vl), 0, 0, 0));
  183. }
  184. }
  185. // 右上
  186. for (int x = argWidth - 100; x <= argWidth - 1; x++)
  187. {
  188. for (int y = 0; y <= 99; y++)
  189. {
  190. double vx = 100 - (argWidth - x); double vy = 100 - y;
  191. double vl = Math.Sqrt((vx * vx) + (vy * vy)) + vcorneroffset;
  192. vbitmap.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 = argHeight - 100; y <= argHeight - 1; y++)
  199. {
  200. double vx = 100 - x; double vy = 100 - (argHeight - y);
  201. double vl = Math.Sqrt((vx * vx) + (vy * vy)) + vcorneroffset;
  202. vbitmap.SetPixel(x, y, Color.FromArgb(GetAlpha(vl), 0, 0, 0));
  203. }
  204. }
  205. // 右下
  206. for (int x = argWidth - 100; x <= argWidth - 1; x++)
  207. {
  208. for (int y = argHeight - 100; y <= argHeight - 1; y++)
  209. {
  210. double vx = 100 - (argWidth - x); double vy = 100 - (argHeight - y);
  211. double vl = Math.Sqrt((vx * vx) + (vy * vy)) + vcorneroffset;
  212. vbitmap.SetPixel(x, y, Color.FromArgb(GetAlpha(vl), 0, 0, 0));
  213. }
  214. }
  215. vg.Dispose();
  216. return vbitmap;
  217. }
  218. private static int GetAlpha(double argLength, bool argFocus = true)
  219. {
  220. // 返回值。
  221. double valpha = 0;
  222. // 参数。
  223. double vl = argLength;
  224. if (vl < 0) vl = 0;
  225. if (vl > 100) vl = 100;
  226. // 常数。
  227. double alphamax = 0; // 0 <= x <=255
  228. // 过程变量。
  229. double x = 0, y = 0, xmax = 0, ymax = 0, lmax = 0, tanmax = 0, ratio = 0; ;
  230. // 选择方法。
  231. int vmethod = 1; // flat from 4
  232. switch (vmethod)
  233. {
  234. case 0: // 穷举
  235. ratio = 0.5;
  236. int vlint = (int)argLength;
  237. switch (vlint)
  238. {
  239. #region switch block
  240. case 0: return 40;
  241. case 1: return 39;
  242. case 2: return 38;
  243. case 3: return 37;
  244. case 4: return 36;
  245. case 5: return 36;
  246. case 6: return 35;
  247. case 7: return 34;
  248. case 8: return 33;
  249. case 9: return 33;
  250. case 10: return 32;
  251. case 11: return 31;
  252. case 12: return 30;
  253. case 13: return 30;
  254. case 14: return 29;
  255. case 15: return 28;
  256. case 16: return 28;
  257. case 17: return 27;
  258. case 18: return 26;
  259. case 19: return 26;
  260. case 20: return 25;
  261. case 21: return 24;
  262. case 22: return 24;
  263. case 23: return 23;
  264. case 24: return 23;
  265. case 25: return 22;
  266. case 26: return 21;
  267. case 27: return 21;
  268. case 28: return 20;
  269. case 29: return 20;
  270. case 30: return 19;
  271. case 31: return 19;
  272. case 32: return 18;
  273. case 33: return 17;
  274. case 34: return 17;
  275. case 35: return 16;
  276. case 36: return 16;
  277. case 37: return 15;
  278. case 38: return 15;
  279. case 39: return 14;
  280. case 40: return 14;
  281. case 41: return 13;
  282. case 42: return 13;
  283. case 43: return 12;
  284. case 44: return 12;
  285. case 45: return 12;
  286. case 46: return 11;
  287. case 47: return 11;
  288. case 48: return 10;
  289. case 49: return 10;
  290. case 50: return 10;
  291. case 51: return 9;
  292. case 52: return 9;
  293. case 53: return 8;
  294. case 54: return 8;
  295. case 55: return 8;
  296. case 56: return 7;
  297. case 57: return 7;
  298. case 58: return 7;
  299. case 59: return 6;
  300. case 60: return 6;
  301. case 61: return 6;
  302. case 62: return 5;
  303. case 63: return 5;
  304. case 64: return 5;
  305. case 65: return 4;
  306. case 66: return 4;
  307. case 67: return 4;
  308. case 68: return 4;
  309. case 69: return 3;
  310. case 70: return 3;
  311. case 71: return 3;
  312. case 72: return 3;
  313. case 73: return 2;
  314. case 74: return 2;
  315. case 75: return 2;
  316. case 76: return 2;
  317. case 77: return 2;
  318. case 78: return 1;
  319. case 79: return 1;
  320. case 80: return 1;
  321. case 81: return 1;
  322. case 82: return 1;
  323. case 83: return 1;
  324. case 84: return 1;
  325. case 85: return 0;
  326. case 86: return 0;
  327. case 87: return 0;
  328. case 88: return 0;
  329. case 89: return 0;
  330. case 90: return 0;
  331. case 91: return 0;
  332. case 92: return 0;
  333. case 93: return 0;
  334. case 94: return 0;
  335. case 95: return 0;
  336. case 96: return 0;
  337. case 97: return 0;
  338. case 98: return 0;
  339. case 99: return 0;
  340. case 100: return 0;
  341. #endregion
  342. }
  343. break;
  344. case 1: // 正比例
  345. ratio = 0.2;
  346. valpha = (100 - vl) * ratio;
  347. break;
  348. case 2: // 正切函数
  349. alphamax = 55;
  350. tanmax = 0.45; // 0 < x < 0.5
  351. valpha = (Math.Tan(Math.PI * tanmax * ((100 - vl) / 100)) / Math.Tan(Math.PI * tanmax)) * alphamax;
  352. break;
  353. case 3: // 正弦函数
  354. lmax = 40;
  355. if (vl <= lmax)
  356. {
  357. y = (lmax - vl) * (lmax - vl);
  358. alphamax = 30;
  359. xmax = Math.PI / 2;
  360. x = ((lmax - vl) / lmax) * xmax;
  361. if (x < 0) x = 0;
  362. if (x > Math.PI / 2) x = Math.PI / 2;
  363. valpha = (Math.Sin(Math.PI * 1.5 + x) + 1) * alphamax;
  364. }
  365. else valpha = 0;
  366. break;
  367. case 4: // 平方函数
  368. lmax = 100;
  369. if (vl <= lmax)
  370. {
  371. alphamax = 40;
  372. y = (lmax - vl) * (lmax - vl);
  373. valpha = (y / (lmax * lmax)) * alphamax;
  374. }
  375. else valpha = 0;
  376. break;
  377. case 5: // 幂函数
  378. lmax = 40;
  379. if (vl <= lmax)
  380. {
  381. alphamax = 1;
  382. ratio = 1.1;
  383. x = lmax - vl;
  384. y = Math.Pow(ratio, x);
  385. ymax = Math.Pow(ratio, lmax);
  386. valpha = (y / ymax) * alphamax;
  387. }
  388. else valpha = 0;
  389. break;
  390. case 6:
  391. if (vl <= 40) valpha = 40 - vl;
  392. else valpha = 0;
  393. break;
  394. }
  395. if (valpha < 0) valpha = 0; if (valpha > 255) valpha = 255;
  396. return (int)valpha;
  397. }
  398. #endregion
  399. }
  400. }
  401. #endif