很佩服录像专家软件的功能,前两天一直在尝试实现自己的屏幕录像功能,进行了技术资料搜集和技术探索实现。该技术是基于开源项目CamStudio,将作为国信司南公司的未来技术产品功能的一部分。
技术资料搜集阶段筛选出两种有用资源:
1)ScrRecX是ActiveX插件,商业插件,有详细的二次开发代码实例,经测试,效果很好,录制的视频会有水印,但最终未能找到破解版。ActiveX Screen Video Recorder :
ScrRecX Screen Video Recorder is an ActiveX component. It allows you to incorporate the video recording capabilities into your own applications.
Main Features
- Allows you to select a screen area or window to record.
- Supports multiple monitors.
- Records video as AVI or WMV.
- Records audio and synchronizes it with video.
- Supports various video/audio codecs.
- Video Setup (video compressor, frame rate, and more).
- Audio Setup (audio device, audio input, audio compressor, sample rate, bits per sample, and more).
- Scaling video on the fly.
- Pause/Resume modes.
- Optionally highlights the mouse pointer.
- The recording area can follow the mouse pointer.
- Can display the flashing border.
- Allows you to use the unregistered ActiveX DLL (Example)
- The package contains our FM Screen Capture lossless video compressor for creating demonstrations/tutorials (See FM Screen Capture codec to learn more).
- Supports almost any language Visual Basic, C#, C++, Delphi, and more. (Examples)
- ScrRecX is supplied with many working examples.
ScrRecX功能很强大,实例代码很多,方便二次开发应用,但价格也不菲,初期建议公司购买,以便以后长期使用。
2)开源的CamStudio,是C++开源项目,提供源代码,但为提供二次开发接口,不利于应用。
CamStudio records activity from your screen and audio from a microphone into AVI video files and can also convert the AVIs into Streaming Flash videos (SWFs) using its built-in SWF Producer. Latest Stable Version: Camstudio-2.0-w32.zip
我先前花费大量的时间寻找ScrRecX的破解注册码,自己甚至使用ExploreSuite工具想破解DLL,消除视频水印,但都无功而返。改造CamStudio对我个人来说,是有很大困难的,比较不太熟悉C++。正当我彷徨时,发现让我柳暗花明的消息,原来CamStudio有命令行版的CamStudio Command Line V0.1 Released,这样就可以被WINFORM程序调用啦。下载:http://camstudio.org/CamStudio_cl.01.zip
命令行截图如:
该工具需要三个参数:codec(视频编码,有下面0-14种编码方式)、outputfile(输出的AVI的完整路径)、 seconds(指定录制时间几秒,该项可缺省,缺省时需要输入ENTER键,才能停止输出)
测试命令行代码:C:\camstudio_cl.exe -codec 5 -outfile C:\12345.avi -seconds 10
C:\camstudio_cl.exe -codec 5 -outfile C:\12345.avi (需要手动输入enter结束视频录制)
技术探索实现:winform 调用camstudio_cl.exe
该实验程序只是验证了可行性,将技术路线摸清了。在做实验程序中遇到最大的问题是:主程序如何与另一线程的camstudio_cl.exe进行通信?即如何向camstudio_cl.exe输入ENTER键结束屏幕录像。
开始录像部分关键代码:
{
string RecordArguments = @" -codec 5 -outfile " + _VideoPath;
//要调用外部程序的相对路径
p.StartInfo.FileName = _RecorderPath;
//参数
p.StartInfo.Arguments = RecordArguments;
//不使用操作系统外壳程序启动线程(一定为FALSE,详细的请看MSDN)
p.StartInfo.UseShellExecute = false;
//不创建进程窗口
p.StartInfo.CreateNoWindow = true;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.Start();//启动线程
}
关键是如何与另一进程程序进行交互,这里涉及到WIN32 API 编程(请参照:http://www.cnblogs.com/wuhenke/archive/2010/04/13/1711380.html),我花费了四个小时左右时间来实验探索,主要困扰在是使用SendMessage / PostMessage 还是PostThreadMessage。经测试,这里只能使用PostMessage发消息才能结束视频录制。
SendMessage Function
Sends the specified message to a window or windows. The SendMessage function calls the window procedure for the specified window and does not return until the window procedure has processed the message.
PostMessage Function
Places (posts) a message in the message queue associated with the thread that created the specified window and returns without waiting for the thread to process the message.To post a message in the message queue associated with a thread, use the PostThreadMessage function.
Posts a message to the message queue of the specified thread. It returns without waiting for the thread to process the message.
PostMessage和SendMessage的区别
1, PostMessage只把消息放入队列,不管其他程序是否处理都返回,然后继续执行,这是个异步消息投放函数。而SendMessage必须等待其他程序处理消息完了之后才返回,继续执行,这是个同步消息投放函数。而且,PostMessage的返回值表示PostMessage函数执行是否正确;而SendMessage的返回值表示其他程序处理消息后的返回值。这点大家应该都明白。 2, 如果在同一个线程内,PostMessage发送消息时,消息要先放入线程的消息队列,然后通过消息循环Dispatch到目标窗口。SendMessage发送消息时,系统直接调用目标窗口的消息处理程序,并将结果返回。SendMessage在同一线程中发送消息并不入线程消息队列。 如果在不同线程内。最好用PostThreadMessage代替PostMessage,他工作的很好。SendMessage发送消息到目标窗口所属的线程的消息队列,然后发送消息的线程等待(事实上,他应该还在做一些监测工作,比如监视QS_SENDMESSAGE标志),直到目标窗口处理完并且结果返回,发送消息的线程才继续运行。这是SendMessage的一般情况,事实上,处理过程要复杂的多。比如,当发送消息的线程监测到有别的窗口SendMessage一个消息到来时,他直接调用窗口处理过程(重入),并将处理结果返回(这个过程不需要消息循环中GetMessage等的支持)。 3, msdn: If you send a message in the range below WM_USER to the asynchronous message functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its message parameters can not include pointers. Otherwise, the operation will fail. 如果发送的消息码在WM_USER之下(非自定义消息)且消息参数中带有指针,那么PostMessage,SendNotifyMessage,SendMessageCallback这些异步消息发送函数将会调用失败。 最好不要用PostMessage发送带有指针参数的消息。
摘自:http://blog.csdn.net/Aoouch/archive/2007/03/09/1525457.aspx
结束视频录制的关键代码:
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr PostMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
const UInt32 WM_KEYDOWN =0X100;
const UInt32 WM_KEYUP = 0x101;
const UInt32 WM_CHAR = 0X102;
const Int32 VK_RETURN = 0X0D; //enter键代码
/// <summary>
/// 结束屏幕录制
/// </summary>
private void EndScreenRecorder()
{
IntPtr hWnd = FindWindow(null, _RecorderPath);
// // SetForegroundWindow(hWnd);
PostMessage(hWnd, WM_KEYDOWN, VK_RETURN, 0);
//阻塞等待进程结束
p.WaitForExit();
// PostMessage(hWnd, WM_KEYUP, VK_RETURN, 0);
p.Close();//关闭进程
p.Dispose();//释放资源
}
希望上面的探索工作能帮网友们少走弯路!
实例程序下载:下载
参考资料:
Enum Windows & SendMessage API http://www.developerfusion.com/article/34/enum-windows-sendmessage-api/3/
http://msdn.microsoft.com/en-us/library/ms644944(v=VS.85).aspx
http://msdn.microsoft.com/en-us/library/ms644950(VS.85).aspx
http://msdn.microsoft.com/en-us/library/ms644946(v=VS.85).aspx
Virtual-Key Codes http://msdn.microsoft.com/en-us/library/ms927178.aspx
http://sourceforge.net/projects/camstudio/