1. 程式人生 > 實用技巧 >C# 自定義無邊框窗體陰影效果

C# 自定義無邊框窗體陰影效果

工作中我們會經常遇到自定義一些視窗的樣式,設定無邊框然後自定義關閉、最大化等其他選單,但是這樣就失去了Winform自帶的邊框陰影效果,下面這個方法能讓無邊框增加陰影效果。程式碼如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WinfromTest.ShadowDialog { public partial class ShadowForm : Form { [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; // variables for box shadow
private const int CS_DROPSHADOW = 0x00020000; private const int WM_NCPAINT = 0x0085; private const int WM_ACTIVATEAPP = 0x001C; public struct MARGINS // struct for box shadow { public int leftWidth; public int rightWidth; public int topHeight; public int bottomHeight; } private const int WM_NCHITTEST = 0x84; // variables for dragging the form private const int HTCLIENT = 0x1; private const int HTCAPTION = 0x2; 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; } protected override void WndProc(ref Message m) { switch (m.Msg) { case WM_NCPAINT: // box shadow if (m_aeroEnabled) { var v = 2; DwmSetWindowAttribute(Handle, 2, ref v, 4); MARGINS margins = new MARGINS() { bottomHeight = 1, leftWidth = 0, rightWidth = 0, topHeight = 0 }; DwmExtendFrameIntoClientArea(Handle, ref margins); } break; default: break; } base.WndProc(ref m); if (m.Msg == WM_NCHITTEST && (int)m.Result == HTCLIENT) // drag the form m.Result = (IntPtr)HTCAPTION; } public ShadowForm() { m_aeroEnabled = false; FormBorderStyle = FormBorderStyle.None; InitializeComponent(); } private void btnClose_Click(object sender, EventArgs e) { Close(); } private void ShadowForm_Resize(object sender, EventArgs e) { pnlClient.Dock = DockStyle.Top; pnlClient.Height = this.Height - 1; } } }

1.上面程式碼中MARGINS部分原始碼裡設定的都是1,這樣陰影效果中會有一條1畫素的白邊,如果都設定成0後陰影效果就沒了,無奈只能bottomHeight=1,這樣只有底部有個小白線。

MARGINS margins = new MARGINS()
                        {
                            bottomHeight = 1,
                            leftWidth = 0,
                            rightWidth = 0,
                            topHeight = 0
                        };

2.如果窗體上弄個pannel設定成Fill模式,陰影效果也會消失,費解。。。所以不能全部填充滿,為此我想了個辦法,設計介面還是弄一個pannel設定成FIll模式,這樣不影響我們繼續在頁面佈局,但是在ShadowForm_Resize中動態設定Dock為Top,高度為父容器Height -1就可以了。

這樣一個自帶陰影效果的Form就做好了。

private void ShadowForm_Resize(object sender, EventArgs e)
        {
            pnlClient.Dock = DockStyle.Top;
            pnlClient.Height = this.Height - 1;
        }

效果如下: