BaseForm.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. using System;
  2. using System.Diagnostics;
  3. using System.Drawing;
  4. using System.Drawing.Imaging;
  5. using System.Runtime.InteropServices;
  6. using System.Windows.Forms;
  7. // ReSharper disable UnusedMember.Local
  8. // ReSharper disable IdentifierTypo
  9. // ReSharper disable MemberCanBePrivate.Global
  10. namespace BsWidget
  11. {
  12. public abstract partial class BaseForm : Form
  13. {
  14. private const int WM_NCLBUTTONDOWN = 0xA1;
  15. private const int HT_CAPTION = 0x2;
  16. private const int WS_EX_LAYERED = 0x00080000;
  17. public const byte AcSrcOver = 0x00;
  18. public const byte AcSrcAlpha = 0x01;
  19. public const int UlwAlpha = 0x00000002;
  20. [StructLayout(LayoutKind.Sequential)]
  21. public struct POINT
  22. {
  23. public int x;
  24. public int y;
  25. public POINT(int x, int y)
  26. {
  27. this.x = x;
  28. this.y = y;
  29. }
  30. }
  31. [StructLayout(LayoutKind.Sequential)]
  32. public struct SIZE
  33. {
  34. public int cx;
  35. public int cy;
  36. public SIZE(int cx, int cy)
  37. {
  38. this.cx = cx;
  39. this.cy = cy;
  40. }
  41. }
  42. [StructLayout(LayoutKind.Sequential, Pack = 1)]
  43. public struct Blendfunction
  44. {
  45. public byte BlendOp;
  46. public byte BlendFlags;
  47. public byte SourceConstantAlpha;
  48. public byte AlphaFormat;
  49. }
  50. [DllImport("user32", ExactSpelling = true, SetLastError = true)]
  51. public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref POINT pptDst, ref SIZE psize,
  52. IntPtr hdcSrc, ref POINT pprSrc, int crKey, ref Blendfunction pblend, int dwFlags);
  53. [DllImport("user32", ExactSpelling = true, SetLastError = true)]
  54. public static extern IntPtr GetDC(IntPtr hWnd);
  55. [DllImport("user32", ExactSpelling = true)]
  56. public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDc);
  57. [DllImport("gdi32", ExactSpelling = true, SetLastError = true)]
  58. public static extern IntPtr CreateCompatibleDC(IntPtr hDc);
  59. [DllImport("gdi32", ExactSpelling = true, SetLastError = true)]
  60. public static extern bool DeleteDC(IntPtr hdc);
  61. [DllImport("gdi32", ExactSpelling = true)]
  62. public static extern IntPtr SelectObject(IntPtr hDc, IntPtr hObject);
  63. [DllImport("gdi32", ExactSpelling = true, SetLastError = true)]
  64. public static extern bool DeleteObject(IntPtr hObject);
  65. private Size _viewSize;
  66. private Bitmap _buffedBitmap;
  67. public BaseForm() => InitializeComponent();
  68. protected override CreateParams CreateParams
  69. {
  70. get
  71. {
  72. var cp = base.CreateParams;
  73. cp.ExStyle |= WS_EX_LAYERED;
  74. return cp;
  75. }
  76. }
  77. protected override void OnSizeChanged(EventArgs e)
  78. {
  79. _viewSize = Size;
  80. base.OnSizeChanged(e);
  81. var old = _buffedBitmap;
  82. var sz = ViewSize;
  83. _buffedBitmap = new Bitmap(sz.Width, sz.Height, PixelFormat.Format32bppArgb);
  84. UpdateGraphic();
  85. old?.Dispose();
  86. }
  87. public Size ViewSize
  88. {
  89. get { return _viewSize; }
  90. protected set
  91. {
  92. if (value.Width > 0 && value.Height > 0)
  93. {
  94. MinimumSize = value;
  95. MaximumSize = value;
  96. _viewSize = value;
  97. }
  98. }
  99. }
  100. protected void UpdateGraphic()
  101. {
  102. if (_buffedBitmap == null) return;
  103. using (var g = Graphics.FromImage(_buffedBitmap))
  104. {
  105. RenderGraphic(g);
  106. }
  107. var screenDc = GetDC(IntPtr.Zero);
  108. var memDc = CreateCompatibleDC(screenDc);
  109. var hBitmap = IntPtr.Zero;
  110. var oldBitmap = IntPtr.Zero;
  111. try
  112. {
  113. hBitmap = _buffedBitmap.GetHbitmap(Color.FromArgb(0)); // 创建GDI位图句柄,效率较低
  114. oldBitmap = SelectObject(memDc, hBitmap);
  115. var topPos = new POINT(Left, Top);
  116. var pointSource = new POINT(0, 0);
  117. var size = new SIZE(_buffedBitmap.Width, _buffedBitmap.Height);
  118. var blend = new Blendfunction
  119. {
  120. BlendOp = AcSrcOver,
  121. BlendFlags = 0,
  122. SourceConstantAlpha = 255,
  123. AlphaFormat = AcSrcAlpha
  124. };
  125. UpdateLayeredWindow(
  126. Handle, screenDc
  127. , ref topPos, ref size
  128. , memDc, ref pointSource
  129. , 0, ref blend,
  130. UlwAlpha);
  131. }
  132. catch (Exception ex)
  133. {
  134. Debug.Print(ex.ToString());
  135. }
  136. finally
  137. {
  138. SelectObject(memDc, oldBitmap);
  139. DeleteObject(hBitmap);
  140. DeleteObject(oldBitmap);
  141. ReleaseDC(IntPtr.Zero, screenDc);
  142. DeleteDC(screenDc);
  143. DeleteDC(memDc);
  144. }
  145. }
  146. protected abstract void RenderGraphic(Graphics g);
  147. }
  148. }