C# 在无边框 WinForm 上放置阴影

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16493698/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 01:09:17  来源:igfitidea点击:

Drop Shadow On A Borderless WinForm

c#vb.netwinformsdropshadow

提问by Sam Oyl

I'm trying to drop a shadow around the whole form just like the first picture, except that that is a WPF, not a WinForm. now I want to drop the same shadow on a winform.

我试图像第一张图片一样在整个表单周围添加阴影,除了那是 WPF,而不是 WinForm。现在我想在 winform 上放置相同的阴影。

This is what I want..?

这就是我要的..?

Windows Form Shadow

Windows 窗体阴影

Not this..?

不是这个..?

Windows Form Shadow

Windows 窗体阴影

回答by Amit Mittal

As far as I know, there is no direct way of doing this in WinForms.

据我所知,在 WinForms 中没有直接的方法可以做到这一点。

Instead, you can follow this step by step:

相反,您可以按照以下步骤进行操作:

1) Create an image having the desired drop shadow using photoshop or any other tool.
2) Use this image as background image of your form.
3) Set FormBorderStyle property of the form to None.
4) You are done!
5) Note: Make sure to save the image in proper format(such as png) so that the drop shadow effect could work.

1) 使用 photoshop 或任何其他工具创建具有所需阴影的图像。
2) 将此图像用作表单的背景图像。
3) 将表单的 FormBorderStyle 属性设置为 None。
4)你完成了!
5)注意:确保以正确的格式(例如png)保存图像,以便投影效果可以工作。

回答by Cody Gray

In WinForms, you can just override the form's protected CreateParamsproperty and add the CS_DROPSHADOWflag to the class styles. For example:

在 WinForms 中,您可以只覆盖表单的受保护CreateParams属性并将CS_DROPSHADOW标志添加到类样式。例如:

public class ShadowedForm : Form {
    protected override CreateParams CreateParams {
        get {
            const int CS_DROPSHADOW = 0x20000;
            CreateParams cp = base.CreateParams;
            cp.ClassStyle |= CS_DROPSHADOW;
            return cp;
        }
    }

    // ... other code ...
}

But, a couple of caveats…

但是,有几个警告......

  1. This flag works only on top-level windows. In Win32-speak, that means overlapped and popup windows. It has no effect on child windows (e.g. controls). I thought I remembered hearing somewhere that this limitation had been removed from Windows 8, but I can't find a link confirming this and I don't have Windows 8 installed for testing purposes.

  2. It is possible that the user has disabled this feature altogether. If so, you won't get drop shadows, no matter how you ask for them. That's by design. Your application should not try and override this request. You can determine whether drop shadows are enabled or disabled by P/Invoking the SystemParametersInfofunction and passing the SPI_GETDROPSHADOWflag.

  3. The Aero theme also adds shadows to top-level windows. This effect is separate and distinct from CS_DROPSHADOW, and works onlywhen Aero is enabled. There's no way to turn it off and on for individual windows. Moreover, since the Aero theme has been removed from Windows 8, it won't ever have these shadows.

  1. 此标志仅适用于顶级窗口。在 Win32 中,这意味着重叠和弹出窗口。它对子窗口(例如控件)没有影响。我想我记得在某处听说此限制已从 Windows 8 中删除,但我找不到确认这一点的链接,而且我没有安装 Windows 8 以进行测试。

  2. 用户可能完全禁用了此功能。如果是这样,无论您如何要求,您都不会得到阴影。那是设计使然。您的应用程序不应尝试覆盖此请求。您可以通过 P/InvokingSystemParametersInfo函数并传递SPI_GETDROPSHADOW标志来确定是启用还是禁用阴影。

  3. Aero 主题还为顶级窗口添加了阴影。此效果与 分开且不同CS_DROPSHADOW,并且在启用 Aero时才有效。无法为单个窗口关闭和打开它。此外,由于 Aero 主题已从 Windows 8 中删除,因此它永远不会有这些阴影。

回答by Al.Pertro

Humm ,,, Just past the code and you will get the windows 7 Drop Shadow like this >>> http://marcin.floryan.pl/wp-content/uploads/2010/08/WPF-Window-native-shadow.png

嗯,,,只要通过代码,你就会得到像这样的 Windows 7 投影 >>> http://marcin.floryan.pl/wp-content/uploads/2010/08/WPF-Window-native-shadow。 PNG

Imports System.Runtime.InteropServices

Public Class IMSS_SplashScreen
    Private aeroEnabled As Boolean
    Protected Overrides ReadOnly Property CreateParams() As CreateParams
        Get
            CheckAeroEnabled()
            Dim cp As CreateParams = MyBase.CreateParams
            If Not aeroEnabled Then
                cp.ClassStyle = cp.ClassStyle Or NativeConstants.CS_DROPSHADOW
                Return cp
            Else
                Return cp
            End If
        End Get
    End Property
    Protected Overrides Sub WndProc(ByRef m As Message)
        Select Case m.Msg
            Case NativeConstants.WM_NCPAINT
                Dim val = 2
                If aeroEnabled Then
                    NativeMethods.DwmSetWindowAttribute(Handle, 2, val, 4)
                    Dim bla As New NativeStructs.MARGINS()
                    With bla
                        .bottomHeight = 1
                        .leftWidth = 1
                        .rightWidth = 1
                        .topHeight = 1
                    End With
                    NativeMethods.DwmExtendFrameIntoClientArea(Handle, bla)
                End If
                Exit Select
        End Select
        MyBase.WndProc(m)
    End Sub
    Private Sub CheckAeroEnabled()
        If Environment.OSVersion.Version.Major >= 6 Then
            Dim enabled As Integer = 0
            Dim response As Integer = NativeMethods.DwmIsCompositionEnabled(enabled)
            aeroEnabled = (enabled = 1)
        Else
            aeroEnabled = False
        End If
    End Sub
End Class
Public Class NativeStructs
    Public Structure MARGINS
        Public leftWidth As Integer
        Public rightWidth As Integer
        Public topHeight As Integer
        Public bottomHeight As Integer
    End Structure
End Class
Public Class NativeMethods
    <DllImport("dwmapi")> _
    Public Shared Function DwmExtendFrameIntoClientArea(ByVal hWnd As IntPtr, ByRef pMarInset As NativeStructs.MARGINS) As Integer
    End Function
    <DllImport("dwmapi")> _
    Friend Shared Function DwmSetWindowAttribute(ByVal hwnd As IntPtr, ByVal attr As Integer, ByRef attrValue As Integer, ByVal attrSize As Integer) As Integer
    End Function
    <DllImport("dwmapi.dll")> _
    Public Shared Function DwmIsCompositionEnabled(ByRef pfEnabled As Integer) As Integer
    End Function
End Class
Public Class NativeConstants
    Public Const CS_DROPSHADOW As Integer = &H20000
    Public Const WM_NCPAINT As Integer = &H85
End Class

回答by Ryan Loggerythm

Here's my C# implementation. It's similar to Al. Petro's, but you'll notice that when you lose focus and regain focus, the shadow repaints itself.

这是我的 C# 实现。这与艾尔相似。Petro 的,但是您会注意到,当您失去焦点并重新获得焦点时,阴影会重新绘制自己。

I've also added code to allow mouse-dragging.

我还添加了允许鼠标拖动的代码。

public partial class Form1: Form
{
    [DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
    private static extern IntPtr CreateRoundRectRgn
    (
        int nLeftRect, // x-coordinate of upper-left corner
        int nTopRect, // y-coordinate of upper-left corner
        int nRightRect, // x-coordinate of lower-right corner
        int nBottomRect, // y-coordinate of lower-right corner
        int nWidthEllipse, // height of ellipse
        int nHeightEllipse // width of ellipse
     );        

    [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(this.Handle, 2, ref v, 4);
                    MARGINS margins = new MARGINS()
                    {
                        bottomHeight = 1,
                        leftWidth = 1,
                        rightWidth = 1,
                        topHeight = 1
                    };
                    DwmExtendFrameIntoClientArea(this.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 Form1()
    {
        m_aeroEnabled = false;

        this.FormBorderStyle = FormBorderStyle.None;

        InitializeComponent();
    }
}

回答by D J

I already answered it here: Drop shadow on Borderless Winform-No flicker or disappearance

我已经在这里回答了: 无边框 Winform 上的阴影-无闪烁或消失

Here's my answer:

这是我的回答:

Pls try the below steps and revert back for any errors:

请尝试以下步骤并恢复任何错误:

Add the below code to a new code file named DropShadow.cs;

将以下代码添加到名为 DropShadow.cs 的新代码文件中;

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Core
{
    public class DropShadow
    {
        #region Shadowing

        #region Fields

        private bool _isAeroEnabled = false;
        private bool _isDraggingEnabled = false;
        private const int WM_NCHITTEST = 0x84;
        private const int WS_MINIMIZEBOX = 0x20000;
        private const int HTCLIENT = 0x1;
        private const int HTCAPTION = 0x2;
        private const int CS_DBLCLKS = 0x8;
        private const int CS_DROPSHADOW = 0x00020000;
        private const int WM_NCPAINT = 0x0085;
        private const int WM_ACTIVATEAPP = 0x001C;

        #endregion

        #region Structures

        [EditorBrowsable(EditorBrowsableState.Never)]
        public struct MARGINS
        {
            public int leftWidth;
            public int rightWidth;
            public int topHeight;
            public int bottomHeight;
        }

        #endregion

        #region Methods

        #region Public

        [DllImport("dwmapi.dll")]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMarInset);

        [DllImport("dwmapi.dll")]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);

        [DllImport("dwmapi.dll")]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public static extern int DwmIsCompositionEnabled(ref int pfEnabled);

        [EditorBrowsable(EditorBrowsableState.Never)]
        public static bool IsCompositionEnabled()
        {
            if (Environment.OSVersion.Version.Major < 6) return false;

            bool enabled;
            DwmIsCompositionEnabled(out enabled);

            return enabled;
        }

        #endregion

        #region Private

        [DllImport("dwmapi.dll")]
        private static extern int DwmIsCompositionEnabled(out bool enabled);

        [DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
        private static extern IntPtr CreateRoundRectRgn
        (
            int nLeftRect,
            int nTopRect,
            int nRightRect,
            int nBottomRect,
            int nWidthEllipse,
            int nHeightEllipse
         );

        private bool CheckIfAeroIsEnabled()
        {
            if (Environment.OSVersion.Version.Major >= 6)
            {
                int enabled = 0;
                DwmIsCompositionEnabled(ref enabled);

                return (enabled == 1) ? true : false;
            }
            return false;
        }

        #endregion

        #region Overrides

        public void ApplyShadows(Form form)
        {
            var v = 2;

            DwmSetWindowAttribute(form.Handle, 2, ref v, 4);

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

            DwmExtendFrameIntoClientArea(form.Handle, ref margins);
        }

        #endregion

        #endregion

        #endregion
    }
}

In your form, add this line below InitializeComponent();

在您的表单中,在 InitializeComponent(); 下方添加此行;

(new Core.DropShadow()).ApplyShadows(this);