再 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. react 学习文章

    生命周期 学习笔记 一些坑 项目完成后总结 理解Immutable 是否要同构如何同构 react组件最佳实践 redux集合所有的state props来源, 页面所有状态 数据的唯一来源 reac ...

  2. javascript 的智能提示intellisence用法

    转载自:http://blog.csdn.net/applewangpai/article/details/23517087   引用指令reference Visual Studio 2012支持的 ...

  3. Delphi for Android (aka Delphi XE5 aka RAD Studio XE5) has appeared

    Delphi for Android (aka Delphi XE5 aka RAD Studio XE5) has appeared   Blimey, that took me by surpri ...

  4. 处理get中文乱码

    package com.servlet;              import java.io.IOException;       import java.io.PrintWriter;      ...

  5. 重温CLR(三)类型基础

    所有类型都从System.Object派生 “运行时”要求每个类型最终都要从System.Object类型派生.也就是说,一下两个类型的定义完全一致. //隐式派生自Object class Empl ...

  6. 接口测试基础——第一篇smtplib发送文字邮件

    现在我们就开始进入接口测试框架的知识准备阶段,今天是第一篇,很简单的,就是发送纯文字的电子邮件,会的童鞋可以忽略,不会的就多敲几遍,直到自己能敲出来为止~~ # coding: utf-8 impor ...

  7. matlab滤波器的设计

    求出濾波器的階數以及 3dB 截止頻率後,可用相應的 Matlab 函數計算出實現傳遞函數的分子分母係數來.巴特沃斯型濾波器是通帶內最大平坦.帶外單調下降型的,其計算命令是:[b,a] = butte ...

  8. CSS 属性:touch-action

    CSS 属性 touch-action 用于指定某个给定的区域是否允许用户操作,以及如何响应用户操作(比如浏览器自带的划动.缩放等). /* Keyword values */ touch-actio ...

  9. Yii中处理前后台登录新方法

    我一开始的做法是在后台登录时设置一个isadmin的session,然后再前台登录时注销这个session,这样做只能辨别是前台登录还是后台登录,但做不到前后台一起登录,也即前台登录了后台就退出了,后 ...

  10. 【CSS3】 - 初识CSS3

    .navdemo{ width:560px; height: 50px; font:bold 0/50px Arial; text-align:center; margin:40px auto 0; ...