C# WinForm窗体四周阴影效果

一、起因

关于winform窗体无边框的问题很简单,只需要设置winform的窗体属性即可:

FormBorderStyle = FormBorderStyle.None;

但是这中无边框窗口实现的效果和背景完全没有层次的感觉,所以能加上阴影,突出窗口显示的感觉。

二、网上搜索的解决方案

方法 1

首先,发现了使用 user32.dll 中方法实现的方案:
C# WinForm无边框窗体设置阴影效果

缺点:这种方法只能实现右边和下边的阴影效果,效果不是很好。

效果如图:
方法一效果图

方法 2

然后发现了使用双层窗体,底层窗体贴阴影的PNG来实现的方式:
教你实现Winform窗体的四边阴影效果

缺点:PNG格式特点是,支持alpha通道半透明,但是放大会失真

效果如图:
方法二效果图

三、最终解决方案

我使用的方法是绘制阴影到bitmap上,然后使用双层窗体的原理把bitmap绘制到背景层上去。

其中比较重要的是:

1、绘制圆角矩形

public static void DrawRoundRectangle(Graphics g, Pen pen, Rectangle rect, int cornerRadius)
{using (GraphicsPath path = CreateRoundedRectanglePath(rect, cornerRadius)){g.DrawPath(pen, path);}
}
public static void FillRoundRectangle(Graphics g, Brush brush, Rectangle rect, int cornerRadius)
{using (GraphicsPath path = CreateRoundedRectanglePath(rect, cornerRadius)){g.FillPath(brush, path);}
}
internal static GraphicsPath CreateRoundedRectanglePath(Rectangle rect, int cornerRadius)
{GraphicsPath roundedRect = new GraphicsPath();roundedRect.AddArc(rect.X, rect.Y, cornerRadius * 2, cornerRadius * 2, 180, 90);roundedRect.AddLine(rect.X + cornerRadius, rect.Y, rect.Right - cornerRadius * 2, rect.Y);roundedRect.AddArc(rect.X + rect.Width - cornerRadius * 2, rect.Y, cornerRadius * 2, cornerRadius * 2, 270, 90);roundedRect.AddLine(rect.Right, rect.Y + cornerRadius * 2, rect.Right, rect.Y + rect.Height - cornerRadius * 2);roundedRect.AddArc(rect.X + rect.Width - cornerRadius * 2, rect.Y + rect.Height - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 0, 90);roundedRect.AddLine(rect.Right - cornerRadius * 2, rect.Bottom, rect.X + cornerRadius * 2, rect.Bottom);roundedRect.AddArc(rect.X, rect.Bottom - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 90, 90);roundedRect.AddLine(rect.X, rect.Bottom - cornerRadius * 2, rect.X, rect.Y + cornerRadius * 2);roundedRect.CloseFigure();return roundedRect;
}

2、绘制阴影

internal void DrawShadow()
{Bitmap bitmap = null;Graphics g = null;try{bitmap = new Bitmap(Width, Height);g = Graphics.FromImage(bitmap);g.SmoothingMode = SmoothingMode.AntiAlias;Color c = Color.FromArgb(0, 0, 0, 0);Pen p = new Pen(c, 3);for (int i = 0; i < Main.ShadowWidth; i++){p.Color = Color.FromArgb((255 / 10 / Main.ShadowWidth) * i, c);DrawRoundRectangle(g, p, new Rectangle(i, i, Width - (2 * i) - 1, Height - (2 * i) - 1), Main.ShadowWidth - i);}SetBits(bitmap);}catch { }finally{g?.Dispose();bitmap?.Dispose();}
}

3、绘制半透明bitmap到窗口上

protected override CreateParams CreateParams
{get{CreateParams cParms = base.CreateParams;cParms.ExStyle |= 0x00080000; // WS_EX_LAYEREDreturn cParms;}
}
public void SetBits(Bitmap bitmap)
{if (!Image.IsCanonicalPixelFormat(bitmap.PixelFormat) || !Image.IsAlphaPixelFormat(bitmap.PixelFormat))throw new ApplicationException("图片必须是32位带Alhpa通道的图片。");IntPtr oldBits = IntPtr.Zero;IntPtr screenDC = FormStyleAPI.GetDC(IntPtr.Zero);IntPtr hBitmap = IntPtr.Zero;IntPtr memDc = FormStyleAPI.CreateCompatibleDC(screenDC);try{FormStyleAPI.Point topLoc = new FormStyleAPI.Point(Left, Top);FormStyleAPI.Size bitMapSize = new FormStyleAPI.Size(Width, Height);FormStyleAPI.BLENDFUNCTION blendFunc = new FormStyleAPI.BLENDFUNCTION();FormStyleAPI.Point srcLoc = new FormStyleAPI.Point(0, 0);hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));oldBits = FormStyleAPI.SelectObject(memDc, hBitmap);blendFunc.BlendOp = FormStyleAPI.AC_SRC_OVER;blendFunc.SourceConstantAlpha = Byte.Parse(((int)(Main.Opacity * 255)).ToString());blendFunc.AlphaFormat = FormStyleAPI.AC_SRC_ALPHA;blendFunc.BlendFlags = 0;FormStyleAPI.UpdateLayeredWindow(Handle, screenDC, ref topLoc, ref bitMapSize, memDc, ref srcLoc, 0, ref blendFunc, FormStyleAPI.ULW_ALPHA);}finally{if (hBitmap != IntPtr.Zero){FormStyleAPI.SelectObject(memDc, oldBits);FormStyleAPI.DeleteObject(hBitmap);}FormStyleAPI.ReleaseDC(IntPtr.Zero, screenDC);FormStyleAPI.DeleteDC(memDc);}
}

四、最终方案的效果和源码

源码下载

效果图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/544654.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

synchronized 优化手段之锁膨胀机制!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;synchronized 在 JDK 1.5 之前性能是比较低的&#xff0c;在那时我们通常会选择使用 Lock 来替代 synchronized。然而这个情…

NTFS USN的Create和工具代码汇总

1、 因为之前把相关代码放在了GitHub上&#xff0c;后来突然有人帮忙改了些个BUG&#xff0c;非常感谢 760193107&#xff0c;所以就写了个完整点的例子&#xff0c;希望对别人有所帮助。 GitHub项目地址 2、错误码&#xff1a;ERROR_JOURNAL_NOT_ACTIVE 在测试时&#xff…

在Java中,负数的绝对值不一定是正数!

作者 l Hollis来源 l Hollis&#xff08;ID&#xff1a;hollischuang&#xff09;绝对值是指一个数在数轴上所对应点到原点的距离&#xff0c;所以&#xff0c;在数学领域&#xff0c;正数的绝对值是这个数本身&#xff0c;负数的绝对值应该是他的相反数。这几乎是每个人都知道…

自己写着玩(二)

转载于:https://www.cnblogs.com/wangmengmeng/p/4572611.html

实战:隐藏SpringBoot中的私密数据!

这几天公司在排查内部数据账号泄漏&#xff0c;原因是发现某些实习生小可爱居然连带着账号、密码将源码私传到GitHub上&#xff0c;导致核心数据外漏&#xff0c;孩子还是没挨过社会毒打&#xff0c;这种事的后果可大可小。说起这个我是比较有感触的&#xff0c;之前我TM被删库…

JS的条形码和二维码生成

一、前言 最近做项目用到了JS生成条形码和二维码&#xff0c;内容不多&#xff0c;整理一下方便使用。 2018年7月5日更新&#xff1a; 二维码生成时&#xff0c;如果长度太长会有异常&#xff1a; Uncaught Error: code length overflow. (1604>1056) 创建的时候&#…

synchronized 中的 4 个优化,你知道几个?

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;synchronized 在 JDK 1.5 时性能是比较低的&#xff0c;然而在后续的版本中经过各种优化迭代&#xff0c;它的性能也得到了前…

31Exchange Server 2010跨站点部署-搬迁Exchange服务器到分支机构

16.4 将EX07和EX08搬迁到上海分支机构首先我在上海分支机机构站点下创建一个CAS阵列&#xff0c;命令如下&#xff1a;下面获取下当前域中的CAS阵列信息16.4.1搬迁CAS,HT服务器1、从广州总部NLB群集删除EX07主机2、修改EX07的IP地址为分支机构IP地址 192.168.20.27(上海分支机构…

@Autowired的这些骚操作,你都知道吗?

前言最近review别人代码的时候&#xff0c;看到了一些Autowired不一样的用法&#xff0c;觉得有些意思&#xff0c;特定花时间研究了一下&#xff0c;收获了不少东西&#xff0c;现在分享给大家。也许Autowired比你想象中更强大。1. Autowired的默认装配我们都知道在spring中Au…

C# Winform 使用二维码

关于C# Winform 程序中使用二维码的使用记录&#xff1a; 1、使用 Nuget 安装 ZXing.Net 程序包&#xff1b; 2、调用代码&#xff1a; private void button1_Click(object sender, EventArgs e) {BarcodeWriter writer new BarcodeWriter();writer.Format BarcodeFormat…

[Swust OJ 85]--单向公路(BFS)

题目链接:http://acm.swust.edu.cn/problem/0085/ Time limit(ms): 5000      Memory limit(kb): 65535Description某个地区有许多城镇&#xff0c;但并不是每个城镇都跟其他城镇有公路连接&#xff0c;且有公路的并不都能双向行驶。现在我们把这些城镇间的公路分布及允许…

7 种分布式全局 ID 生成策略,你更爱哪种?

上了微服务之后&#xff0c;很多原本很简单的问题现在都变复杂了&#xff0c;例如全局 ID 这事&#xff01;最近工作中刚好用到这块内容&#xff0c;于是调研了市面上几种常见的全局 ID 生成策略&#xff0c;稍微做了一下对比&#xff0c;供小伙伴们参考。当数据库分库分表之后…

C# 读取照片的EXIF信息

一、使用 MetadataExtractor 读取 EXIF 信息 1、NuGet 中安装 在 NuGet 中搜索并安装 MetadataExtractor&#xff1b; 2、包信息 我安装后会有两个包&#xff1a;MetadataExtractor 2.0.0 和 XmpCore 5.1.3 3、代码实现 我是创建的 WPF 项目&#xff1a; private void B…

ReentrantLock 中的 4 个坑!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;JDK 1.5 之前 synchronized 的性能是比较低的&#xff0c;但在 JDK 1.5 中&#xff0c;官方推出一个重量级功能 Lock&#x…

SpringBoot 中 4 大核心组件,你了解多少?

Spring Boot 中的 4 大组件分别是&#xff1a;Spring Boot Starter、Spring Boot Autoconfigure、Spring Boot CLI 以及 Spring Boot actuator&#xff0c;接下来&#xff0c;我们分别来看他们的使用和作用。1.Spring Boot Starter1.1 Starter的应用示例<dependency><…

双重检查锁,原来是这样演变来的,你了解吗

最近在看Nacos的源代码时&#xff0c;发现多处都使用了“双重检查锁”的机制&#xff0c;算是非常好的实践案例。这篇文章就着案例来分析一下双重检查锁的使用以及优势所在&#xff0c;目的就是让你的代码格调更加高一个层次。同时&#xff0c;基于单例模式&#xff0c;讲解一下…

WakaTime 记录你的时间(Moana 自动同步信息客户端)

X、写在前面 代码界有一神器&#xff0c;可以记录敲代码的时间&#xff0c;项目名称&#xff0c;编译器等信息&#xff0c;可以极大的满足程序员的虚荣心&#xff0c;它就是 WakaTime 网站链接 WakaTime 可以记录敲代码时间&#xff0c;和具体编辑的文件等信息&#xff0c;并…

图解:为什么非公平锁的性能更高?

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;在 Java 中 synchronized 和 ReentrantLock 默认使用的都是非公平锁&#xff0c;而它们采用非公平锁的原因都是一致的&#…

死锁的 4 种排查工具 !

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone死锁&#xff08;Dead Lock&#xff09;指的是两个或两个以上的运算单元&#xff08;进程、线程或协程&#xff09;&#xff0c;都在等待…

【HM】第2课:JavaScript基础

<pre>day02第一天的内容&#xff1a;*html标签里面的表单标签*html标签里面的表格标签思维导图1、JavaScript的简介* 什么是JavaScript&#xff1a;js是一个基于对象和事件驱动的语言&#xff0c;应用客户端。**基于对象&#xff1a;在java里面如果使用对象需要创建&…