win10的毛玻璃透明背景窗口(winform、wpf)
win10的毛玻璃透明背景窗口。win7、win8没试过,不知道效果。
1、winform的实现
必须为无边框的窗体,为了效果好看,这里先建立一个无边框阴影窗体的类:ConextForm.cs
程序代码:
using System; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; public partial class ConextForm : Form { public bool Sizeable = true; [DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")] private static extern IntPtr CreateRoundRectRgn ( int nLeftRect, int nTopRect, int nRightRect, int nBottomRect, int nWidthEllipse, int nHeightEllipse ); [DllImport("dwmapi.dll")] public static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMarInset); [DllImport("dwmapi.dll")] public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize); [DllImport("dwmapi.dll")] public static extern int DwmIsCompositionEnabled(ref int pfEnabled); private bool m_aeroEnabled = false; private const int CS_DROPSHADOW = 0x00020000; private const int WM_NCPAINT = 0x0085; private const int WM_ACTIVATEAPP = 0x001C; public struct MARGINS { public int leftWidth; public int rightWidth; public int topHeight; public int bottomHeight; } protected override CreateParams CreateParams { get { m_aeroEnabled = CheckAeroEnabled(); CreateParams cp = base.CreateParams; if (!m_aeroEnabled) cp.ClassStyle |= CS_DROPSHADOW; return cp; } } private bool CheckAeroEnabled() { if (Environment.OSVersion.Version.Major >= 6) { int enabled = 0; DwmIsCompositionEnabled(ref enabled); return (enabled == 1) ? true : false; } return false; } const int HTLEFT = 10; const int HTRIGHT = 11; const int HTTOP = 12; const int HTTOPLEFT = 13; const int HTTOPRIGHT = 14; const int HTBOTTOM = 15; const int HTBOTTOMLEFT = 0x10; const int HTBOTTOMRIGHT = 17; protected override void WndProc(ref Message m) { base.WndProc(ref m); switch (m.Msg) { case WM_NCPAINT: if (m_aeroEnabled) { var v = 2; DwmSetWindowAttribute(this.Handle, 2, ref v, 4); MARGINS margins = new MARGINS() { bottomHeight = 1, leftWidth = 1, rightWidth = 1, topHeight = 1 }; DwmExtendFrameIntoClientArea(this.Handle, ref margins); } break; case 0x0084: if (Sizeable) { base.WndProc(ref m); Point vPoint = new Point((int)m.LParam & 0xFFFF, (int)m.LParam >> 16 & 0xFFFF); vPoint = PointToClient(vPoint); if (vPoint.X <= 5) { if (vPoint.Y <= 5) { m.Result = (IntPtr)HTTOPLEFT; } else if (vPoint.Y >= ClientSize.Height - 5) { m.Result = (IntPtr)HTBOTTOMLEFT; } else { m.Result = (IntPtr)HTLEFT; } } else if (vPoint.X >= ClientSize.Width - 5) { if (vPoint.Y <= 5) { m.Result = (IntPtr)HTTOPRIGHT; } else if (vPoint.Y >= ClientSize.Height - 5) { m.Result = (IntPtr)HTBOTTOMRIGHT; } else { m.Result = (IntPtr)HTRIGHT; } } else if (vPoint.Y <= 5) { m.Result = (IntPtr)HTTOP; } else { if (vPoint.Y >= ClientSize.Height - 5) { m.Result = (IntPtr)HTBOTTOM; } } } break; default: break; } } private void InitializeComponent() { this.SuspendLayout(); this.ClientSize = new Size(284, 261); this.DoubleBuffered = true; this.Name = "conextForm"; this.ResumeLayout(false); } }
再修改窗体Form1代码
程序代码:
using System; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; namespace W_1 { public partial class Form1 : ConextForm { [DllImport("user32.dll")] internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data); [StructLayout(LayoutKind.Sequential)] internal struct WindowCompositionAttributeData { public WindowCompositionAttribute Attribute; public IntPtr Data; public int SizeOfData; } internal enum WindowCompositionAttribute { WCA_ACCENT_POLICY = 19 } internal enum AccentState { ACCENT_DISABLED = 0, ACCENT_ENABLE_GRADIENT = 1, ACCENT_ENABLE_TRANSPARENTGRADIENT = 2, ACCENT_ENABLE_BLURBEHIND = 3, ACCENT_INVALID_STATE = 4 } [StructLayout(LayoutKind.Sequential)] internal struct AccentPolicy { public AccentState AccentState; public int AccentFlags; public int GradientColor; public int AnimationId; } internal void EnableBlur() { var accent = new AccentPolicy(); var accentStructSize = Marshal.SizeOf(accent); accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; var accentPtr = Marshal.AllocHGlobal(accentStructSize); Marshal.StructureToPtr(accent, accentPtr, false); var data = new WindowCompositionAttributeData(); data.Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY; data.SizeOfData = accentStructSize; data.Data = accentPtr; SetWindowCompositionAttribute(this.Handle, ref data); Marshal.FreeHGlobal(accentPtr); } ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// public Form1() { InitializeComponent(); this.Location = new Point(100, 100); this.Size = new Size(600, 400); this.FormBorderStyle = FormBorderStyle.None; this.BackColor = Color.Pink; this.TransparencyKey = Color.Pink; this.Load += Form1_Load; this.MouseMove += FormMove_MouseDown; } private void Form1_Load(object sender, EventArgs e) { EnableBlur(); } [DllImport("user32.dll")] public static extern bool ReleaseCapture(); [DllImport("user32.dll")] public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam); private void FormMove_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { ReleaseCapture(); SendMessage(Handle, 0xA1, 0x02, 0); } } } }
这样就完成了。美中不足,由于透明了颜色Pink,所以有些字体显示有毛边。解决办法:窗体上面再嵌套一个窗体,设置透明度就可以了,移动最上层窗体,下面的毛玻璃窗体跟着移动就可以了。
2、wpf:
简单多了,直接写
程序代码:
using System; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media; namespace W_2 { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { [DllImport("user32.dll")] internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data); [StructLayout(LayoutKind.Sequential)] internal struct WindowCompositionAttributeData { public WindowCompositionAttribute Attribute; public IntPtr Data; public int SizeOfData; } internal enum WindowCompositionAttribute { WCA_ACCENT_POLICY = 19 } internal enum AccentState { ACCENT_DISABLED = 0, ACCENT_ENABLE_GRADIENT = 1, ACCENT_ENABLE_TRANSPARENTGRADIENT = 2, ACCENT_ENABLE_BLURBEHIND = 3, ACCENT_INVALID_STATE = 4 } [StructLayout(LayoutKind.Sequential)] internal struct AccentPolicy { public AccentState AccentState; public int AccentFlags; public int GradientColor; public int AnimationId; } internal void EnableBlur() { var windowHelper = new WindowInteropHelper(this); var accent = new AccentPolicy(); var accentStructSize = Marshal.SizeOf(accent); accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; var accentPtr = Marshal.AllocHGlobal(accentStructSize); Marshal.StructureToPtr(accent, accentPtr, false); var data = new WindowCompositionAttributeData(); data.Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY; data.SizeOfData = accentStructSize; data.Data = accentPtr; SetWindowCompositionAttribute(windowHelper.Handle, ref data); Marshal.FreeHGlobal(accentPtr); } ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// public MainWindow() { InitializeComponent(); WindowStyle = WindowStyle.None; AllowsTransparency = true; Background = Brushes.Transparent; this.Loaded += (s, e) => { EnableBlur(); }; this.MouseMove += MainWindow_MouseMove; } private void MainWindow_MouseMove(object sender, MouseEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed) { this.DragMove(); } } } }
总之,winform要达到比较好的效果,需无边框阴影窗口,并窗体叠加;wpf直接写就行了。
以前学c#时候google上找的,发到了一些网站上,这里详细给出代码。