2025-10-14
C#
00

在 .NET 9 中,System.Text.Json 库得到了显著增强,为开发者提供了更强大和灵活的 JSON 处理能力。这些改进主要集中在 JSON 架构支持、智能应用功能以及序列化和反序列化过程的自定义选项上。本文将详细介绍这些新特性,并提供示例代码,帮助开发者更好地理解和应用这些功能。

JSON 架构导出器

在 .NET 9 中,新增了 JsonSchemaExporter 类,使开发者能够从 .NET 类型中提取 JSON 架构文档。这一特性有助于验证和文档化 JSON 数据结构,确保应用程序之间的一致性。

示例代码

C#
using System.Text.Json; using System.Text.Json.Schema; namespace AppTextJson { public class Employee { public int Id { get; set; } public string Name { get; set; } public string Position { get; set; } } internal class Program { static void Main(string[] args) { var options = new JsonSerializerOptions { WriteIndented = true }; string jsonSchema = JsonSerializer.Serialize(new Employee(), options); Console.WriteLine(jsonSchema); Console.ReadKey(); } } }

输出示例

image.png

2025-10-14
C#
00

在日常的Windows应用开发中,标准的ComboBox控件往往显得过于单调和缺乏个性。作为一名开发者,您是否曾经希望能够:

  • 为每个下拉选项设置独特的背景色
  • 为选项添加个性化图标
  • 精细控制文字颜色和样式

今天,我将为您详细解析如何使用C#开发一个功能强大且高度定制的下拉菜单控件!

关键技术:重写绘制方法

通过重写OnDrawItem方法,我们可以完全自定义每个选项的渲染效果:

  1. 绘制独特背景色
  2. 精确放置图标
  3. 自定义文字样式
  4. 添加选中状态特效

控件特性

  • 支持为每个Item设置独立的背景颜色
  • 支持为每个Item设置独立的文字颜色
  • 支持为每个Item添加图标
  • 支持自定义Item高度
  • 支持鼠标悬停效果
  • 完整的事件处理机制
2025-10-14
C#
00

Toggle Button(开关按钮)是一个常见的UI控件,用于表示两种状态之间的切换(开/关、是/否等)。本文将详细介绍如何在C#中实现一个自定义的Toggle Button控件。

Toggle Button(开关按钮)是一个常见的UI控件,用于表示两种状态之间的切换(开/关、是/否等)。本文将详细介绍如何在C#中实现一个自定义的Toggle Button控件。

技术亮点:平滑动画与精细控制

我们的切换按钮具备以下关键特性:

  1. 流畅动画:采用计时器实现像素级平滑切换
  2. 高度可定制:支持自定义颜色、边框和样式
  3. 抗锯齿渲染:使用SmoothingMode.AntiAlias确保视觉质量
2025-10-14
C#
00

屏幕录制现在已经变得非常常见了。不管是做教程视频、游戏直播,还是记录会议内容,一款好用的录屏工具都能让我们轻松抓取画面,并分享重要的瞬间。接下来,本文会一步步教你如何用 C# 和 FFmpeg 打造一个简单却实用的屏幕录制程序。

FFmpeg 是一个强大的开源音频与视频处理工具,支持几乎所有的音视频格式。结合 C# 的界面设计,我们可以快速构建出一个用户友好的录屏应用程序。本文将逐步引导您如何实现这一功能。

环境准备

在开始之前,请确保您已经安装了以下软件:

  1. Visual Studio - 用于 C# 开发的集成开发环境。
  2. FFmpeg - 下载并解压 FFmpeg,记录下其可执行文件的路径。

创建 C# 应用程序

  1. 创建项目:打开 Visual Studio,新建一个 Windows Forms 应用程序项目,命名为 AppRecordScreen
  2. 添加控件:在窗口中添加两个按钮,分别用于“开始录制”和“停止录制”。
2025-10-14
C#
00

在多媒体处理中,将一系列图片转换为视频是一个常见的需求。本文将详细介绍如何使用 SharpAvi库在 C# 中实现这一功能。

安装必要的 NuGet 包

C#
Install-Package SharpAvi Install-Package System.Drawing.Common

核心实现代码

完整的图片转 AVI 方法

C#
using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using SharpAvi; using SharpAvi.Output; using Image = System.Drawing.Image; namespace AppSharpAvi { public class VideoCreator { /// <summary> /// 将图片序列转换为 AVI 视频 /// </summary> /// <param name="imagePaths">图片路径数组</param> /// <param name="outputPath">输出的 AVI 文件路径</param> /// <param name="frameRate">视频帧率</param> public static void CreateAviFromImages( string[] imagePaths, string outputPath, int frameRate = 30 ) { // 参数有效性检查 if (imagePaths == null || imagePaths.Length == 0) throw new ArgumentException("图片路径数组不能为空"); // 读取第一张图片获取尺寸 using (var firstImage = Image.FromFile(imagePaths[0])) { int width = firstImage.Width; int height = firstImage.Height; // 创建 AVI 写入器 using (var writer = new AviWriter(outputPath) { FramesPerSecond = frameRate, EmitIndex1 = true }) { // 添加视频流 var videoStream = writer.AddVideoStream( width, height, BitsPerPixel.Bpp24 ); // 逐帧处理 ProcessFrames(imagePaths, videoStream, width, height); } } } /// <summary> /// 处理每一帧图像 /// </summary> private static void ProcessFrames( string[] imagePaths, IAviVideoStream videoStream, int width, int height) { foreach (var imagePath in imagePaths) { using (var bitmap = new Bitmap(imagePath)) { // 调整图像大小 using (var resizedBitmap = new Bitmap(bitmap, width, height)) { // 锁定图像数据 var bitmapData = resizedBitmap.LockBits( new Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb ); try { // 准备帧数据 int frameDataLength = bitmapData.Stride * height; byte[] frameData = new byte[frameDataLength]; // 垂直翻转图像数据 for (int y = 0; y < height; y++) { Marshal.Copy( new IntPtr(bitmapData.Scan0.ToInt64() + bitmapData.Stride * (height - 1 - y)), frameData, y * bitmapData.Stride, bitmapData.Stride ); } // 写入帧 videoStream.WriteFrame( true, // 关键帧 frameData, 0, frameDataLength ); } finally { resizedBitmap.UnlockBits(bitmapData); } } } } } } }

4. 使用示例

C#
namespace AppSharpAvi { internal class Program { static void Main(string[] args) { VideoCreator.CreateAviFromImages(new string[] { "1.jpg", "2.jpg", "3.jpg","4.jpg" }, "output.avi", 30); } } }

image.png