c# winform 透明窗口PNG 锯齿毛边 解决方案
本文关键字: c#, winform, 毛边, 透明, 锯齿问题说明: 普通应用下,设置背景透明可实现透明窗口,如果PNG为方形 不会有锯齿和毛边的情形;但是如果透明背景为圆形,则可能会出现 锯齿毛边的情况(和PNG图片的导入像素无关)。
解决方法:
- 皮肤窗口类
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace WindowsFormsApp1
{
public partial class Skin : Form
{
public FormShow show;
public Skin(FormShow show)
{
InitializeComponent();
this.show = show;
this.BackgroundImage = WindowsFormsApp3.Properties.Resource1.log_bg;//将背景图应用到皮肤层
this.BackgroundImageLayout = ImageLayout.Stretch;//自动拉伸背景图以适应窗口
this.Size = show.Size;//统一大小
show.Owner = this;//设置控件层的拥有皮肤层Location = new Point(show.Location.X, show.Location.Y);//统一控件层和皮肤层的位置
}private void Form1_Load(object sender, EventArgs e)
{
FormBorderStyle = FormBorderStyle.None;//取消窗口边框
SetBits(new Bitmap(BackgroundImage, new Size(135, 70)));//设置不规则窗体
FormMovableEvent();
}
bool haveHandle = false;//窗体句柄创建完成
private void InitializeStyles()
{
SetStyle(
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.ResizeRedraw |
ControlStyles.SupportsTransparentBackColor, true);
SetStyle(ControlStyles.Selectable, false);
UpdateStyles();
}protected override void OnHandleCreated(EventArgs e)
{
InitializeStyles();//设置窗口样式、双缓冲等
base.OnHandleCreated(e);
haveHandle = true;
}
protected override CreateParams CreateParams
{
get
{
CreateParams cParms = base.CreateParams;
cParms.ExStyle |= 0x00080000; // WS_EX_LAYERED
return cParms;
}
}
public void SetBits(Bitmap bitmap)
{
if (!haveHandle) return;if (!Bitmap.IsCanonicalPixelFormat(bitmap.PixelFormat) || !Bitmap.IsAlphaPixelFormat(bitmap.PixelFormat))
throw new ApplicationException(“The picture must be 32bit picture with alpha channel.”);IntPtr oldBits = IntPtr.Zero;
IntPtr screenDC = Win32.GetDC(IntPtr.Zero);
IntPtr hBitmap = IntPtr.Zero;
IntPtr memDc = Win32.CreateCompatibleDC(screenDC);try
{
Win32.Point topLoc = new Win32.Point(Left, Top);
Win32.Size bitMapSize = new Win32.Size(bitmap.Width, bitmap.Height);
Win32.BLENDFUNCTION blendFunc = new Win32.BLENDFUNCTION();
Win32.Point srcLoc = new Win32.Point(0, 0);hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));
oldBits = Win32.SelectObject(memDc, hBitmap);blendFunc.BlendOp = Win32.AC_SRC_OVER;
blendFunc.SourceConstantAlpha = 255;//这里设置窗体绘制的透明度
blendFunc.AlphaFormat = Win32.AC_SRC_ALPHA;
blendFunc.BlendFlags = 0;Win32.UpdateLayeredWindow(Handle, screenDC, ref topLoc, ref bitMapSize, memDc, ref srcLoc, 0, ref blendFunc, Win32.ULW_ALPHA);
}
finally
{
if (hBitmap != IntPtr.Zero)
{
Win32.SelectObject(memDc, oldBits);
Win32.DeleteObject(hBitmap);
}
Win32.ReleaseDC(IntPtr.Zero, screenDC);
Win32.DeleteDC(memDc);
}
}private Point mouseOffset; //记录鼠标指针的坐标
private bool isMouseDown = false; //记录鼠标按键是否按下/// <summary>
/// 窗体移动监听绑定
/// </summary>
private void FormMovableEvent()
{
//窗体移动
this.MouseDown += new MouseEventHandler(Frm_MouseDown);
this.MouseMove += new MouseEventHandler(Frm_MouseMove);
this.MouseUp += new MouseEventHandler(Frm_MouseUp);
}/// <summary>
/// 窗体按下时
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void Frm_MouseDown(object sender, MouseEventArgs e)
{
int xOffset;
int yOffset;
//点击窗体时,记录鼠标位置,启动移动
if (e.Button == MouseButtons.Left)
{
xOffset = -e.X;
yOffset = -e.Y;
mouseOffset = new Point(xOffset, yOffset);
isMouseDown = true;
}
}/// <summary>
/// 窗体移动时
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void Frm_MouseMove(object sender, MouseEventArgs e)
{
if (isMouseDown)
{
//移动的位置计算
Point mousePos = Control.MousePosition;
mousePos.Offset(mouseOffset.X, mouseOffset.Y);
Location = mousePos;
}
}/// <summary>
/// 窗体按下并释放按钮时
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void Frm_MouseUp(object sender, MouseEventArgs e)
{
// 修改鼠标状态isMouseDown的值
// 确保只有鼠标左键按下并移动时,才移动窗体
if (e.Button == MouseButtons.Left)
{
//松开鼠标时,停止移动
isMouseDown = false;
//Top高度小于0的时候,等于0
if (this.Top < 0)
{
this.Top = 0;
}
}
}private void Skin_Move(object sender, EventArgs e)
{
show.Location = new Point(Location.X, Location.Y);//统一控件层和皮肤层的位置
}
}
} - 主窗口 添加内容文字等
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace WindowsFormsApp1
{
public partial class FormShow : Form
{
public Skin Skin;
public FormShow()
{
InitializeComponent();}
private void FormShow_Load(object sender, EventArgs e)
{
if (!DesignMode)
{Skin = new Skin(this);//创建皮肤层
this.BackgroundImage = null;//去除控件层背景
TransparencyKey = BackColor;//使控件层背景透明
this.ShowInTaskbar = false;
Skin.Show();//显示皮肤层
}
}}
} - WIN32API
using System;
using System.Runtime.InteropServices;/// <summary>
/// Wind32API
/// </summary>
internal class Win32
{
#region 消息
public const int MF_REMOVE = 0x1000;public const int SC_RESTORE = 0xF120; //还原
public const int SC_MOVE = 0xF010; //移动
public const int SC_SIZE = 0xF000; //大小
public const int SC_MINIMIZE = 0xF020; //最小化
public const int SC_MAXIMIZE = 0xF030; //最大化
public const int SC_CLOSE = 0xF060; //关闭public const int WM_SYSCOMMAND = 0x0112;
public const int WM_COMMAND = 0x0111;public const int GW_HWNDFIRST = 0;
public const int GW_HWNDLAST = 1;
public const int GW_HWNDNEXT = 2;
public const int GW_HWNDPREV = 3;
public const int GW_OWNER = 4;
public const int GW_CHILD = 5;public const int WM_NCCALCSIZE = 0x83;
public const int WM_WINDOWPOSCHANGING = 0x46;
public const int WM_PAINT = 0xF;
public const int WM_CREATE = 0x1;
public const int WM_NCCREATE = 0x81;
public const int WM_NCPAINT = 0x85;
public const int WM_PRINT = 0x317;
public const int WM_DESTROY = 0x2;
public const int WM_SHOWWINDOW = 0x18;
public const int WM_SHARED_MENU = 0x1E2;
public const int HC_ACTION = 0;
public const int WH_CALLWNDPROC = 4;
public const int GWL_WNDPROC = -4;public const int WS_SYSMENU = 0x80000;
public const int WS_SIZEBOX = 0x40000;public const int WS_MAXIMIZEBOX = 0x10000;
public const int WS_MINIMIZEBOX = 0x20000;
#endregion
[StructLayout(LayoutKind.Sequential)]
public struct Size
{
public Int32 cx;
public Int32 cy;public Size(Int32 x, Int32 y)
{
cx = x;
cy = y;
}
}[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}[StructLayout(LayoutKind.Sequential)]
public struct Point
{
public Int32 x;
public Int32 y;public Point(Int32 x, Int32 y)
{
this.x = x;
this.y = y;
}
}public const byte AC_SRC_OVER = 0;
public const Int32 ULW_ALPHA = 2;
public const byte AC_SRC_ALPHA = 1;[DllImport(“gdi32.dll”, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);[DllImport(“user32.dll”, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetDC(IntPtr hWnd);[DllImport(“gdi32.dll”, ExactSpelling = true)]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObj);[DllImport(“user32.dll”, ExactSpelling = true)]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);[DllImport(“gdi32.dll”, ExactSpelling = true, SetLastError = true)]
public static extern int DeleteDC(IntPtr hDC);[DllImport(“gdi32.dll”, ExactSpelling = true, SetLastError = true)]
public static extern int DeleteObject(IntPtr hObj);[DllImport(“user32.dll”, ExactSpelling = true, SetLastError = true)]
public static extern int UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pptSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);[DllImport(“gdi32.dll”, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr ExtCreateRegion(IntPtr lpXform, uint nCount, IntPtr rgnData);[DllImport(“user32”)]
public static extern int SendMessage(IntPtr hwnd, int msg, int wp, int lp);
}
引用来源:https://download.csdn.net/download/gaocongdehao/10368078