IrregularFormSkin.cs 8.8 KB

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