IrregularFormSkin.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10. using Y.Utils.WindowsUtils.APIUtils;
  11. namespace Y.Skin.YoForm.Irregular
  12. {
  13. partial class IrregularFormSkin : Form
  14. {
  15. private IrregularForm Main;
  16. public IrregularFormSkin(IrregularForm main)
  17. {
  18. InitializeComponent();
  19. SetStyles();//减少闪烁
  20. Main = main;//获取控件层对象
  21. FormBorderStyle = FormBorderStyle.None;//设置无边框的窗口样式
  22. ShowInTaskbar = true;//使控件层显示到任务栏
  23. BackgroundImage = Main.BackgroundImage;//将控件层背景图应用到皮肤层
  24. BackgroundImageLayout = ImageLayout.Stretch;//自动拉伸背景图以适应窗口
  25. Size = Main.Size;//统一大小
  26. Main.Owner = this;//设置控件层的拥有皮肤层
  27. FormMovableEvent();//激活皮肤层窗体移动
  28. SetBits();//绘制半透明不规则皮肤
  29. Location = new Point(Main.Location.X, Main.Location.Y);//统一控件层和皮肤层的位置
  30. }
  31. #region 减少闪烁
  32. private void SetStyles()
  33. {
  34. SetStyle(
  35. ControlStyles.UserPaint |
  36. ControlStyles.AllPaintingInWmPaint |
  37. ControlStyles.OptimizedDoubleBuffer |
  38. ControlStyles.ResizeRedraw |
  39. ControlStyles.DoubleBuffer, true);
  40. //强制分配样式重新应用到控件上
  41. UpdateStyles();
  42. base.AutoScaleMode = AutoScaleMode.None;
  43. }
  44. #endregion
  45. #region 不规则无毛边方法
  46. protected override CreateParams CreateParams
  47. {
  48. get
  49. {
  50. CreateParams cParms = base.CreateParams;
  51. cParms.ExStyle |= 0x00080000; // WS_EX_LAYERED
  52. return cParms;
  53. }
  54. }
  55. public void SetBits()
  56. {
  57. if (BackgroundImage != null)
  58. {
  59. //绘制绘图层背景
  60. Bitmap bitmap = new Bitmap(BackgroundImage, base.Width, base.Height);
  61. if (!Bitmap.IsCanonicalPixelFormat(bitmap.PixelFormat) || !Bitmap.IsAlphaPixelFormat(bitmap.PixelFormat))
  62. throw new ApplicationException("图片必须是32位带Alhpa通道的图片。");
  63. IntPtr oldBits = IntPtr.Zero;
  64. IntPtr screenDC = FormStyleAPI.GetDC(IntPtr.Zero);
  65. IntPtr hBitmap = IntPtr.Zero;
  66. IntPtr memDc = FormStyleAPI.CreateCompatibleDC(screenDC);
  67. try
  68. {
  69. FormStyleAPI.Point topLoc = new FormStyleAPI.Point(Left, Top);
  70. FormStyleAPI.Size bitMapSize = new FormStyleAPI.Size(Width, Height);
  71. FormStyleAPI.BLENDFUNCTION blendFunc = new FormStyleAPI.BLENDFUNCTION();
  72. FormStyleAPI.Point srcLoc = new FormStyleAPI.Point(0, 0);
  73. hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));
  74. oldBits = FormStyleAPI.SelectObject(memDc, hBitmap);
  75. blendFunc.BlendOp = FormStyleAPI.AC_SRC_OVER;
  76. blendFunc.SourceConstantAlpha = Byte.Parse(((int)(Main.Opacity * 255)).ToString());
  77. blendFunc.AlphaFormat = FormStyleAPI.AC_SRC_ALPHA;
  78. blendFunc.BlendFlags = 0;
  79. FormStyleAPI.UpdateLayeredWindow(Handle, screenDC, ref topLoc, ref bitMapSize, memDc, ref srcLoc, 0, ref blendFunc, FormStyleAPI.ULW_ALPHA);
  80. }
  81. finally
  82. {
  83. if (hBitmap != IntPtr.Zero)
  84. {
  85. FormStyleAPI.SelectObject(memDc, oldBits);
  86. FormStyleAPI.DeleteObject(hBitmap);
  87. }
  88. FormStyleAPI.ReleaseDC(IntPtr.Zero, screenDC);
  89. FormStyleAPI.DeleteDC(memDc);
  90. bitmap.Dispose();
  91. }
  92. }
  93. }
  94. #endregion
  95. #region 无标题栏的窗口移动
  96. private Point mouseOffset; //记录鼠标指针的坐标
  97. private bool isMouseDown = false; //记录鼠标按键是否按下
  98. /// <summary>
  99. /// 窗体移动监听绑定
  100. /// </summary>
  101. private void FormMovableEvent()
  102. {
  103. //绘制层窗体移动
  104. this.MouseDown += new MouseEventHandler(Frm_MouseDown);
  105. this.MouseMove += new MouseEventHandler(Frm_MouseMove);
  106. this.MouseUp += new MouseEventHandler(Frm_MouseUp);
  107. this.LocationChanged += new EventHandler(Frm_LocationChanged);
  108. //控制层层窗体移动
  109. Main.MouseDown += new MouseEventHandler(Frm_MouseDown);
  110. Main.MouseMove += new MouseEventHandler(Frm_MouseMove);
  111. Main.MouseUp += new MouseEventHandler(Frm_MouseUp);
  112. Main.LocationChanged += new EventHandler(Frm_LocationChanged);
  113. }
  114. /// <summary>
  115. /// 窗体按下时
  116. /// </summary>
  117. /// <param name="sender"></param>
  118. /// <param name="e"></param>
  119. private void Frm_MouseDown(object sender, MouseEventArgs e)
  120. {
  121. if (Main.SkinMovable)
  122. {
  123. int xOffset;
  124. int yOffset;
  125. //点击窗体时,记录鼠标位置,启动移动
  126. if (e.Button == MouseButtons.Left)
  127. {
  128. xOffset = -e.X;
  129. yOffset = -e.Y;
  130. mouseOffset = new Point(xOffset, yOffset);
  131. isMouseDown = true;
  132. }
  133. }
  134. }
  135. /// <summary>
  136. /// 窗体移动时
  137. /// </summary>
  138. /// <param name="sender"></param>
  139. /// <param name="e"></param>
  140. private void Frm_MouseMove(object sender, MouseEventArgs e)
  141. {
  142. if (Main.SkinMovable)
  143. {
  144. //将调用此事件的窗口保存下
  145. Form frm = (Form)sender;
  146. //确定开启了移动模式后
  147. if (isMouseDown)
  148. {
  149. //移动的位置计算
  150. Point mousePos = Control.MousePosition;
  151. mousePos.Offset(mouseOffset.X, mouseOffset.Y);
  152. //判断是绘图层还是控件层调用了移动事件,并作出相应回馈
  153. if (frm == this)
  154. {
  155. Location = mousePos;
  156. }
  157. else
  158. {
  159. Main.Location = mousePos;
  160. }
  161. }
  162. }
  163. }
  164. /// <summary>
  165. /// 窗体按下并释放按钮时
  166. /// </summary>
  167. /// <param name="sender"></param>
  168. /// <param name="e"></param>
  169. private void Frm_MouseUp(object sender, MouseEventArgs e)
  170. {
  171. if (Main.SkinMovable)
  172. {
  173. // 修改鼠标状态isMouseDown的值
  174. // 确保只有鼠标左键按下并移动时,才移动窗体
  175. if (e.Button == MouseButtons.Left)
  176. {
  177. //松开鼠标时,停止移动
  178. isMouseDown = false;
  179. //Top高度小于0的时候,等于0
  180. if (this.Top < 0)
  181. {
  182. this.Top = 0;
  183. Main.Top = 0;
  184. }
  185. }
  186. }
  187. }
  188. /// <summary>
  189. /// 窗口移动时
  190. /// </summary>
  191. /// <param name="sender"></param>
  192. /// <param name="e"></param>
  193. void Frm_LocationChanged(object sender, EventArgs e)
  194. {
  195. //将调用此事件的窗口保存下
  196. Form frm = (Form)sender;
  197. if (frm == this)
  198. {
  199. Main.Location = new Point(this.Left, this.Top);
  200. }
  201. else
  202. {
  203. Location = new Point(Main.Left, Main.Top);
  204. }
  205. }
  206. #endregion
  207. }
  208. }