C#中部分透明的闪屏

时间:2014-12-30 16:34:40

标签: c# winforms

我试图为我的应用程序制作启动画面。我有一个.PNG图像,它有一些部分透明的部分。

我已将该表单设为无边框并禁用了控件箱。但是,背景颜色会导致问题。

首先,我将图像放在图片框中。然后我以这种方式使表单背景透明:

this.BackColor = Color.Magenta;
this.TransparencyKey = Color.Magenta;

它有点奏效。屏幕的完全透明部分是透明的,但在部分透明的部分可以看到洋红色。

然后我尝试将图像作为表单的背景图像。我尝试使用此代码使表单的背景透明:

private void Form1_Load(object sender, EventArgs e)
{
   this.SetStyle(System.Windows.Forms.ControlStyles.SupportsTransparentBackColor, true);
   this.BackColor = System.Drawing.Color.Transparent;
}

它也没有用。背景仍然不透明。 我该怎么办?

3 个答案:

答案 0 :(得分:3)

为什么是洋红色?尝试使用白色。我将背面颜色设置为白色,透明度设置为白色。在下图中,带有图片的随机框是我的飞溅。

Results

答案 1 :(得分:2)

TransparencyKey会将表单设置为完全不透明,但指定的确切颜色的像素除外。 AFAIK它通过实际定义基于匹配颜色的像素的WindowRegion窗口形状来实现这一点 - 这些像素不再是窗口的一部分,可以点击。

听起来你的PNG有一个alpha层,即透明度等级0..255,它们混合在你的背景色(洋红色)上,之后只有纯品红色像素变得透明。

你可以尝试:

  • 选择一种颜色,例如Magenta未在您的启动画中使用,并将其放在您的启动画面PNG中代替完全透明区域作为不透明像素
  • 在显示之前在您的窗口下捕获桌面位图的副本,然后将其放在PictureBox下。

然后,飞溅的部分透明区域会与背景图像混合,完全透明的区域将与TransparencyKey匹配并且是透明的。

但是如果桌面的其他部分在启动时显示,如果你的启动画面移动等,那么你将获得视觉假象。

编辑:似乎有一个更简单的解决方案here而不使用TransparencyKey

答案 2 :(得分:1)

您可以使用layered windowsUpdateLayeredWindow() Api:

来完成此操作
protected override CreateParams CreateParams
{
    get
    {
        // Add the layered extended style (WS_EX_LAYERED) to this window
        CreateParams createParam = base.CreateParams;
        createParam.ExStyle = (createParam.ExStyle | APIHelp.WS_EX_LAYERED);
        return createParam;
    }
}

以您的格式load event

IntPtr memDc, hBmp, hOldBmp;

private void Form1_Load(object sender, EventArgs e)
{
    APIHelp.BLENDFUNCTION blend;

    //Only works with a 32bpp bitmap
    blend.BlendOp = APIHelp.AC_SRC_OVER;
    //Always 0
    blend.BlendFlags = 0;
    //Set to 255 for per-pixel alpha values
    blend.SourceConstantAlpha = 255;
    //Only works when the bitmap contains an alpha channel
    blend.AlphaFormat = APIHelp.AC_SRC_ALPHA;

    IntPtr screenDc;

    screenDc = APIHelp.GetDC(IntPtr.Zero);

    Bitmap bmp;

    using (bmp = (Bitmap)Bitmap.FromFile(@"C:\.......png")) //the image must be the same size as your form
    {
        memDc = APIHelp.CreateCompatibleDC(screenDc);
        hBmp = bmp.GetHbitmap(Color.FromArgb(0));
        hOldBmp = APIHelp.SelectObject(memDc, hBmp); //memDc is a device context that contains our image
    }

    APIHelp.DeleteDC(screenDc);

    APIHelp.Size newSize;
    APIHelp.Point newLocation;
    APIHelp.Point sourceLocation;

    newLocation.x = this.Location.X;
    newLocation.y = this.Location.Y;

    sourceLocation.x = 0;
    sourceLocation.y = 0;

    newSize.cx = this.Width;
    newSize.cy = this.Height;

    APIHelp.UpdateLayeredWindow(Handle, IntPtr.Zero, ref newLocation, ref newSize, memDc, ref sourceLocation, 
           0, ref blend, APIHelp.ULW_ALPHA);
}

Class APIHelp:

class APIHelp
{
    public const Int32 WS_EX_LAYERED = 524288;
    public const Int32 ULW_ALPHA = 2;
    public const byte AC_SRC_OVER = 0;
    public const byte AC_SRC_ALPHA = 1;

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

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

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

    [StructLayout(LayoutKind.Sequential)]
    public struct BLENDFUNCTION
    {
        public Byte BlendOp;
        public Byte BlendFlags;
        public Byte SourceConstantAlpha;
        public Byte AlphaFormat;
    }

    [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
    public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst,
       ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pptSrc, uint crKey,
       [In] ref BLENDFUNCTION pblend, uint dwFlags);


    [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleDC", SetLastError = true)]
    public static extern IntPtr CreateCompatibleDC([In] IntPtr hdc);

    [DllImport("gdi32.dll", EntryPoint = "SelectObject")]
    public static extern IntPtr SelectObject([In] IntPtr hdc, [In] IntPtr hgdiobj);

    [DllImport("user32.dll")]
    public static extern IntPtr GetDC(IntPtr hWnd);

    [DllImport("gdi32.dll", EntryPoint = "DeleteDC")]
    public static extern bool DeleteDC([In] IntPtr hdc);

    [DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool DeleteObject([In] IntPtr hObject);
}

当表单关闭时释放资源:

APIHelp.SelectObject(memDc, hOldBmp);
APIHelp.DeleteObject(hBmp);
APIHelp.DeleteDC(memDc);
相关问题