Windows 7的风格阴影效果无边距形式 [英] Windows 7 style Dropshadow in borderless form

查看:314
本文介绍了Windows 7的风格阴影效果无边距形式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

短版本:

Short Version:

目标:深,暗,Windows 7的阴影效果在无国界的WinForm在C#

Goal: A deep, dark, Windows 7 dropshadow in borderless WinForm in C#

已知现有解决方案1:简单阴影效果使用的CreateParams XP风格

Known existing solutions 1: Simple XP-style dropshadow using CreateParams.

问题::要弱,光,以难看

已知的现有解决方案2:替换位图形式的GDI

Known existing solutions 2: Replace GDI of form with bitmap.

问题:减肥使用的控制,唯一的功能作为启动画面的能力。

Problem: Lose the ability to use controls, only functional as a splash screen.

目标通过这篇文章:查找位数解决这个问题或者一起更好的。

Objective by this post: Find a median solution to this problem or an all together better one.



. . .

龙版本:

Long Version:

(编辑:我指的是下拉阴影以及任何Windows窗体的边界去,如果不清楚)
我明白,有一种方法使用,使在C#中的XP风格阴影效果的:

( I am referring to the drop-shadow going along the border of any windows form, if that wasn't clear.) I understand that there is a way to make XP style dropshadows in C# using:

C#代码1 - 简单的XP风格的阴影效果(问题:要轻,弱,丑)

// Define the CS_DROPSHADOW constant
private const int CS_DROPSHADOW = 0x00020000;

// Override the CreateParams property
protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        cp.ClassStyle |= CS_DROPSHADOW;
        return cp;
    }
}



不过,我试图找出如何使他们看起来像在Windows 7(更深和更大的阴影)DO和想不通这样做的最佳方式。

However, I am trying to figure out how to make them appear like the do in Windows 7 (deeper and larger shadows) and can't figure out the best way of doing this.

我有一个方法,现在创建,将让我重写整个窗体GDI和看起来像一个闪屏会(信用不是我的):

I have a method now created that will let me override the entire form GDI and appear like a splash screen would (credit not mine):

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位背景(因为我需要对手动添加阴影效果),但我失去了创造可见的表单元素的能力。

However, this does give me a full 32-bit background (as I require to add the dropshadow manually), but I lose the ability to create form elements that are visible.

所以基本上,我试图找出这两种方法之间的中位数。一些能够给我留下很深的暗阴影,而不会丢失等功能/引起过度重绘要求。

So basically, I am trying to figure out a median between these two methods. Something that will give me deep and dark drop shadows without losing other functionality / causing excessive repainting requirements.

推荐答案

好了,所以后约4小时的头脑风暴和编码,我终于开发的解决方案。基本上,我做了2种形式。

Okay, so after about 4 hours of brainstorming and coding, I have finally developed a solution. Basically, I made 2 forms.

表格#1 :创建通过修改和组合8图像(4个角梯度+ 4线性渐变为每个方向)的阴影效果,并设置其由于使用第二个代码我上面贴的背景下( C#代码2:替换形式GDI与位图)。 。代码几乎解释了它

Form #1: Create the dropshadow by modifying and combining 8 images (4 corners gradients + 4 linear gradients for each direction) and set them as a background using the second code I posted above (C# Code 2: Replace form GDI with Bitmap). Code pretty much explains it.

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形式是在上面。

Form #2: This just launches the dropshadow form at launch and I also created some interfaces to allow further integration and flexibility that I omitted to avoid extra confusion. Basically methods to ensure that the Dropshadow form was not taking away mouse clicks from the active form and wouldn't force the user to have to click a button twice if the Dropshadow form was on top.

这篇关于Windows 7的风格阴影效果无边距形式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆