工作中我们会经常遇到自定义一些窗口的样式,设置无边框然后自定义关闭、最大化等其他菜单,但是这样就失去了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;
}
效果如下: