表单的透明背景图像 - 表单的光滑边缘形状

11

当我尝试使用透明背景时,它并不完全透明。 我尝试了两个代码块来解决这个问题。 首先,我尝试了这段代码:

 public Form1()
    {
        InitializeComponent();
        SetStyle(ControlStyles.SupportsTransparentBackColor, true);
        this.BackColor = Color.Transparent;
        this.FormBorderStyle = FormBorderStyle.None;
        //this.WindowState = System.Windows.Forms.FormWindowState.Maximized;

    }

它看起来像这张图片:

在此输入图像描述

然后我找到了一些不同的代码并尝试了像这样的方式;

 public Form1()
    {
        InitializeComponent();
        this.TransparencyKey = Color.White;
        this.BackColor = Color.White;
        this.FormBorderStyle = FormBorderStyle.None;
        this.WindowState = System.Windows.Forms.FormWindowState.Maximized;

    }

这看起来像这张图片:

enter image description here

您可以看到带有白色边框的徽标。我想完全透明地显示仅 .png 徽标。我应该怎么做?如何做到这一点?

以下是我的 .png 徽标图像:

enter image description here


那是什么图片?是背景图吗? - Reza Aghaei
这是PictureBox的背景图像。实际上我想在程序启动前制作一个欢迎消息... - CoderWho
你能分享那张图片吗? - Reza Aghaei
@RezaAghaei 我在我的问题末尾添加了logo.png。 - CoderWho
该项目演示了如何设计一个具有透明Alpha位图的窗口:https://www.codeproject.com/Articles/19213/An-Alpha-Channel-Composited-Windows-Form-with-Desi - Elmue
2个回答

20
您可以使用分层窗口(Layered Windows)

对于具有复杂形状、动态形状或希望使用 alpha 混合效果的窗口,使用分层窗口可以显著提高性能和视觉效果。系统会自动组合和重绘分层窗口及其底层应用程序的窗口。因此,分层窗口可以平滑地呈现,而不会出现典型的复杂窗口区域闪烁。此外,分层窗口可以部分透明,即 alpha 混合。

在 Windows Forms 中创建分层窗口 以下是来自msdn 代码库的一些代码,演示如何在 Windows Forms 中创建分层窗口。它允许您创建一个有形状的启动屏幕,并通过鼠标移动它。
PerPixelAlphaForm 添加到项目中,然后只需从该表单进行继承并调用其 SelectBitmap 方法,并将您的 png 传递给该方法以创建分层窗口。 enter image description here PerPixelAlphaForm.cs
#region Using directives
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
#endregion
namespace CSWinFormLayeredWindow
{
    public partial class PerPixelAlphaForm : Form
    {
        public PerPixelAlphaForm()
        {
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            this.ShowInTaskbar = false;
            this.StartPosition = FormStartPosition.CenterScreen;
            this.Load += PerPixelAlphaForm_Load;
        }

        void PerPixelAlphaForm_Load(object sender, EventArgs e)
        {
            this.TopMost = true;
        }
        protected override CreateParams CreateParams
        {
            get
            {
                // Add the layered extended style (WS_EX_LAYERED) to this window.
                CreateParams createParams = base.CreateParams;
                if(!DesignMode)
                    createParams.ExStyle |= WS_EX_LAYERED;
                return createParams;
            }
        }
        /// <summary>
        /// Let Windows drag this window for us (thinks its hitting the title 
        /// bar of the window)
        /// </summary>
        /// <param name="message"></param>
        protected override void WndProc(ref Message message)
        {
            if (message.Msg == WM_NCHITTEST)
            {
                // Tell Windows that the user is on the title bar (caption)
                message.Result = (IntPtr)HTCAPTION;
            }
            else
            {
                base.WndProc(ref message);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="bitmap"></param>
        public void SelectBitmap(Bitmap bitmap)
        {
            SelectBitmap(bitmap, 255);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="bitmap">
        /// 
        /// </param>
        /// <param name="opacity">
        /// Specifies an alpha transparency value to be used on the entire source 
        /// bitmap. The SourceConstantAlpha value is combined with any per-pixel 
        /// alpha values in the source bitmap. The value ranges from 0 to 255. If 
        /// you set SourceConstantAlpha to 0, it is assumed that your image is 
        /// transparent. When you only want to use per-pixel alpha values, set 
        /// the SourceConstantAlpha value to 255 (opaque).
        /// </param>
        public void SelectBitmap(Bitmap bitmap, int opacity)
        {
            // Does this bitmap contain an alpha channel?
            if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
            {
                throw new ApplicationException("The bitmap must be 32bpp with alpha-channel.");
            }

            // Get device contexts
            IntPtr screenDc = GetDC(IntPtr.Zero);
            IntPtr memDc = CreateCompatibleDC(screenDc);
            IntPtr hBitmap = IntPtr.Zero;
            IntPtr hOldBitmap = IntPtr.Zero;

            try
            {
                // Get handle to the new bitmap and select it into the current 
                // device context.
                hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));
                hOldBitmap = SelectObject(memDc, hBitmap);

                // Set parameters for layered window update.
                Size newSize = new Size(bitmap.Width, bitmap.Height);
                Point sourceLocation = new Point(0, 0);
                Point newLocation = new Point(this.Left, this.Top);
                BLENDFUNCTION blend = new BLENDFUNCTION();
                blend.BlendOp = AC_SRC_OVER;
                blend.BlendFlags = 0;
                blend.SourceConstantAlpha = (byte)opacity;
                blend.AlphaFormat = AC_SRC_ALPHA;

                // Update the window.
                UpdateLayeredWindow(
                    this.Handle,     // Handle to the layered window
                    screenDc,        // Handle to the screen DC
                    ref newLocation, // New screen position of the layered window
                    ref newSize,     // New size of the layered window
                    memDc,           // Handle to the layered window surface DC
                    ref sourceLocation, // Location of the layer in the DC
                    0,               // Color key of the layered window
                    ref blend,       // Transparency of the layered window
                    ULW_ALPHA        // Use blend as the blend function
                    );
            }
            finally
            {
                // Release device context.
                ReleaseDC(IntPtr.Zero, screenDc);
                if (hBitmap != IntPtr.Zero)
                {
                    SelectObject(memDc, hOldBitmap);
                    DeleteObject(hBitmap);
                }
                DeleteDC(memDc);
            }
        }
        #region Native Methods and Structures

        const Int32 WS_EX_LAYERED = 0x80000;
        const Int32 HTCAPTION = 0x02;
        const Int32 WM_NCHITTEST = 0x84;
        const Int32 ULW_ALPHA = 0x02;
        const byte AC_SRC_OVER = 0x00;
        const byte AC_SRC_ALPHA = 0x01;

        [StructLayout(LayoutKind.Sequential)]
        struct Point
        {
            public Int32 x;
            public Int32 y;

            public Point(Int32 x, Int32 y)
            { this.x = x; this.y = y; }
        }

        [StructLayout(LayoutKind.Sequential)]
        struct Size
        {
            public Int32 cx;
            public Int32 cy;

            public Size(Int32 cx, Int32 cy)
            { this.cx = cx; this.cy = cy; }
        }

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct ARGB
        {
            public byte Blue;
            public byte Green;
            public byte Red;
            public byte Alpha;
        }

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct BLENDFUNCTION
        {
            public byte BlendOp;
            public byte BlendFlags;
            public byte SourceConstantAlpha;
            public byte AlphaFormat;
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst,
            ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc,
            Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);

        [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern IntPtr CreateCompatibleDC(IntPtr hDC);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern IntPtr GetDC(IntPtr hWnd);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

        [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool DeleteDC(IntPtr hdc);

        [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);

        [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool DeleteObject(IntPtr hObject);

        #endregion
    }
}

SplashScreen.cs

public partial class Form4 : CSWinFormLayeredWindow.PerPixelAlphaForm
{
    public Form4()
    {
        InitializeComponent();
        this.SelectBitmap(Properties.Resources.splash);
    }
}

注意

原始答案基于关闭双缓冲并覆盖OnPaintBackground,在不调用基本方法的情况下绘制图像。该答案存在已知问题;当窗体静止时它能正常工作,但如果窗体移动或窗口背景改变,则窗口不会更新。您可以在修订版本中查看以前的代码。当前编辑完全基于MSDN代码,没有任何已知问题。


但有一个问题 :S 当我尝试这个时。它显示像这样: http://i66.tinypic.com/9knl9d.png - CoderWho
根据图片显示,您在SetStyle之后执行了InitializeComponent();。您应该在InitializeComponent();之后执行SetStyle - Reza Aghaei
非常感谢。我在您上传的图片中看到它正在工作。你是对的,这就是我的解决方案。再次感谢。 - CoderWho
1
不,这是窗体的背景图片。并没有PictureBox。我想我应该这样回答。 - Reza Aghaei
据我所记,此情况下该窗体无法显示控件。 - Reza Aghaei
显示剩余10条评论

0

您可以通过更改介于0和255之间的alpha系数来选择图像的透明度级别。一张图片也可以是背景图片,没有问题。

private static Image ToGrayscale(Image s,int alpha)
        {
            Bitmap tImage = new Bitmap(s);

            for (int x = 0; x < tImage.Width; x++)
            {
                for (int y = 0; y < tImage.Height; y++)
                {
                    Color tCol = tImage.GetPixel(x, y);
                    Color newColor = Color.FromArgb(alpha, tCol.R, tCol.G, tCol.B);
                  tImage.SetPixel(x, y, newColor);
                }
            }
            return tImage;

        }

2
这并没有回答问题。你的函数名称已经是错误的了。 - Elmue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接