C#中的Drawing 類案例詳解
更新時間:2025年08月08日 11:50:24 作者:工程師007
文章解析WPF與WinForms的Drawing類差異,涵蓋命名空間、繼承鏈、常用類及應(yīng)用場景,通過案例展示如何創(chuàng)建帶陰影圓角矩形按鈕,強調(diào)WPF的輕量、可動畫特性與WinForms的即時繪制模式,對C# Drawing類相關(guān)知識感興趣的朋友一起看看吧
一、Drawing 是什么?
命名空間
- WPF:System.Windows.Media
- WinForms:System.Drawing(GDI+)
繼承鏈(WPF)
- Object → DispatcherObject → DependencyObject → Freezable → Animatable → Drawing
常用派生類:
- GeometryDrawing(用 Path 畫形狀)
- ImageDrawing(貼位圖)
- VideoDrawing(播放視頻)
- GlyphRunDrawing(文字)
- DrawingGroup(容器,可組合其它 Drawing)
特點
- 輕量級:只存“矢量指令”,不繼承 UIElement,不參與布局/事件路由。
- 可凍結(jié)(Freeze):變?yōu)橹蛔x后可跨線程使用。
- 可序列化/導(dǎo)出為 XAML。
二、典型用法
- 直接放在控件里
- 用 DrawingBrush 或 DrawingImage 把 Drawing 變成 Brush/Image,再賦給控件的 Background、Source 等屬性。
- 在 DrawingVisual 里繪制
- 適合自定義控件、命中測試、打印。
- 在 DrawingGroup 里組合
- 把多個 Drawing 套娃,實現(xiàn)復(fù)雜場景。
三、案例:畫一個“帶陰影的圓角矩形按鈕”
目標:
- 圓角矩形(填充線性漸變、描邊)
- 下方有一層模糊陰影(半透明黑圓角矩形)
- 鼠標懸停時整體高亮(動畫改變漸變)
WPF:
<Window x:Class="DemoDrawing.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Drawing 示例" Width="300" Height="200">
<Grid>
<!-- 使用 DrawingBrush 做背景 -->
<Rectangle x:Name="btnRect" Width="180" Height="60"
MouseEnter="BtnRect_MouseEnter"
MouseLeave="BtnRect_MouseLeave">
<Rectangle.Resources>
<!-- 陰影 Drawing -->
<GeometryDrawing x:Key="shadow"
Geometry="M 5,5 175,5 175,55 5,55 Z"
Brush="#80000000">
<GeometryDrawing.Pen>
<Pen Brush="Transparent" Thickness="1"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
<!-- 按鈕主體 Drawing -->
<GeometryDrawing x:Key="body" Geometry="M 0,0 170,0 170,50 0,50 Z">
<GeometryDrawing.Brush>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#FF4C9AFF"/>
<GradientStop Offset="1" Color="#FF0050DD"/>
</LinearGradientBrush>
</GeometryDrawing.Brush>
<GeometryDrawing.Pen>
<Pen Brush="#FF003399" Thickness="2"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
<!-- 組合 DrawingGroup -->
<DrawingGroup x:Key="combined">
<!-- 先畫陰影 -->
<DrawingGroup.Children>
<DrawingGroup>
<DrawingGroup.Children>
<StaticResource ResourceKey="shadow"/>
</DrawingGroup.Children>
<DrawingGroup.BitmapEffect>
<BlurBitmapEffect Radius="5"/>
</DrawingGroup.BitmapEffect>
</DrawingGroup>
<!-- 再畫按鈕主體 -->
<StaticResource ResourceKey="body"/>
</DrawingGroup.Children>
</DrawingGroup>
<!-- 把 DrawingGroup 變成 Brush -->
<DrawingBrush x:Key="btnBrush" Drawing="{StaticResource combined}"/>
</Rectangle.Resources>
<Rectangle.Fill>
<StaticResource ResourceKey="btnBrush"/>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Window>后臺代碼
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void BtnRect_MouseEnter(object sender, MouseEventArgs e)
{
// 找到 Drawing 里的漸變刷
var rect = (Rectangle)sender;
var brush = (DrawingBrush)rect.Fill;
var dg = (DrawingGroup)brush.Drawing;
var body = (GeometryDrawing)((DrawingGroup)dg.Children[1]).Children[0];
var lg = (LinearGradientBrush)body.Brush;
// 動畫高亮
var da = new ColorAnimation(Color.FromRgb(0x6F, 0xBA, 0xFF),
TimeSpan.FromMilliseconds(300));
lg.GradientStops[0].BeginAnimation(GradientStop.ColorProperty, da);
}
private void BtnRect_MouseLeave(object sender, MouseEventArgs e)
{
var rect = (Rectangle)sender;
var brush = (DrawingBrush)rect.Fill;
var dg = (DrawingGroup)brush.Drawing;
var body = (GeometryDrawing)((DrawingGroup)dg.Children[1]).Children[0];
var lg = (LinearGradientBrush)body.Brush;
var da = new ColorAnimation(Color.FromRgb(0x4C, 0x9A, 0xFF),
TimeSpan.FromMilliseconds(300));
lg.GradientStops[0].BeginAnimation(GradientStop.ColorProperty, da);
}
}四、WinForms(GDI+)對應(yīng)寫法
WinForms 沒有 Drawing 類,而是 GraphicsPath + LinearGradientBrush + Bitmap 的“即時模式”繪制。核心步驟:
protected override void OnPaint(PaintEventArgs e)
{
var g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
// 1. 陰影
using (var path = CreateRoundRect(5, 5, 175, 55, 8))
using (var brush = new SolidBrush(Color.FromArgb(128, 0, 0, 0)))
using (var blur = new Bitmap(180, 60))
{
using (var g2 = Graphics.FromImage(blur))
{
g2.SmoothingMode = SmoothingMode.AntiAlias;
g2.FillPath(brush, path);
}
// 手動高斯模糊(略)...
g.DrawImage(blur, 0, 0);
}
// 2. 主體
using (var path = CreateRoundRect(0, 0, 170, 50, 8))
using (var brush = new LinearGradientBrush(
new Point(0, 0), new Point(0, 50),
Color.FromArgb(255, 0x4C, 0x9A, 0xFF),
Color.FromArgb(255, 0x00, 0x50, 0xDD)))
using (var pen = new Pen(Color.FromArgb(255, 0x00, 0x33, 0x99), 2))
{
g.FillPath(brush, path);
g.DrawPath(pen, path);
}
}
private GraphicsPath CreateRoundRect(float x, float y, float w, float h, float r)
{
var gp = new GraphicsPath();
gp.AddArc(x + w - r, y, r, r, 270, 90);
gp.AddArc(x + w - r, y + h - r, r, r, 0, 90);
gp.AddArc(x, y + h - r, r, r, 90, 90);
gp.AddArc(x, y, r, r, 180, 90);
gp.CloseFigure();
return gp;
}- WPF 的 Drawing 體系是“矢量指令樹”,輕量、可緩存、可動畫,適合高性能場景(千級圖形)。
- 常用套路:GeometryDrawing/DrawingGroup → DrawingBrush/DrawingImage → Shape 或 Image 控件。
- WinForms 沒有 Drawing 類,用 Graphics 即時繪制;想緩存可用 Bitmap/ Metafile。
到此這篇關(guān)于C#Drawing 類詳解的文章就介紹到這了,更多相關(guān)C# Drawing 類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解析如何正確使用SqlConnection的實現(xiàn)方法
本篇文章對如何正確使用SqlConnection的實現(xiàn)方法進行了詳細的分析介紹,需要的朋友參考下2013-05-05
C#影院售票系統(tǒng)畢業(yè)設(shè)計(2)
這篇文章主要介紹了C#影院售票系統(tǒng)畢業(yè)設(shè)計,介紹了電影院座位的動態(tài)繪制、電影信息綁定到窗體中如何展現(xiàn)出來,需要的朋友可以參考下2015-11-11

