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;
        }

 

效果如下:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM