再 nuget 中 搜索 shapAvi 并添加引用

github 地址:https://github.com/baSSiLL/SharpAvi

using SharpAvi;
using SharpAvi.Codecs;
using SharpAvi.Output;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace BankAutoTransfer.Common
{
public class Recorder
{ private readonly int zoomWidth;
private readonly int zoomHeight;
private readonly AviWriter writer;
private readonly IAviVideoStream videoStream;
private readonly Thread screenThread; /// <summary>
/// 上一次图片
/// </summary>
Bitmap lastBitmap = new Bitmap(, ); bool stop = false; /// <summary>
/// 缩放
/// </summary>
float zoom = ;
/// <summary>
/// 鼠标是否点击
/// </summary>
bool mouseclick = false;
/// <summary>
/// 钩子句柄
/// </summary>
int hook = ;
/// <summary>
/// 录制屏幕
/// </summary>
/// <param name="fileName">要保存的文件名</param>
/// <param name="codec">编码</param>
/// <param name="quality">录制质量</param>
/// <param name="zoom">缩放</param>
public Recorder(string fileName, FourCC codec, int quality = , float zoom = 1.0F)
{
//设置缩放 宽高
zoomHeight = (int)Math.Floor(System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height * zoom);
zoomWidth = (int)Math.Floor(System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width * zoom); this.zoom = zoom;
//创建视频
writer = new AviWriter(fileName)
{
FramesPerSecond = ,
EmitIndex1 = true,
}; //创建视频流
videoStream = CreateVideoStream(codec, quality);
videoStream.Name = "Screencast";
//开启一个线程录制屏幕
screenThread = new Thread(RecordScreen)
{
Name = typeof(Recorder).Name + ".RecordScreen",
IsBackground = true
};
//钩子函数用于监控是否点击了鼠标
hook = WinHook.SetWindowsHookEx(HookType.WH_MOUSE_LL, WinHook.hookProc += MouseHook, Win32Api.GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), ); screenThread.Start();
} private IAviVideoStream CreateVideoStream(FourCC codec, int quality)
{
// Select encoder type based on FOURCC of codec
if (codec == KnownFourCCs.Codecs.Uncompressed)
{
return writer.AddUncompressedVideoStream(zoomWidth, zoomHeight);
}
else if (codec == KnownFourCCs.Codecs.MotionJpeg)
{
return writer.AddMotionJpegVideoStream(zoomWidth, zoomHeight, quality);
}
else
{
return writer.AddMpeg4VideoStream(zoomWidth, zoomHeight, (double)writer.FramesPerSecond,
// It seems that all tested MPEG-4 VfW codecs ignore the quality affecting parameters passed through VfW API
// They only respect the settings from their own configuration dialogs, and Mpeg4VideoEncoder currently has no support for this
quality: quality,
codec: codec,
// Most of VfW codecs expect single-threaded use, so we wrap this encoder to special wrapper
// Thus all calls to the encoder (including its instantiation) will be invoked on a single thread although encoding (and writing) is performed asynchronously
forceSingleThreadedAccess: true);
}
}
/// <summary>
/// 停止录制
/// </summary>
public void Stop()
{
WinHook.UnhookWindowsHookEx(hook);
lastBitmap.Dispose();
stop = true;
} private void RecordScreen()
{
while (!stop)
{
var buffer = GetScreenshot();
// 把图片写入视频流
videoStream.WriteFrameAsync(true, buffer, , buffer.Length).Wait();
}
writer.Close();
} private byte[] GetScreenshot()
{
using (Bitmap avibitmap = GetScreen())
{
Point mouseXY = new Point();
Win32Api.GetCursorPos(ref mouseXY);
using (Graphics mouseGraphics = Graphics.FromImage(avibitmap))
{
//绘制鼠标位置
if (mouseclick)
mouseGraphics.DrawEllipse(new Pen(new SolidBrush(Color.Red), ), new Rectangle(mouseXY.X - , mouseXY.Y - , , ));
else
mouseGraphics.DrawEllipse(new Pen(new SolidBrush(Color.Black), ), new Rectangle(mouseXY.X - , mouseXY.Y - , , ));
if (zoom != )
{
//缩放
using (var copy = new Bitmap(this.zoomWidth, this.zoomHeight))
{
var buffer = new byte[copy.Width * copy.Height * ];
var gcopy = Graphics.FromImage(copy);
gcopy.DrawImage(avibitmap, new Rectangle(new Point(, ), copy.Size), , , avibitmap.Width, avibitmap.Height, GraphicsUnit.Pixel);
gcopy.Dispose();
var bits = copy.LockBits(new Rectangle(, , copy.Width, copy.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
Marshal.Copy(bits.Scan0, buffer, , buffer.Length);
copy.UnlockBits(bits);
return buffer;
}
}
else
{
var buffer = new byte[avibitmap.Width * avibitmap.Height * ];
var bits = avibitmap.LockBits(new Rectangle(, , avibitmap.Width, avibitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
Marshal.Copy(bits.Scan0, buffer, , buffer.Length);
avibitmap.UnlockBits(bits);
return buffer;
}
}
} } private Bitmap GetScreen()
{
try
{
var bitmap = new Bitmap(System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height);
var graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(, , , , System.Windows.Forms.Screen.PrimaryScreen.Bounds.Size);
graphics.Dispose();
lastBitmap.Dispose();
lastBitmap = bitmap;
}
catch
{
}
return (Bitmap)lastBitmap.Clone();
} private int MouseHook(int nCode, int wParam, IntPtr lParam)
{
if (wParam == CommonConst.WM_LBUTTONDOWN)
mouseclick = true;
else if (wParam == CommonConst.WM_LBUTTONUP)
mouseclick = false;
return WinHook.CallNextHookEx(hook, nCode, wParam, lParam);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks; namespace BankAutoTransfer.Common
{
public class WinHook
{
[DllImport("user32.dll")]
public static extern int SetWindowsHookEx(
HookType idHook,
HookProc lpfn,
IntPtr hInstance,
int threadId
); public delegate int HookProc(int nCode, int wParam, IntPtr lParam); public static HookProc hookProc; [DllImport("user32.dll")]
public static extern int CallNextHookEx(
int hhk, //handle to current hook
int nCode, //hook code passed to hook procedure
int wParam, //value passed to hook procedure
IntPtr lParam //value passed to hook procedure
); [DllImport("user32.dll")]
public static extern bool UnhookWindowsHookEx(int hook);
} /// <summary>
/// 设置的钩子类型
/// </summary>
public enum HookType : int
{
/// <summary>
/// WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以监视菜单,滚动
///条,消息框,对话框消息并且发现用户使用ALT+TAB or ALT+ESC 组合键切换窗口。
///WH_MSGFILTER Hook只能监视传递到菜单,滚动条,消息框的消息,以及传递到通
///过安装了Hook子过程的应用程序建立的对话框的消息。WH_SYSMSGFILTER Hook
///监视所有应用程序消息。
///
///WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以在模式循环期间
///过滤消息,这等价于在主消息循环中过滤消息。
///
///通过调用CallMsgFilter function可以直接的调用WH_MSGFILTER Hook。通过使用这
///个函数,应用程序能够在模式循环期间使用相同的代码去过滤消息,如同在主消息循
///环里一样
/// </summary>
WH_MSGFILTER = -,
/// <summary>
/// WH_JOURNALRECORD Hook用来监视和记录输入事件。典型的,可以使用这
///个Hook记录连续的鼠标和键盘事件,然后通过使用WH_JOURNALPLAYBACK Hook
///来回放。WH_JOURNALRECORD Hook是全局Hook,它不能象线程特定Hook一样
///使用。WH_JOURNALRECORD是system-wide local hooks,它们不会被注射到任何行
///程地址空间
/// </summary>
WH_JOURNALRECORD = ,
/// <summary>
/// WH_JOURNALPLAYBACK Hook使应用程序可以插入消息到系统消息队列。可
///以使用这个Hook回放通过使用WH_JOURNALRECORD Hook记录下来的连续的鼠
///标和键盘事件。只要WH_JOURNALPLAYBACK Hook已经安装,正常的鼠标和键盘
///事件就是无效的。WH_JOURNALPLAYBACK Hook是全局Hook,它不能象线程特定
///Hook一样使用。WH_JOURNALPLAYBACK Hook返回超时值,这个值告诉系统在处
///理来自回放Hook当前消息之前需要等待多长时间(毫秒)。这就使Hook可以控制实
///时事件的回放。WH_JOURNALPLAYBACK是system-wide local hooks,它们不会被
///注射到任何行程地址空间
/// </summary>
WH_JOURNALPLAYBACK = ,
/// <summary>
/// 在应用程序中,WH_KEYBOARD Hook用来监视WM_KEYDOWN and
///WM_KEYUP消息,这些消息通过GetMessage or PeekMessage function返回。可以使
///用这个Hook来监视输入到消息队列中的键盘消息
/// </summary>
WH_KEYBOARD = ,
/// <summary>
/// 应用程序使用WH_GETMESSAGE Hook来监视从GetMessage or PeekMessage函
///数返回的消息。你可以使用WH_GETMESSAGE Hook去监视鼠标和键盘输入,以及
///其它发送到消息队列中的消息
/// </summary>
WH_GETMESSAGE = ,
/// <summary>
/// 监视发送到窗口过程的消息,系统在消息发送到接收窗口过程之前调用
/// </summary>
WH_CALLWNDPROC = ,
/// <summary>
/// 在以下事件之前,系统都会调用WH_CBT Hook子过程,这些事件包括:
///1. 激活,建立,销毁,最小化,最大化,移动,改变尺寸等窗口事件;
///2. 完成系统指令;
///3. 来自系统消息队列中的移动鼠标,键盘事件;
///4. 设置输入焦点事件;
///5. 同步系统消息队列事件。
///Hook子过程的返回值确定系统是否允许或者防止这些操作中的一个
/// </summary>
WH_CBT = ,
/// <summary>
/// WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以监视菜单,滚动
///条,消息框,对话框消息并且发现用户使用ALT+TAB or ALT+ESC 组合键切换窗口。
///WH_MSGFILTER Hook只能监视传递到菜单,滚动条,消息框的消息,以及传递到通
///过安装了Hook子过程的应用程序建立的对话框的消息。WH_SYSMSGFILTER Hook
///监视所有应用程序消息。
///
///WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以在模式循环期间
///过滤消息,这等价于在主消息循环中过滤消息。
///
///通过调用CallMsgFilter function可以直接的调用WH_MSGFILTER Hook。通过使用这
///个函数,应用程序能够在模式循环期间使用相同的代码去过滤消息,如同在主消息循
///环里一样
/// </summary>
WH_SYSMSGFILTER = ,
/// <summary>
/// WH_MOUSE Hook监视从GetMessage 或者 PeekMessage 函数返回的鼠标消息。
///使用这个Hook监视输入到消息队列中的鼠标消息
/// </summary>
WH_MOUSE = ,
/// <summary>
/// 当调用GetMessage 或 PeekMessage 来从消息队列种查询非鼠标、键盘消息时
/// </summary>
WH_HARDWARE = ,
/// <summary>
/// 在系统调用系统中与其它Hook关联的Hook子过程之前,系统会调用
///WH_DEBUG Hook子过程。你可以使用这个Hook来决定是否允许系统调用与其它
///Hook关联的Hook子过程
/// </summary>
WH_DEBUG = ,
/// <summary>
/// 外壳应用程序可以使用WH_SHELL Hook去接收重要的通知。当外壳应用程序是
///激活的并且当顶层窗口建立或者销毁时,系统调用WH_SHELL Hook子过程。
///WH_SHELL 共有5钟情况:
///1. 只要有个top-level、unowned 窗口被产生、起作用、或是被摧毁;
///2. 当Taskbar需要重画某个按钮;
///3. 当系统需要显示关于Taskbar的一个程序的最小化形式;
///4. 当目前的键盘布局状态改变;
///5. 当使用者按Ctrl+Esc去执行Task Manager(或相同级别的程序)。
///
///按照惯例,外壳应用程序都不接收WH_SHELL消息。所以,在应用程序能够接
///收WH_SHELL消息之前,应用程序必须调用SystemParametersInfo function注册它自
///己
/// </summary>
WH_SHELL = ,
/// <summary>
/// 当应用程序的前台线程处于空闲状态时,可以使用WH_FOREGROUNDIDLE
///Hook执行低优先级的任务。当应用程序的前台线程大概要变成空闲状态时,系统就
///会调用WH_FOREGROUNDIDLE Hook子过程
/// </summary>
WH_FOREGROUNDIDLE = ,
/// <summary>
/// 监视发送到窗口过程的消息,系统在消息发送到接收窗口过程之后调用
/// </summary>
WH_CALLWNDPROCRET = ,
/// <summary>
/// 监视输入到线程消息队列中的键盘消息
/// </summary>
WH_KEYBOARD_LL = ,
/// <summary>
/// 监视输入到线程消息队列中的鼠标消息
/// </summary>
WH_MOUSE_LL =
} }

C#使用 SharpAVI进行 屏幕录制的更多相关文章

  1. ffmpeg 屏幕录制 so easy....

    linux Linux下使用FFmpeg进行屏幕录制相对比较方便,可以使用x11grab,使用如下的命令: ffmpeg -f x11grab -s 1600x900 -r 50 -vcodec li ...

  2. Mac与iPhone屏幕录制

    1. Mac电脑屏幕录制 1.1 文件->新建屏幕录制   1.2 点击红色按钮   1.3 截取需要录制的屏幕部分,点击开始录制   1.4 点击工具栏的停止按钮,停止录制   1.5 然后会 ...

  3. C# 与 Microsoft Expression Encoder实现屏幕录制

    在日常开发中,我们会经常遇到屏幕录制的需求.在C#中可以通过Expression Encoder的SDK实现这样的需求.首先需要下载Expression Encoder SDK,实现代码: priva ...

  4. LICEcap – 灵活好用,GIF 屏幕录制工具

    LICEcap – 灵活好用,GIF 屏幕录制工具 http://www.appinn.com/licecap/

  5. 团队交流合作简单解决方案:TeamViewer远程控制&会议演示 + HyperCam屏幕录制(免费)

    一. 教程摘要 做开发,团队合作是少不了的.而在合作中,有一部分是花在交流讨论上,其中包括初期的任务分配,成员的进度汇报,以及资源和心得分享等.该教程介绍了两个免费的软件,搭配起来,适合人数不超过25 ...

  6. LICEcap GIF 屏幕录制工具

    LICEcap 是一款屏幕录制工具,支持导出git动画图片格式,简单好用.大小只有几百KB   运行之后,可以随意调整大小,右下角有开始/停止按钮.      压缩包:http://files.cnb ...

  7. 在MAC系统上进行屏幕录制

    最近打算将一些软件操作过程进行屏幕录制进行视频分享,所以寻思着找一块能在MAC上使用的屏幕录制软件.google了一番,没想到MAC系统自带的QuickTime Player已经内置屏幕录像功能,而且 ...

  8. LICEcap 简洁易用的动画屏幕录制软件

    LICEcap 简洁易用的动画屏幕录制软件 LICEcap 捕捉屏幕的区域并保存为gif动画(便于网络发布)或lcf格式(见下). LICEcap 直观易用,功能灵活,支持 Windows 和 OSX ...

  9. 屏幕录制:SCR Screen Recorder Pro v0.14.3汉化破解版

    应用概览 <ignore_js_op> 软件名称:屏幕录制:SCR Screen Recorder Pro 软件版本:v0.14.3汉化破解版软件语言:中文软件大小:3.5M软件包名:co ...

随机推荐

  1. UI - 视图控制器跳转另一个视图控制器特效总结

    1. 从一个视图控制器跳转另一个视图控制器的方式是可以进行设置的 CATransition *animation = [[CATransition alloc]init]; animation.dur ...

  2. 【网络】<网络是怎样连接的>笔记

    [一] 浏览器 http://user:pwd@hosturl:port/dir/of/file 基本思路: 1.1 生成http请求信息 包含“对什么”“进行怎样的操作”两个方法.一般常用操作是GE ...

  3. IOS对存放对象的数组排序

    我们开发的每个程序都会使用到一些数据,而这些数据一般被封装在一个自定义的类中.例如一个音乐程序可能会有一个Song类,聊天程序则又一个 Friend类,点菜程序会有一个Recipe类等.有时候我们希望 ...

  4. File I|O(八)

    1.I/O:input/output 1.1.java.io.File 表示:文件或者文件夹(目录) File f=new File("文件路径") 注意:相对路径:非web项目的 ...

  5. PHP防止mysql注入方法

    本文纲要: 1. 初始化你的变量 2. 一定记得要过滤你的变量 [一.在服务器端配置] 安全,PHP代码编写是一方面,PHP的配置更是非常关键. 我们php手手工安装的,php的默认配置文件在 /us ...

  6. 【MFC】MFC中窗口重绘

    MFC中窗口重绘 摘自:http://blog.csdn.net/shuilan0066/article/details/5859057 在刷新窗口时经常要调用重绘函数 MFC提供了三个函数用于窗口重 ...

  7. 使用 minio 搭建私有对象存储云。aws-php-sdk 操作object

    How to use AWS SDK for PHP with Minio Server aws-sdk-php is the official AWS SDK for the PHP program ...

  8. 软件开发中IT用语-日文和英文对照版

    開発工程 † 要件定義…Requirement Definition (Analyze) 外部設計…External Design 内部設計…Internal Design 開発…Coding テスト ...

  9. 关于ListView和GridView的应用

    这两篇博文分别讲的很好: ListView: http://www.cnblogs.com/noTice520/archive/2011/12/05/2276379.html GridViw: htt ...

  10. Java-Runoob:Java 教程

    ylbtech-Java-Runoob:Java 教程 1.返回顶部 1. Java 教程 Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言. Java可运行于 ...