窗体的透明背景图像 - 窗体的平滑边缘形状
Transparent background image for Form - Smooth edge shape for the Form
当我尝试使用透明背景时,它不是完全透明的。
我为这个问题尝试了两个代码块。首先我试过这样的代码:
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;
}
这看起来像这张照片;
您可以看到带有白色边框的徽标。我只想显示完全透明的 .png 徽标。我应该怎么办?怎么做到的?
这是我的徽标图片,格式为 .png;
您可以使用 Layered Windows:
Using a layered window can significantly improve performance and
visual effects for a window that has a complex shape, animates its
shape, or wishes to use alpha blending effects. The system
automatically composes and repaints layered windows and the windows of
underlying applications. As a result, layered windows are rendered
smoothly, without the flickering typical of complex window regions. In
addition, layered windows can be partially translucent, that is,
alpha-blended.
在 Windows 表单中创建分层 window
这是来自 msdn code gallery 的一些代码,它演示了如何在 Windows 表单中创建分层 Windows。它允许您创建一个形状的初始屏幕,并让您通过鼠标移动它。
将 PerPixelAlphaForm
添加到项目中,然后从该表单继承并调用其 SelectBitmap
并将您的 png 传递给创建分层 window 的方法就足够了。
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
并在不调用基本方法的情况下绘制图像。答案有一个已知问题;虽然表格是不动的,但它运行良好,但如果表格正在移动或表格后面的 window 被更改,则 window 不会更新。您可以在修订版中查看以前的代码。当前完全基于 MSDN 代码的编辑没有任何已知问题。
您可以通过更改介于 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;
}
当我尝试使用透明背景时,它不是完全透明的。 我为这个问题尝试了两个代码块。首先我试过这样的代码:
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;
}
这看起来像这张照片;
您可以看到带有白色边框的徽标。我只想显示完全透明的 .png 徽标。我应该怎么办?怎么做到的?
这是我的徽标图片,格式为 .png;
您可以使用 Layered Windows:
Using a layered window can significantly improve performance and visual effects for a window that has a complex shape, animates its shape, or wishes to use alpha blending effects. The system automatically composes and repaints layered windows and the windows of underlying applications. As a result, layered windows are rendered smoothly, without the flickering typical of complex window regions. In addition, layered windows can be partially translucent, that is, alpha-blended.
在 Windows 表单中创建分层 window
这是来自 msdn code gallery 的一些代码,它演示了如何在 Windows 表单中创建分层 Windows。它允许您创建一个形状的初始屏幕,并让您通过鼠标移动它。
将 PerPixelAlphaForm
添加到项目中,然后从该表单继承并调用其 SelectBitmap
并将您的 png 传递给创建分层 window 的方法就足够了。
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
并在不调用基本方法的情况下绘制图像。答案有一个已知问题;虽然表格是不动的,但它运行良好,但如果表格正在移动或表格后面的 window 被更改,则 window 不会更新。您可以在修订版中查看以前的代码。当前完全基于 MSDN 代码的编辑没有任何已知问题。
您可以通过更改介于 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;
}