C# 类CSS3盒阴影实现/算法
我正在寻找或尝试实现一种算法来绘制方框阴影(如CSS 3规范中所述),该算法接受以下参数:C# 类CSS3盒阴影实现/算法,c#,.net,gdi+,dropshadow,C#,.net,Gdi+,Dropshadow,我正在寻找或尝试实现一种算法来绘制方框阴影(如CSS 3规范中所述),该算法接受以下参数: 水平偏移 垂直偏移 插图 散布 模糊 颜色 (可选:不透明度) 从哪里开始 我已经寻找了Firefox/Chrome的源代码,看看我是否可以从那里得到一个实现,没有这样的运气 我研究过线性梯度算法,用方框画,这种方法很有效,除了圆形矩形,它在阴影中留下空像素,可能是因为边缘的半径 我正在用GDI+在.NET中执行此操作。我的目标不是为图像创建阴影。我已经看过这方面的文章了。我想为用GDI+绘制的形状创
- 水平偏移
- 垂直偏移
- 插图
- 散布
- 模糊
- 颜色
- (可选:不透明度)
感谢您的帮助 我为您编写了一个DropShadowPanel,用于处理其中的控件,并根据控件标记的要求添加阴影(外部或内部) 正如您在图像控件中所看到的,这些控件按照定义获取其阴影: 标签: 文本框:DropShadow:5,5,10,000000,noinset 日历:DropShadow:10,10,80,30,#0000FF,noinset 图片框左上角:DropShadow:-50,20,50,10,8888,noinset 图片框左下:DropShadow:10,10,20,20,#442200,插图 图片框右下:DropShadow:0,0,50,50,#442200,noinset 以下是面板的代码: (在绘制到控件gdi对象之前,它将中间图形用于图像,以避免表单爬行-这实际上运行得非常快)
使用系统;
使用System.Collections.Generic;
使用系统图;
使用System.Drawing.Drawing2D;
使用System.Linq;
使用系统文本;
使用System.Windows.Forms;
命名空间Windows窗体应用程序4
{
公共类DropShadowPanel:面板
{
已添加受保护的覆盖无效OnControlAdded(ControlEventArgs e)
{
e、 Control.Paint+=新的PaintEventHandler(Control\u Paint);
添加的碱基(e);
}
无效控件\u绘制(对象发送器,PaintEventArgs e)
{
CheckDrawInnerShadow(发送方作为控件,例如图形);
}
私有void CheckDrawInnerShadow(控制发送器,图形g)
{
var dropShadowStruct=GetDropShadowStruct(发送方);
if(dropShadowStruct==null | |!dropShadowStruct.Inset)
{
返回;
}
DrawInsetShadow(发送方作为控件,g);
}
受保护的覆盖无效OnControlRemoved(ControlEventArgs e)
{
e、 Control.Paint-=新的PaintEventHandler(Control\u Paint);
}
受保护的覆盖无效OnPaint(PaintEventArgs e)
{
基础漆(e);
DrawShadow(Controls.OfType(),其中(c=>c.Tag!=null&&c.Tag.ToString().StartsWith(“DropShadow”)),例如Graphics);
}
void DrawInsertShadow(控件,图形g)
{
var dropShadowStruct=GetDropShadowStruct(控制);
var rInner=新矩形(Point.Empty,control.Size);
var img=新位图(rInner.Width,rInner.Height,g);
var g2=图形。来自图像(img);
g2.CompositingMode=CompositingMode.SourceCopy;
g2.FillRectangle(新的SolidBrush(dropShadowStruct.Color),0,0,control.Width,control.Height);
rInner.Offset(dropShadowStruct.HShadow、dropShadowStruct.VShadow);
充气(dropShadowStruct.Blur,dropShadowStruct.Blur);
充气(-dropShadowStruct.Spread,-dropShadowStruct.Spread);
双模糊大小=dropShadowStruct.Blur;
双模糊开始大小=模糊大小;
做
{
var transparency=blurSize/blurStartSize;
var color=color.FromArgb(((int)(255*(透明度*透明度))),dropShadowStruct.color);
充气(-1,-1);
DrawRoundedRectangle(g2,rInner,(int)blurSize,钢笔。透明,彩色);
模糊尺寸--;
}而(模糊度>0);
g、 绘图图像(img,0,0);
g、 冲洗();
g2.Dispose();
img.Dispose();
}
void DrawShadow(IEnumerable控件,图形g)
{
foreach(控件中的var控件)
{
var dropShadowStruct=GetDropShadowStruct(控制);
if(dropShadowStruct.Inset)
{
continue;//必须由控件本身处理
}
DrawOutsetShadow(g,dropShadowStruct,control);
}
}
//由于速度原因,在图像上绘制循环
私有void DrawOutsetShadow(图形g、动态dropShadowStruct、控件)
{
var路由器=control.Bounds;
var rInner=control.Bounds;
rInner.Offset(dropShadowStruct.HShadow、dropShadowStruct.VShadow);
充气(-dropShadowStruct.Blur,-dropShadowStruct.Blur);
路由器。充气(dropShadowStruct.Spread,dropShadowStruct.Spread);
rOuter.Offset(dropShadowStruct.HShadow、dropShadowStruct.VShadow);
var originalOuter=路由器;
var img=新位图(originalOuter.Width,originalOuter.Height,g);
var g2=图形。来自图像(img);
var currentBlur=0;
做
{
变量透明度=(rOuter.Height-rInner.Height)/(double)(dropShadowStruct.Blur*2+dropShadowStruct.Spread*2);
var color=color.FromArgb(((int)(255*(透明度*透明度))),dropShadowStruct.color);
var-rOutput=rInner;
线路输出偏移量(-originalOuter.Left,-originalOuter.Top);
DrawRoundedRectangle(g2、rOutput、currentBlur、Pens.透明、彩色);
充气(1,1);
currentBlur=(int)((双精度)dropShadowStruct.Blur*(1-(透明度*透明度));
}while(rOuter.Contains(rInner));
g2.Flush();
g2.Dispose();
g、 DrawImage(img,origina
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication4
{
public class DropShadowPanel : Panel
{
protected override void OnControlAdded(ControlEventArgs e)
{
e.Control.Paint += new PaintEventHandler(Control_Paint);
base.OnControlAdded(e);
}
void Control_Paint(object sender, PaintEventArgs e)
{
CheckDrawInnerShadow(sender as Control, e.Graphics);
}
private void CheckDrawInnerShadow(Control sender, Graphics g)
{
var dropShadowStruct = GetDropShadowStruct(sender);
if (dropShadowStruct == null || !dropShadowStruct.Inset)
{
return;
}
DrawInsetShadow(sender as Control, g);
}
protected override void OnControlRemoved(ControlEventArgs e)
{
e.Control.Paint -= new PaintEventHandler(Control_Paint);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
DrawShadow(Controls.OfType<Control>().Where(c => c.Tag != null && c.Tag.ToString().StartsWith("DropShadow")), e.Graphics);
}
void DrawInsetShadow(Control control, Graphics g)
{
var dropShadowStruct = GetDropShadowStruct(control);
var rInner = new Rectangle(Point.Empty, control.Size);
var img = new Bitmap(rInner.Width, rInner.Height, g);
var g2 = Graphics.FromImage(img);
g2.CompositingMode = CompositingMode.SourceCopy;
g2.FillRectangle(new SolidBrush(dropShadowStruct.Color), 0, 0, control.Width, control.Height);
rInner.Offset(dropShadowStruct.HShadow, dropShadowStruct.VShadow);
rInner.Inflate(dropShadowStruct.Blur, dropShadowStruct.Blur);
rInner.Inflate(-dropShadowStruct.Spread, -dropShadowStruct.Spread);
double blurSize = dropShadowStruct.Blur;
double blurStartSize = blurSize;
do
{
var transparency = blurSize/blurStartSize;
var color = Color.FromArgb(((int)(255 * (transparency * transparency))), dropShadowStruct.Color);
rInner.Inflate(-1,-1);
DrawRoundedRectangle(g2, rInner, (int)blurSize, Pens.Transparent, color);
blurSize--;
} while (blurSize > 0);
g.DrawImage(img, 0, 0);
g.Flush();
g2.Dispose();
img.Dispose();
}
void DrawShadow(IEnumerable<Control> controls, Graphics g)
{
foreach (var control in controls)
{
var dropShadowStruct = GetDropShadowStruct(control);
if (dropShadowStruct.Inset)
{
continue; // must be handled by the control itself
}
DrawOutsetShadow(g, dropShadowStruct, control);
}
}
// drawing the loop on an image because of speed
private void DrawOutsetShadow(Graphics g, dynamic dropShadowStruct, Control control)
{
var rOuter = control.Bounds;
var rInner = control.Bounds;
rInner.Offset(dropShadowStruct.HShadow, dropShadowStruct.VShadow);
rInner.Inflate(-dropShadowStruct.Blur, -dropShadowStruct.Blur);
rOuter.Inflate(dropShadowStruct.Spread, dropShadowStruct.Spread);
rOuter.Offset(dropShadowStruct.HShadow, dropShadowStruct.VShadow);
var originalOuter = rOuter;
var img = new Bitmap(originalOuter.Width, originalOuter.Height, g);
var g2 = Graphics.FromImage(img);
var currentBlur = 0;
do
{
var transparency = (rOuter.Height - rInner.Height)/(double) (dropShadowStruct.Blur*2 + dropShadowStruct.Spread*2);
var color = Color.FromArgb(((int)(255 * (transparency * transparency))), dropShadowStruct.Color);
var rOutput = rInner;
rOutput.Offset(-originalOuter.Left, -originalOuter.Top);
DrawRoundedRectangle(g2, rOutput, currentBlur, Pens.Transparent, color);
rInner.Inflate(1, 1);
currentBlur = (int) ((double) dropShadowStruct.Blur*(1 - (transparency*transparency)));
} while (rOuter.Contains(rInner));
g2.Flush();
g2.Dispose();
g.DrawImage(img, originalOuter);
img.Dispose();
}
private static dynamic GetDropShadowStruct(Control control)
{
if (control.Tag == null || !(control.Tag is string) || !control.Tag.ToString().StartsWith("DropShadow"))
return null;
string[] dropShadowParams = control.Tag.ToString().Split(':')[1].Split(',');
var dropShadowStruct = new
{
HShadow = Convert.ToInt32(dropShadowParams[0]),
VShadow = Convert.ToInt32(dropShadowParams[1]),
Blur = Convert.ToInt32(dropShadowParams[2]),
Spread = Convert.ToInt32(dropShadowParams[3]),
Color = ColorTranslator.FromHtml(dropShadowParams[4]),
Inset = dropShadowParams[5].ToLowerInvariant() == "inset"
};
return dropShadowStruct;
}
private void DrawRoundedRectangle(Graphics gfx, Rectangle bounds, int cornerRadius, Pen drawPen, Color fillColor)
{
int strokeOffset = Convert.ToInt32(Math.Ceiling(drawPen.Width));
bounds = Rectangle.Inflate(bounds, -strokeOffset, -strokeOffset);
var gfxPath = new GraphicsPath();
if (cornerRadius > 0)
{
gfxPath.AddArc(bounds.X, bounds.Y, cornerRadius, cornerRadius, 180, 90);
gfxPath.AddArc(bounds.X + bounds.Width - cornerRadius, bounds.Y, cornerRadius, cornerRadius, 270, 90);
gfxPath.AddArc(bounds.X + bounds.Width - cornerRadius, bounds.Y + bounds.Height - cornerRadius, cornerRadius,
cornerRadius, 0, 90);
gfxPath.AddArc(bounds.X, bounds.Y + bounds.Height - cornerRadius, cornerRadius, cornerRadius, 90, 90);
}
else
{
gfxPath.AddRectangle(bounds);
}
gfxPath.CloseAllFigures();
gfx.FillPath(new SolidBrush(fillColor), gfxPath);
if (drawPen != Pens.Transparent)
{
var pen = new Pen(drawPen.Color);
pen.EndCap = pen.StartCap = LineCap.Round;
gfx.DrawPath(pen, gfxPath);
}
}
}
}