在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
最近手头工作比较轻松了一点就继续研究和完善之前的录屏软件,使用AForge最大的问题在于:最原始的只能够录全屏,而自定义的录屏需要更改非常多的细节:like follows: 1、需要支持区域化录屏; 2、需要支持麦克风录音,并且混音在视频中,同步; 3、需要支持系统声音录取、并且需要混音在视频中,同步; 4、需要支持捕获光标,并且自定义颜色、描边,最重要的是你需要在区域录屏的时候支持坐标位置更新(相对比较难); 前面3个已经在前面的文章介绍了,这里不再赘述。着重列出第4点的内容以及如何解决。如果正在研究录屏这块的朋友们,千万别去copy那什么网上有限制时间录制和收费的录制,特别是有些很恶心的还发表长篇大论写的如何如何实现(的确技术不可否认是实现了),其实最后还是要你付费才能完全使用,就问你恶不恶心! 好了,废话不多说,我们来一一解决; 首先获取系统光标有两种方式,第一种是直接通过系统API进行获取光标,这个是完全记录系统光标在做什么。随着系统光标变化而变化的。这边有用到的是几个类: 第一种方式:【CursorHelper.cs】、【GDIStuff.cs】、【Win32Stuff.cs】相对复杂一些;我就在代码中直接显示就好了,不需要引用任何其他的东西; /// <summary> /// The rt global cursor. /// </summary> public class CursorHelper { #region Constants /// <summary> /// The curso r_ showing. /// </summary> private const int CURSOR_SHOWING = 1; #endregion #region Public Methods and Operators /// <summary> /// The capture cursor. /// </summary> /// <param name="x"> /// The x. /// </param> /// <param name="y"> /// The y. /// </param> /// <returns> /// The <see cref="Bitmap"/>. /// </returns> public static Bitmap CaptureCursor(ref int x, ref int y) { Win32Stuff.CURSORINFO cursorInfo = new Win32Stuff.CURSORINFO(); cursorInfo.cbSize = Marshal.SizeOf(cursorInfo); if (!Win32Stuff.GetCursorInfo(out cursorInfo)) { return null; } if (cursorInfo.flags != Win32Stuff.CURSOR_SHOWING) { return null; } IntPtr hicon = Win32Stuff.CopyIcon(cursorInfo.hCursor); if (hicon == IntPtr.Zero) { return null; } Win32Stuff.ICONINFO iconInfo; if (!Win32Stuff.GetIconInfo(hicon, out iconInfo)) { return null; } x = cursorInfo.ptScreenPos.x - ((int)iconInfo.xHotspot); y = cursorInfo.ptScreenPos.y - ((int)iconInfo.yHotspot); using (Bitmap maskBitmap = Bitmap.FromHbitmap(iconInfo.hbmMask)) { // Is this a monochrome cursor? if (maskBitmap.Height == maskBitmap.Width * 2) { Bitmap resultBitmap = new Bitmap(maskBitmap.Width, maskBitmap.Width); using (Graphics desktopGraphics = Graphics.FromHwnd(Win32Stuff.GetDesktopWindow())) { IntPtr desktopHdc = desktopGraphics.GetHdc(); IntPtr maskHdc = GDIStuff.CreateCompatibleDC(desktopHdc); IntPtr oldPtr = GDIStuff.SelectObject(maskHdc, maskBitmap.GetHbitmap()); using (Graphics resultGraphics = Graphics.FromImage(resultBitmap)) { IntPtr resultHdc = resultGraphics.GetHdc(); // These two operation will result in a black cursor over a white background. // Later in the code, a call to MakeTransparent() will get rid of the white background. GDIStuff.BitBlt( resultHdc, 0, 0, 32, 32, maskHdc, 0, 32, (int)GDIStuff.TernaryRasterOperations.SRCCOPY); GDIStuff.BitBlt( resultHdc, 0, 0, 32, 32, maskHdc, 0, 0, (int)GDIStuff.TernaryRasterOperations.SRCINVERT); resultGraphics.ReleaseHdc(resultHdc); GDIStuff.DeleteDC(resultHdc); GDIStuff.DeleteObject(resultHdc); } IntPtr newPtr = GDIStuff.SelectObject(maskHdc, oldPtr); GDIStuff.DeleteObject(oldPtr); GDIStuff.DeleteObject(newPtr); GDIStuff.DeleteDC(maskHdc); desktopGraphics.ReleaseHdc(desktopHdc); GDIStuff.DeleteDC(desktopHdc); } // Remove the white background from the BitBlt calls, // resulting in a black cursor over a transparent background. resultBitmap.MakeTransparent(Color.White); return resultBitmap; } } //// Delete the mask, if present. // if (iconInfo.hbmMask != IntPtr.Zero) // { // DeleteObject(iconInfo.hbmMask); // } //// Delete the color bitmap, if present. // if (iconInfo.hbmColor != IntPtr.Zero) // { // DeleteObject(iconInfo.hbmColor); // } using (Icon icon = Icon.FromHandle(hicon)) { return icon.ToBitmap(); } } #endregion #region Methods /// <summary> /// The copy icon. /// </summary> /// <param name="hIcon"> /// The h icon. /// </param> /// <returns> /// The <see cref="IntPtr"/>. /// </returns> [DllImport("user32.dll")] private static extern IntPtr CopyIcon(IntPtr hIcon); /// <summary> /// The delete object. /// </summary> /// <param name="hDc"> /// The h dc. /// </param> /// <returns> /// The <see cref="IntPtr"/>. /// </returns> [DllImport("gdi32.dll")] private static extern IntPtr DeleteObject(IntPtr hDc); /// <summary> /// The destroy icon. /// </summary> /// <param name="hIcon"> /// The h icon. /// </param> /// <returns> /// The <see cref="bool"/>. /// </returns> [DllImport("user32.dll")] private static extern bool DestroyIcon(IntPtr hIcon); /// <summary> /// The get cursor info. /// </summary> /// <param name="pci"> /// The pci. /// </param> /// <returns> /// The <see cref="bool"/>. /// </returns> [DllImport("user32.dll")] private static extern bool GetCursorInfo(out CURSORINFO pci); /// <summary> /// The get gdi handle count. /// </summary> /// <returns> /// The <see cref="int" />. /// </returns> private static int GetGDIHandleCount() { return GetGuiResources(Process.GetCurrentProcess().Handle, 0); } /// <summary> /// The get gui resources. /// </summary> /// <param name="hProcess"> /// The h process. /// </param> /// <param name="uiFlags"> /// The ui flags. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> [DllImport("user32.dll")] private static extern int GetGuiResources(IntPtr hProcess, int uiFlags); /// <summary> /// The get icon info. /// </summary> /// <param name="hIcon"> /// The h icon. /// </param> /// <param name="piconinfo"> /// The piconinfo. /// </param> /// <returns> /// The <see cref="bool"/>. /// </returns> [DllImport("user32.dll")] private static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo); /// <summary> /// The get user handle count. /// </summary> /// <returns> /// The <see cref="int" />. /// </returns> private static int GetUserHandleCount() { return GetGuiResources(Process.GetCurrentProcess().Handle, 1); } /// <summary> /// The handle message. /// </summary> /// <param name="message"> /// The message. /// </param> private static void HandleMessage(string message) { Debug.WriteLine("HC: " + message + ": GDI: " + GetGDIHandleCount() + ": User: " + GetUserHandleCount()); } #endregion /// <summary> /// The cursorinfo. /// </summary> [StructLayout(LayoutKind.Sequential)] private struct CURSORINFO { // Fields /// <summary> /// The cb size. /// </summary> [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Reviewed. Suppression is OK here."), SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:AccessibleFieldsMustBeginWithUpperCaseLetter", Justification = "Reviewed. Suppression is OK here.")] public int cbSize; /// <summary> /// The flags. /// </summary> [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Reviewed. Suppression is OK here."), SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:AccessibleFieldsMustBeginWithUpperCaseLetter", Justification = "Reviewed. Suppression is OK here.")] public int flags; /// <summary> /// The h cursor. /// </summary> [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Reviewed. Suppression is OK here."), SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:AccessibleFieldsMustBeginWithUpperCaseLetter", Justification = "Reviewed. Suppression is OK here.")] public IntPtr hCursor; /// <summary> /// The pt screen pos. /// </summary> [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Reviewed. Suppression is OK here."), SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:AccessibleFieldsMustBeginWithUpperCaseLetter", Justification = "Reviewed. Suppression is OK here.")] public POINT ptScreenPos; } /// <summary> /// The iconinfo. /// </summary> [StructLayout(LayoutKind.Sequential)] private struct ICONINFO { // Fields /// <summary> /// The f icon. /// </summary> public bool fIcon; /// <summary> /// The x hotspot. /// </summary> public int xHotspot; /// <summary> /// The y hotspot. /// </summary> public int yHotspot; // Handle of the icon’s bitmask bitmap. /// <summary> /// The hbm mask. /// </summary> public IntPtr hbmMask; // Handle of the icon’s color bitmap. Optional for monochrome icons. /// <summary> /// The hbm color. /// </summary> public IntPtr hbmColor; } /// <summary> /// The point. /// </summary> [StructLayout(LayoutKind.Sequential)] private struct POINT { // Fields /// <summary> /// The x. /// </summary> public int x; /// <summary> /// The y. /// </summary> public int y; } ///// <summary> ///// The capture cursor. ///// </summary> ///// <param name="x"> ///// The x. ///// </param> ///// <param name="y"> ///// The y. ///// </param> ///// <returns> ///// The <see cref="Bitmap"/>. ///// </returns> // public static Bitmap CaptureCursor(ref int x, ref int y) // { // try // { // // Return value initially nothing // Bitmap bmp = null; // CURSORINFO curInfo = new CURSORINFO(); // curInfo.cbSize = Marshal.SizeOf(curInfo); // // HandleMessage("Start") // if (GetCursorInfo(ref curInfo)) // { // if (curInfo.flags == CURSOR_SHOWING) // { // IntPtr hicon = CopyIcon(curInfo.hCursor); // if (hicon != IntPtr.Zero) // { // ICONINFO icoInfo = default(ICONINFO); // if (GetIconInfo(hicon, ref icoInfo)) // { // // Delete the mask, if present. // if (icoInfo.hbmMask != IntPtr.Zero) // { // DeleteObject(icoInfo.hbmMask); // } // // Delete the color bitmap, if present. // if (icoInfo.hbmColor != IntPtr.Zero) // { // DeleteObject(icoInfo.hbmColor); // } // x = curInfo.ptScreenPos.x - icoInfo.xHotspot; // y = curInfo.ptScreenPos.y - icoInfo.yHotspot; // } // Icon ic = Icon.FromHandle(hicon); // bmp = ic.ToBitmap(); // // Must destroy the icon object we got from CopyIcon // DestroyIcon(hicon); // } // } // } // // HandleMessage("End") // return bmp; // } // catch // { // return null; // } // } } /// <summary> /// The gdi stuff. /// </summary> internal class GDIStuff { #region Constants /// <summary> /// The srccopy. /// </summary> public const int SRCCOPY = 13369376; #endregion #region Enums /// <summary> /// Specifies a raster-operation code. These codes define how the color data for the /// source rectangle is to be combined with the color data for the destination /// rectangle to achieve the final color. /// </summary> public enum TernaryRasterOperations { /// <summary>dest = source</summary> SRCCOPY = 0x00CC0020, /// <summary>dest = source OR dest</summary> SRCPAINT = 0x00EE0086, /// <summary>dest = source AND dest</summary> SRCAND = 0x008800C6, /// <summary>dest = source XOR dest</summary> SRCINVERT = 0x00660046, /// <summary>dest = source AND (NOT dest)</summary> SRCERASE = 0x00440328, /// <summary>dest = (NOT source)</summary> NOTSRCCOPY = 0x00330008, /// <summary>dest = (NOT src) AND (NOT dest)</summary> NOTSRCERASE = 0x001100A6, /// <summary>dest = (source AND pattern)</summary> MERGECOPY = 0x00C000CA, /// <summary>dest = (NOT source) OR dest</summary> MERGEPAINT = 0x00BB0226, /// <summary>dest = pattern</summary> PATCOPY = 0x00F00021, /// <summary>dest = DPSnoo</summary> PATPAINT = 0x00FB0A09, /// <summary>dest = pattern XOR dest</summary> PATINVERT = 0x005A0049, /// <summary>dest = (NOT dest)</summary> DSTINVERT = 0x00550009, /// <summary>dest = BLACK</summary> BLACKNESS = 0x00000042, /// <summary>dest = WHITE</summary> WHITENESS = 0x00FF0062, /// <summary> /// Capture window as seen on screen. This includes layered windows /// such as WPF windows with AllowsTransparency="true" /// </summary> CAPTUREBLT = 0x40000000 } #endregion #region Public Methods and Operators /// <summary> /// The bit blt. /// </summary> /// <param name="hdcDest"> /// The hdc dest. /// </param> /// <param name="xDest"> /// The x dest. /// </param> /// <param name="yDest"> /// The y dest. /// </param> /// <param name="wDest"> /// The w dest. /// </param> /// <param name="hDest"> /// The h dest. /// 全部评论
专题导读
热门推荐
热门话题
阅读排行榜
|
请发表评论