Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Windows 7样式的无边框Dropshadow_C#_.net_Winforms_User Interface_Windows 7 - Fatal编程技术网

C# Windows 7样式的无边框Dropshadow

C# Windows 7样式的无边框Dropshadow,c#,.net,winforms,user-interface,windows-7,C#,.net,Winforms,User Interface,Windows 7,短版: 目标:在C语言的无边界WinForm中,一个深沉、黑暗的Windows7 dropshadow# 已知现有解决方案1:使用CreateParams的简单XP风格dropshadow 问题:太弱、太轻、太难看 已知的现有解决方案2:用位图替换表单的GDI 问题:无法使用控件,只能作为启动屏幕使用 本帖的目标:为这个问题找到一个中位数的解决方案,或是一个综合起来更好的解决方案 。 . 长版本: (编辑:我指的是沿着任何windows窗体边框的阴影,如果不清楚的话。) 我知道有一种方法

短版:

目标:在C语言的无边界WinForm中,一个深沉、黑暗的Windows7 dropshadow#


已知现有解决方案1:使用CreateParams的简单XP风格dropshadow

问题:太弱、太轻、太难看


已知的现有解决方案2:用位图替换表单的GDI

问题:无法使用控件,只能作为启动屏幕使用


本帖的目标:为这个问题找到一个中位数的解决方案,或是一个综合起来更好的解决方案

。 .

长版本:

(编辑:我指的是沿着任何windows窗体边框的阴影,如果不清楚的话。) 我知道有一种方法可以在C#中制作XP风格的dropshadows,方法是:

C#代码1-简单XP风格的dropshadow(问题:变亮、变弱、变丑)

然而,我正试图找出如何使它们看起来像Windows7中的那样(更深更大的阴影),却找不出最好的方法

我现在创建了一个方法,可以覆盖整个表单GDI,并像启动屏幕一样出现(不是我的):

C#代码2:用位图替换表单GDI(问题:无法使用表单控件,难以维护GUI)

    public void SetBitmap(Bitmap bitmap, byte opacity)
    {
        if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
            throw new ApplicationException("The bitmap must be 32ppp with alpha-channel.");

        // 1. Create a compatible DC with screen;
        // 2. Select the bitmap with 32bpp with alpha-channel in the compatible DC;
        // 3. Call the UpdateLayeredWindow.

        IntPtr screenDc = Win32.GetDC(IntPtr.Zero);
        IntPtr memDc = Win32.CreateCompatibleDC(screenDc);
        IntPtr hBitmap = IntPtr.Zero;
        IntPtr oldBitmap = IntPtr.Zero;

        try
        {
            hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));  // grab a GDI handle from this GDI+ bitmap
            oldBitmap = Win32.SelectObject(memDc, hBitmap);

            Win32.Size size = new Win32.Size(bitmap.Width, bitmap.Height);
            Win32.Point pointSource = new Win32.Point(0, 0);
            Win32.Point topPos = new Win32.Point(Left, Top);
            Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION();
            blend.BlendOp = Win32.AC_SRC_OVER;
            blend.BlendFlags = 0;
            blend.SourceConstantAlpha = opacity;
            blend.AlphaFormat = Win32.AC_SRC_ALPHA;

            Win32.UpdateLayeredWindow(this.Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, Win32.ULW_ALPHA);
        }
        finally
        {
            Win32.ReleaseDC(IntPtr.Zero, screenDc);
            if (hBitmap != IntPtr.Zero)
            {
                Win32.SelectObject(memDc, oldBitmap);
                Win32.DeleteObject(hBitmap);
            }
            Win32.DeleteDC(memDc);
        }
    }


    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style
            return cp;
        }
    }
然而,这确实给了我一个完整的32位背景(因为我需要手动添加dropshadow),但是我失去了创建可见表单元素的能力


所以基本上,我试图找出这两种方法之间的中间值。在不丢失其他功能/导致过度重新喷漆要求的情况下,可以给我带来深沉的阴影

好吧,经过大约4个小时的头脑风暴和编码,我终于找到了一个解决方案。基本上,我做了两张表格

表单#1:通过修改和组合8个图像(每个方向4个角渐变+4个线性渐变)创建dropshadow,并使用上面发布的第二个代码将其设置为背景(C#代码2:用位图替换表单GDI)。代码很好地解释了这一点

public partial class Dropshadow : Form
{

    public Dropshadow(Form parentForm)
    {
        /*This bit of code makes the form click-through. 
          So you can click forms that are below it in z-space */
        int wl = GetWindowLong(this.Handle, -20);
        wl = wl | 0x80000 | 0x20;
        SetWindowLong(this.Handle, -20, wl);

        InitializeComponent();

        //Makes the start location the same as parent.
        this.StartPosition = parentForm.StartPosition;

        parentForm.Activated += ParentForm_Activated; //Fires on parent activation to do a this.BringToFront() 
        this.Deactivate += This_Deactivated; //Toggles a boolean that ensures that ParentForm_Activated does fire when clicking through (this)
        parentForm.Closed += ParentForm_Closed; //Closes this when parent closes
        parentForm.Move += ParentForm_Move; //Follows movement of parent form

        //Draws border with standard bitmap modifications and merging
        /* Omitted function to avoid extra confusion */
        Bitmap getShadow = DrawBlurBorder(parentForm.ClientSize.Width, parentForm.ClientSize.Height);
        /* **This code was featured in the original post:** */
        SetBitmap(getShadow, 255); //Sets background as 32-bit image with full alpha.

        this.Location = Offset; //Set within DrawBlurBorder creates an offset 

    }
    private void ParentForm_Activated(object o, EventArgs e)
    {
        /* Sets this form on top when parent form is activated.*/
        if (isBringingToFront)
        { 
            /*Hopefully prevents recusion*/
            isBringingToFront = false;
            return;
        }

        this.BringToFront();


        /* Some special tweaks omitted to avoid confusion */
    }
    private void This_Deactivated(object o, EventArgs e)
    {
        /* Prevents recusion. */
        isBringingToFront = true;
    }
    /* Closes this when parent form closes. */
    private void ParentForm_Closed(object o, EventArgs e)
    {
        this.Close();
    }
    /* Adjust position when parent moves. */
    private void ParentForm_Move(object o, EventArgs e)
    {
        if(o is Form)
            this.Location = new Point((o as Form).Location.X + Offset.X, (o as Form).Location.Y + Offset.Y);
    }
 }
表单#2:这只是在启动时启动dropshadow表单,我还创建了一些接口以允许进一步的集成和灵活性,我省略了这些接口以避免额外的混乱。基本上是确保Dropshadow窗体不会从活动窗体中删除鼠标单击,并且如果Dropshadow窗体位于顶部,也不会强迫用户必须单击按钮两次的方法。

谢谢,Coryllu

一个可操作的类是

DrawShadow
创建了一个类似阴影的位图,但还不够完美。 这门课并不完美,但很有效

顺便说一句,我不知道如何在任务栏中隐藏阴影窗体。设置
ShowInTaskBar=false
将使表单消失

编辑

我重写了这个类,现在看起来像这样,一个真正的DropShadow

源是

你应该知道的是这个类不考虑<代码>边界半径< /代码>(取而代之的CSS)。

主要财产是

  • 阴影色
  • 沙多夫
  • 阴影
  • 阴影蔓延
  • 阴影模糊
该属性与css
框阴影相同,请参见

这些财产

  • 阴影蔓延
  • 阴影模糊
  • 阴影色
需要手动调用RefreshShadow()


转到

你的问题是什么?这里真的不是为你编写解决方案的地方。@Ramhound问题很简单。我希望能在这件事上找到正确的方向。我的问题经过充分研究,尽可能清楚。我只是想知道是否有人知道一种更好的方法来创建Windows 7风格的dropshadow。你能添加一个屏幕截图或所需结果的模型吗?@KevinMcCormick这是我所需的最终结果,但我发布了我是如何完成的。如果你有任何建议,欢迎。我不知道这是否是最好的方法,但我认为这很聪明。这是ShowInTaskbar问题的有趣之处。我似乎没有同样的问题。我会把我的代码挖出来,如果你愿意的话,把它寄给你。这是一个非常古老的代码,所以它没有经过精确的优化。我的版本涉及到更多的内容,我完全忘记了原因:P但下面是我为使代码正常工作所做的所有事情。有些可能是我想做的,但我主要是想把这些都去掉。我创建了一个新项目来测试dropshadow,发现
ShowInTaskBar
很好。现在,困难的部分是绘制阴影位图。我想使用描述的参数。我注意到您绘制阴影时使用的是图像,它是不可更改的。我更新了我的答案,实现了一个真正的DrowShadow。源代码是,我使用图像是因为我不想每次在一个应用程序上使用dropshadow时都增加不必要的处理能力,而这个应用程序将持续使用相同的dropshadow。然而,当我几年前第一次进入WinForms时,这是我自己使用的。我不再使用此代码,因为现在我主要使用WPF。不过,在推进我的原始代码方面做得很好。
public partial class Dropshadow : Form
{

    public Dropshadow(Form parentForm)
    {
        /*This bit of code makes the form click-through. 
          So you can click forms that are below it in z-space */
        int wl = GetWindowLong(this.Handle, -20);
        wl = wl | 0x80000 | 0x20;
        SetWindowLong(this.Handle, -20, wl);

        InitializeComponent();

        //Makes the start location the same as parent.
        this.StartPosition = parentForm.StartPosition;

        parentForm.Activated += ParentForm_Activated; //Fires on parent activation to do a this.BringToFront() 
        this.Deactivate += This_Deactivated; //Toggles a boolean that ensures that ParentForm_Activated does fire when clicking through (this)
        parentForm.Closed += ParentForm_Closed; //Closes this when parent closes
        parentForm.Move += ParentForm_Move; //Follows movement of parent form

        //Draws border with standard bitmap modifications and merging
        /* Omitted function to avoid extra confusion */
        Bitmap getShadow = DrawBlurBorder(parentForm.ClientSize.Width, parentForm.ClientSize.Height);
        /* **This code was featured in the original post:** */
        SetBitmap(getShadow, 255); //Sets background as 32-bit image with full alpha.

        this.Location = Offset; //Set within DrawBlurBorder creates an offset 

    }
    private void ParentForm_Activated(object o, EventArgs e)
    {
        /* Sets this form on top when parent form is activated.*/
        if (isBringingToFront)
        { 
            /*Hopefully prevents recusion*/
            isBringingToFront = false;
            return;
        }

        this.BringToFront();


        /* Some special tweaks omitted to avoid confusion */
    }
    private void This_Deactivated(object o, EventArgs e)
    {
        /* Prevents recusion. */
        isBringingToFront = true;
    }
    /* Closes this when parent form closes. */
    private void ParentForm_Closed(object o, EventArgs e)
    {
        this.Close();
    }
    /* Adjust position when parent moves. */
    private void ParentForm_Move(object o, EventArgs e)
    {
        if(o is Form)
            this.Location = new Point((o as Form).Location.X + Offset.X, (o as Form).Location.Y + Offset.Y);
    }
 }
var f = new Dropshadow(this)
{
    BorderRadius = 40,
    ShadowColor = Color.Blue
};

f.RefreshShadow();