很佩服录像专家软件的功能,前两天一直在尝试实现自己的屏幕录像功能,进行了技术资料搜集和技术探索实现。该技术是基于开源项目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.
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键结束屏幕录像。
开始录像部分关键代码:
代码 private void BeginScreenRecord() { 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 FunctionSends 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 FunctionPlaces (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.
PostThreadMessage FunctionPosts 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
结束视频录制的关键代码:
代码 [DllImport( " user32.dll " , SetLastError = true )] 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://www.pinvoke.net/
http://sourceforge.net/projects/camstudio/
补充:在实际应用中我修改了CamStudio_CL的源代码,除去codec参数设置,改为自动寻找最优视频编码;提高帧频和压缩率。修改后CamStudio_CL.exe只需要输出路径即可。——2010-6-23 本博客声明:本人的技术探索过程中,得到了国信司南公司方面物质和精神支持。今后,本人博客里的所有技术探索成果将归“无痕客”、“国信司南”和“博客园”三方共同所有,原创作品如需转载,请注明本博客声明。
转载于:https://www.cnblogs.com/wuhenke/archive/2010/06/19/1760980.html
相关资源:DirectX修复工具V4.0增强版