找回密码
 立即注册
首页 业界区 业界 c#造个轮子--GIF录制工具

c#造个轮子--GIF录制工具

恙髡 3 天前
        在以往几篇文章里面,大家都可以看到各种录制的GIF效果图,把gif放在文章开始,不仅可以减少很多冗余的解释白话文,更可以让读者一览无余看到文章大概要义。
以往都是使用“LicEcap”来录制的,那么我们是否能自己实现一个这样的工具呢?一方面国庆假期结束,练练代码手感,另一方面可以根据自己需求扩展需要的功能。
 
01介绍软件UI及操作
操作比较简单,以下是运行界面:

  • 选择录制区域,绘制需要录制的ROI区域 
  • 点击开始录制
  • 录制结束后,停止录制即可.弹出保存路径保存gif
 
1.png

02效果图

  • 整个运行作业图
    2.gif

  • 实际录屏的ROI区域效果GIF
    3.gif

03源码介绍
4.png

 
  1. private void InitializeComponents()
  2. {
  3.     this.Text = "GIF录制工具";
  4.     this.Size = new Size(400, 200);
  5.     this.StartPosition = FormStartPosition.CenterScreen;

  6.     // 选择区域按钮
  7.     Button btnSelectArea = new Button();
  8.     btnSelectArea.Text = "选择录制区域";
  9.     btnSelectArea.Size = new Size(120, 30);
  10.     btnSelectArea.Location = new Point(20, 20);
  11.     btnSelectArea.Click += BtnSelectArea_Click;
  12.     this.Controls.Add(btnSelectArea);

  13.     // 开始录制按钮
  14.     Button btnStart = new Button();
  15.     btnStart.Text = "开始录制";
  16.     btnStart.Size = new Size(120, 30);
  17.     btnStart.Location = new Point(20, 60);
  18.     btnStart.Click += BtnStart_Click;
  19.     this.Controls.Add(btnStart);

  20.     // 停止录制按钮
  21.     Button btnStop = new Button();
  22.     btnStop.Text = "停止录制";
  23.     btnStop.Size = new Size(120, 30);
  24.     btnStop.Location = new Point(20, 100);
  25.     btnStop.Click += BtnStop_Click;
  26.     this.Controls.Add(btnStop);

  27.     // 帧率选择
  28.     Label lblFrameRate = new Label();
  29.     lblFrameRate.Text = "帧率:";
  30.     lblFrameRate.Location = new Point(160, 65);
  31.     lblFrameRate.Size = new Size(50, 20);
  32.     this.Controls.Add(lblFrameRate);

  33.     NumericUpDown numFrameRate = new NumericUpDown();
  34.     numFrameRate.Value = frameRate;
  35.     numFrameRate.Minimum = 1;
  36.     numFrameRate.Maximum = 30;
  37.     numFrameRate.Location = new Point(210, 65);
  38.     numFrameRate.Size = new Size(60, 20);
  39.     numFrameRate.ValueChanged += (s, e) => { frameRate = (int)numFrameRate.Value; };
  40.     this.Controls.Add(numFrameRate);

  41.     // 状态标签
  42.     Label lblStatus = new Label();
  43.     lblStatus.Text = "状态: 就绪";
  44.     lblStatus.Location = new Point(160, 25);
  45.     lblStatus.Size = new Size(200, 20);
  46.     lblStatus.Name = "lblStatus";
  47.     this.Controls.Add(lblStatus);

  48.     // 录制计时器
  49.     captureTimer = new System.Windows.Forms.Timer();
  50.     captureTimer.Tick += CaptureTimer_Tick;
  51. }
复制代码
选择ROI录屏区域
  1. private void StartAreaSelection()
  2. {
  3.     this.Hide();
  4.     Thread.Sleep(500); // 等待窗体隐藏

  5.     isSelectingArea = true;
  6.     Cursor = Cursors.Cross;

  7.     // 创建全屏透明窗体用于区域选择
  8.     Form selectionForm = new Form();
  9.     selectionForm.WindowState = FormWindowState.Maximized;
  10.     selectionForm.FormBorderStyle = FormBorderStyle.None;
  11.     selectionForm.BackColor = Color.Black;
  12.     selectionForm.Opacity = 0.3;
  13.     selectionForm.TopMost = true;
  14.     selectionForm.Cursor = Cursors.Cross;

  15.     Rectangle selectedArea = Rectangle.Empty;
  16.     bool isDragging = false;
  17.     Point dragStart = Point.Empty;

  18.     selectionForm.MouseDown += (s, e) =>
  19.     {
  20.         if (e.Button == MouseButtons.Left)
  21.         {
  22.             isDragging = true;
  23.             dragStart = e.Location;
  24.         }
  25.     };

  26.     selectionForm.MouseMove += (s, e) =>
  27.     {
  28.         if (isDragging)
  29.         {
  30.             int x = Math.Min(dragStart.X, e.X);
  31.             int y = Math.Min(dragStart.Y, e.Y);
  32.             int width = Math.Abs(e.X - dragStart.X);
  33.             int height = Math.Abs(e.Y - dragStart.Y);

  34.             selectedArea = new Rectangle(x, y, width, height);
  35.             selectionForm.Invalidate();
  36.         }
  37.     };

  38.     selectionForm.MouseUp += (s, e) =>
  39.     {
  40.         if (e.Button == MouseButtons.Left && isDragging)
  41.         {
  42.             isDragging = false;
  43.             if (selectedArea.Width > 10 && selectedArea.Height > 10)
  44.             {
  45.                 recordingArea = selectedArea;
  46.                 UpdateStatus($"已选择区域: {recordingArea}");
  47.             }
  48.             selectionForm.Close();
  49.         }
  50.     };

  51.     selectionForm.Paint += (s, e) =>
  52.     {
  53.         if (isDragging && !selectedArea.IsEmpty)
  54.         {
  55.             using (Pen pen = new Pen(Color.Red, 2))
  56.             {
  57.                 e.Graphics.DrawRectangle(pen, selectedArea);
  58.             }

  59.             string sizeText = $"{selectedArea.Width} x {selectedArea.Height}";
  60.             using (Font font = new Font("Arial", 12))
  61.             using (Brush brush = new SolidBrush(Color.Red))
  62.             {
  63.                 e.Graphics.DrawString(sizeText, font, brush, selectedArea.X, selectedArea.Y - 20);
  64.             }
  65.         }
  66.     };

  67.     selectionForm.KeyDown += (s, e) =>
  68.     {
  69.         if (e.KeyCode == Keys.Escape)
  70.         {
  71.             selectionForm.Close();
  72.         }
  73.     };

  74.     selectionForm.FormClosed += (s, e) =>
  75.     {
  76.         isSelectingArea = false;
  77.         Cursor = Cursors.Default;
  78.         this.Show();
  79.         this.BringToFront();
  80.     };

  81.     selectionForm.ShowDialog();
  82. }
复制代码
录制结束,保存GIF
  1. private void SaveGif()
  2.  {
  3.      if (frames.Count == 0)
  4.      {
  5.          MessageBox.Show("没有可保存的帧!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
  6.          return;
  7.      }

  8.      using (SaveFileDialog saveDialog = new SaveFileDialog())
  9.      {
  10.          saveDialog.Filter = "GIF 文件|*.gif";
  11.          saveDialog.Title = "保存GIF文件";
  12.          saveDialog.DefaultExt = "gif";

  13.          if (saveDialog.ShowDialog() == DialogResult.OK)
  14.          {
  15.              try
  16.              {
  17.                  // 使用GifBitmapEncoder替代方案
  18.                  SaveFramesAsGif(frames, saveDialog.FileName, frameRate);
  19.                  MessageBox.Show($"GIF保存成功!\n文件: {saveDialog.FileName}\n帧数: {frames.Count}", "成功",
  20.                      MessageBoxButtons.OK, MessageBoxIcon.Information);
  21.              }
  22.              catch (Exception ex)
  23.              {
  24.                  MessageBox.Show($"保存GIF时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
  25.              }
  26.          }
  27.      }

  28.      // 清理资源
  29.      foreach (var frame in frames)
  30.      {
  31.          frame.Dispose();
  32.      }
  33.      frames.Clear();
  34.  }
复制代码
  1. private void SaveFramesAsGif(List<Bitmap> frames, string filePath, int frameRate)
  2.  {
  3.      using (var collection = new MagickImageCollection())
  4.      {
  5.          foreach (var frame in frames)
  6.          {
  7.              using (var memoryStream = new MemoryStream())
  8.              {
  9.                  frame.Save(memoryStream, ImageFormat.Bmp);
  10.                  memoryStream.Position = 0;

  11.                  var image = new MagickImage(memoryStream);
  12.                  image.AnimationDelay =Convert.ToUInt32( 100 / frameRate); // 设置帧延迟
  13.                  collection.Add(image);
  14.              }
  15.          }

  16.          // 优化GIF
  17.          collection.Optimize();
  18.          collection.Write(filePath);
  19.      }
  20.  }
复制代码
主要用到第三方nuget包

  • AnimatedGif
  • Magick.NET-Q16-AnyCPU
结束语  感谢各位耐心查阅!  如果您有更好的想法欢迎一起交流,有不懂的也可以微信公众号联系博主,作者公众号会经常发一些实用的小工具和demo源码,需要的可以去看看!另外,如果觉得本篇博文对您或者身边朋友有帮助的,麻烦点个关注!赠人玫瑰,手留余香,您的支持就是我写作最大的动力,感谢您的关注,期待和您一起探讨!再会!
5.png

 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册