C# dialog form with blur background

后端 未结 2 1244
醉酒成梦
醉酒成梦 2021-02-09 03:03

Good afternoon,

Just a simple question. Is it possible to make a parent form blurry while you show a new dialog form in winforms? if it\'s not possible by default, are t

2条回答
  •  独厮守ぢ
    2021-02-09 03:09

    I didn't think this was possible but I found a similar question here: Layer effects (blur, etc.) in WinForms

    The code is from an answer over there but I've changed it slightly... You'll need to compile with the unsafe on (see build tab of your project's properties (Allow unsafe code)).

    Basicly you put everything in your form in a panel (called panel1 in the code) and call the blur function. I also added an unblur function to go back to normal:

    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            private PictureBox pb;
    
            public Form1()
            {
                InitializeComponent();
    
                pb = new PictureBox();
                panel1.Controls.Add(pb);
                pb.Dock = DockStyle.Fill;
            }
    
            private void Blur()
            {
                Bitmap bmp = Screenshot.TakeSnapshot(panel1);
                BitmapFilter.GaussianBlur(bmp, 4);
    
                pb.Image = bmp;
                pb.BringToFront();
            }
    
            private void UnBlur()
            {
                pb.Image = null;
                pb.SendToBack();
            }
        }
    
        public class BitmapFilter
        {
            private static bool Conv3x3(Bitmap b, ConvMatrix m)
            {
                // Avoid divide by zero errors
                if (0 == m.Factor) return false;
    
                Bitmap bSrc = (Bitmap)b.Clone();
    
                // GDI+ still lies to us - the return format is BGR, NOT RGB.
                BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
                BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
    
                int stride = bmData.Stride;
                int stride2 = stride * 2;
                System.IntPtr Scan0 = bmData.Scan0;
                System.IntPtr SrcScan0 = bmSrc.Scan0;
    
                unsafe
                {
                    byte* p = (byte*)(void*)Scan0;
                    byte* pSrc = (byte*)(void*)SrcScan0;
    
                    int nOffset = stride + 6 - b.Width * 3;
                    int nWidth = b.Width - 2;
                    int nHeight = b.Height - 2;
    
                    int nPixel;
    
                    for (int y = 0; y < nHeight; ++y)
                    {
                        for (int x = 0; x < nWidth; ++x)
                        {
                            nPixel = ((((pSrc[2] * m.TopLeft) + (pSrc[5] * m.TopMid) + (pSrc[8] * m.TopRight) +
                                (pSrc[2 + stride] * m.MidLeft) + (pSrc[5 + stride] * m.Pixel) + (pSrc[8 + stride] * m.MidRight) +
                                (pSrc[2 + stride2] * m.BottomLeft) + (pSrc[5 + stride2] * m.BottomMid) + (pSrc[8 + stride2] * m.BottomRight)) / m.Factor) + m.Offset);
    
                            if (nPixel < 0) nPixel = 0;
                            if (nPixel > 255) nPixel = 255;
    
                            p[5 + stride] = (byte)nPixel;
    
                            nPixel = ((((pSrc[1] * m.TopLeft) + (pSrc[4] * m.TopMid) + (pSrc[7] * m.TopRight) +
                                (pSrc[1 + stride] * m.MidLeft) + (pSrc[4 + stride] * m.Pixel) + (pSrc[7 + stride] * m.MidRight) +
                                (pSrc[1 + stride2] * m.BottomLeft) + (pSrc[4 + stride2] * m.BottomMid) + (pSrc[7 + stride2] * m.BottomRight)) / m.Factor) + m.Offset);
    
                            if (nPixel < 0) nPixel = 0;
                            if (nPixel > 255) nPixel = 255;
    
                            p[4 + stride] = (byte)nPixel;
    
                            nPixel = ((((pSrc[0] * m.TopLeft) + (pSrc[3] * m.TopMid) + (pSrc[6] * m.TopRight) +
                                (pSrc[0 + stride] * m.MidLeft) + (pSrc[3 + stride] * m.Pixel) + (pSrc[6 + stride] * m.MidRight) +
                                (pSrc[0 + stride2] * m.BottomLeft) + (pSrc[3 + stride2] * m.BottomMid) + (pSrc[6 + stride2] * m.BottomRight)) / m.Factor) + m.Offset);
    
                            if (nPixel < 0) nPixel = 0;
                            if (nPixel > 255) nPixel = 255;
    
                            p[3 + stride] = (byte)nPixel;
    
                            p += 3;
                            pSrc += 3;
                        }
    
                        p += nOffset;
                        pSrc += nOffset;
                    }
                }
    
                b.UnlockBits(bmData);
                bSrc.UnlockBits(bmSrc);
    
                return true;
            }
    
            public static bool GaussianBlur(Bitmap b, int nWeight /* default to 4*/)
            {
                ConvMatrix m = new ConvMatrix();
                m.SetAll(1);
                m.Pixel = nWeight;
                m.TopMid = m.MidLeft = m.MidRight = m.BottomMid = 2;
                m.Factor = nWeight + 12;
    
                return BitmapFilter.Conv3x3(b, m);
            }
    
            public class ConvMatrix
            {
                public int TopLeft = 0, TopMid = 0, TopRight = 0;
                public int MidLeft = 0, Pixel = 1, MidRight = 0;
                public int BottomLeft = 0, BottomMid = 0, BottomRight = 0;
                public int Factor = 1;
                public int Offset = 0;
                public void SetAll(int nVal)
                {
                    TopLeft = TopMid = TopRight = MidLeft = Pixel = MidRight = BottomLeft = BottomMid = BottomRight = nVal;
                }
            }
        }
    
        class Screenshot
        {
            public static Bitmap TakeSnapshot(Control ctl) 
            { 
                Bitmap bmp = new Bitmap(ctl.Size.Width, ctl.Size.Height);
                System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmp); 
                g.CopyFromScreen(ctl.PointToScreen(ctl.ClientRectangle.Location), new Point(0, 0), ctl.ClientRectangle.Size); 
                return bmp; 
            }
        }
    }
    

提交回复
热议问题