我用 WPF 做了一个 “苍蝇飞舞” 的屏保

目录

实现原理

核心流程

核心技术点

技术栈与依赖

下载


我本来想做漂亮的蝴蝶飞舞 ,奈何用WPF的矢量图形不好表现蝴蝶,画出来之后,反而像苍蝇在飞舞。


实现原理

基于 WPF 透明窗口 + 原生 GPU 渲染,实现全屏置顶、鼠标穿透的飞虫屏保效果。

效果:

窗口铺满屏幕,背景完全透明,可看到桌面、始终在最前层、点击、移动等操作直接作用于下层窗口、多只飞虫缓慢、柔和、随机飞行,带翅膀扇动效果

关闭方式:Ctrl+Shift+Q


核心流程

  1. **窗口**:WPF 透明窗口 + Win32 扩展样式实现全屏、置顶、鼠标穿透

  2. **动画**:`CompositionTarget.Rendering` 与显示刷新同步,每帧更新位置

  3. **绘制**:`OnRender` + `DrawingContext`,由 WPF 的 GPU 合成管线渲染

  4. **飞虫**:矢量翅膀(PathGeometry)或位图,带位置、角度、翅膀扇动


核心技术点

窗口控制:

cs 复制代码
<Window AllowsTransparency="True"
        WindowStyle="None"
        Background="Transparent"
        WindowState="Maximized"
        Topmost="True" />

鼠标穿透(WS_EX_TRANSPARENT)

通过 Win32 API 为窗口添加 `WS_EX_TRANSPARENT`,使鼠标事件穿透到下层:

cs 复制代码
private const int GWL_EXSTYLE = -20;
private const int WS_EX_TRANSPARENT = 0x00000020;

[DllImport("user32.dll")]
private static extern int GetWindowLong(IntPtr hwnd, int index);


[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);


var hwnd = new WindowInteropHelper(this).Handle;
var exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_TRANSPARENT);

全局热键(因鼠标穿透无法接收键盘)

cs 复制代码
private const int WM_HOTKEY = 0x0312;

[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hwnd, int id, uint fsModifiers, uint vk);

// 注册 Ctrl+Shift+Q
RegisterHotKey(hwnd, HOTKEY_ID, MOD_CTRL | MOD_SHIFT, VK_Q);

// 在 WndProc 中处理
if (msg == WM_HOTKEY && wParam.ToInt32() == HOTKEY_ID)
    Close();

帧同步动画(CompositionTarget.Rendering)

cs 复制代码
System.Windows.Media.CompositionTarget.Rendering += OnRendering;
private void OnRendering(object? sender, EventArgs e)
{
    var args = (RenderingEventArgs)e;
    var now = args.RenderingTime.TotalSeconds;
    var dt = now - _lastUpdate;
    _lastUpdate = now;

    // 更新每只飞虫的位置、角度、翅膀相位
    foreach (var b in _butterflies)
    {
        b.X += b.Vx * dt;
        b.Y += b.Vy * dt;
        b.FlapPhase += dt * b.FlapSpeed;
    }
    InvalidateVisual();  // 触发重绘
}

自定义绘制(OnRender + DrawingContext)

cs 复制代码
protected override void OnRender(DrawingContext dc)
{
    foreach (var b in _butterflies)
    {
        var wingFlap = Math.Sin(b.FlapPhase) * 0.35;
        dc.PushTransform(new TranslateTransform(b.X, b.Y));
        dc.PushTransform(new RotateTransform(b.Angle * 180 / Math.PI, 0, 0));
        dc.PushTransform(new ScaleTransform(1, 1 - wingFlap * 0.15, centerX, centerY));

        // 绘制身体、翅膀(PathGeometry / Ellipse / Image)
        dc.DrawGeometry(brush, pen, wingGeometry);
        dc.Pop(); dc.Pop(); dc.Pop();
    }
}

翅膀矢量绘制(PathGeometry + BezierSegment)

cs 复制代码
private static Geometry CreateMonarchForewing(int side, double w, double h)
{
    var fig = new PathFigure { StartPoint = new Point(0, 0), IsClosed = true };
    fig.Segments.Add(new BezierSegment(
        new Point(side * w * 0.25, -h * 0.15),
        new Point(side * w * 0.85, -h * 0.55),
        new Point(side * w, -h * 0.25), true));
    fig.Segments.Add(new BezierSegment(
        new Point(side * w * 0.9, h * 0.05),
        new Point(side * w * 0.35, h * 0.55),
        new Point(0, h * 0.25), true));
    var geo = new PathGeometry();
    geo.Figures.Add(fig);
    geo.Freeze();
    return geo;
}

技术栈与依赖

框架 : .NET 8 + WPF

渲染 :WPF 原生 DrawingContext(GPU 加速)

透明 :AllowsTransparency + Background="Transparent"

|穿透 : Win32 WS_EX_TRANSPARENT

热键 :Win32 RegisterHotKey

依赖 :无第三方图形库(纯 WPF)


下载

附件下载: https://pan.baidu.com/s/1hLm8aRX0tQLUXAfl4uba9w 提取码: late

程序目录如下:

相关推荐
xiaoxue..1 小时前
TailwindCSS:从“样式民工”到“UI乐高大师”的逆袭
前端·css·ui
没有bug.的程序员6 小时前
自动化测试之魂:Selenium 与 TestNG 深度集成内核、Page Object 模型实战与 Web UI 交付质量指南
前端·自动化测试·selenium·ui·testng·page·object
赵鑫亿8 小时前
ClawPanel v4.4.0 发布:AI 智能助手 + 模型兼容性修复 + UI 优化
人工智能·ui·docker·容器·qq·openclaw
我命由我1234510 小时前
Photoshop - Photoshop 工具栏(69)前景色和背景色
学习·ui·职场和发展·求职招聘·职场发展·学习方法·photoshop
我命由我1234510 小时前
Photoshop - Photoshop 工具栏(70)以快速蒙版/标准模式编辑
学习·ui·职场和发展·求职招聘·职场发展·学习方法·photoshop
少云清11 小时前
【UI自动化测试】1_PO模式 _面向过程编码
ui·po模式
少云清11 小时前
【UI自动化测试】2_PO模式 _单元测试框架(重点)
ui·单元测试·po模式
我是苏苏11 小时前
Web开发:使用Ocelot+Nacos+WebApi作简单网关鉴权
前端·javascript·ui
我命由我123451 天前
Photoshop - Photoshop 工具栏(67)修补工具
学习·ui·职场和发展·求职招聘·职场发展·学习方法·photoshop
AaronZZH1 天前
AG-UI:连接 AI 智能体与用户应用的开放协议
人工智能·ui