예제 #1
0
        private void CursorCapture(FrameInfo frame)
        {
            //if (_justStarted && (CursorShapeBuffer?.Length ?? 0) == 0)
            {
                //_justStarted = false;

                //https://stackoverflow.com/a/6374151/1735672
                //Bitmap struct, is used to get the cursor shape when SharpDX fails to do so.
                var _infoHeader = new Native.BitmapInfoHeader();
                _infoHeader.biSize         = (uint)Marshal.SizeOf(_infoHeader);
                _infoHeader.biBitCount     = 32;
                _infoHeader.biClrUsed      = 0;
                _infoHeader.biClrImportant = 0;
                _infoHeader.biCompression  = 0;
                _infoHeader.biHeight       = -Height; //Negative, so the Y-axis will be positioned correctly.
                _infoHeader.biWidth        = Width;
                _infoHeader.biPlanes       = 1;

                try
                {
                    var cursorInfo = new Native.CursorInfo();
                    cursorInfo.cbSize = Marshal.SizeOf(cursorInfo);

                    if (Native.GetCursorInfo(out cursorInfo))
                    {
                        if (cursorInfo.flags == Native.CursorShowing)
                        {
                            var hicon = Native.CopyIcon(cursorInfo.hCursor);

                            if (hicon != IntPtr.Zero)
                            {
                                if (Native.GetIconInfo(hicon, out var iconInfo))
                                {
                                    frame.CursorX = cursorInfo.ptScreenPos.X - Left;
                                    frame.CursorY = cursorInfo.ptScreenPos.Y - Top;

                                    var bitmap      = new Native.Bitmap();
                                    var hndl        = GCHandle.Alloc(bitmap, GCHandleType.Pinned);
                                    var ptrToBitmap = hndl.AddrOfPinnedObject();
                                    Native.GetObject(iconInfo.hbmColor, Marshal.SizeOf <Native.Bitmap>(), ptrToBitmap);
                                    bitmap = Marshal.PtrToStructure <Native.Bitmap>(ptrToBitmap);
                                    hndl.Free();

                                    //https://microsoft.public.vc.mfc.narkive.com/H1CZeqUk/how-can-i-get-bitmapinfo-object-from-bitmap-or-hbitmap
                                    _infoHeader.biHeight   = bitmap.bmHeight;
                                    _infoHeader.biWidth    = bitmap.bmWidth;
                                    _infoHeader.biBitCount = (ushort)bitmap.bmBitsPixel;

                                    var w = (bitmap.bmWidth * bitmap.bmBitsPixel + 31) / 8;
                                    CursorShapeBuffer = new byte[w * bitmap.bmHeight];

                                    var windowDeviceContext = Native.GetWindowDC(IntPtr.Zero);
                                    var compatibleBitmap    = Native.CreateCompatibleBitmap(windowDeviceContext, Width, Height);

                                    Native.GetDIBits(windowDeviceContext, compatibleBitmap, 0, (uint)_infoHeader.biHeight, CursorShapeBuffer, ref _infoHeader, Native.DibColorMode.DibRgbColors);

                                    //if (frame.CursorX > 0 && frame.CursorY > 0)
                                    //    Native.DrawIconEx(_compatibleDeviceContext, frame.CursorX - iconInfo.xHotspot, frame.CursorY - iconInfo.yHotspot, cursorInfo.hCursor, 0, 0, 0, IntPtr.Zero, 0x0003);

                                    //Clean objects here.
                                }

                                Native.DeleteObject(iconInfo.hbmColor);
                                Native.DeleteObject(iconInfo.hbmMask);
                            }

                            Native.DestroyIcon(hicon);
                        }

                        Native.DeleteObject(cursorInfo.hCursor);
                    }
                }
                catch (Exception e)
                {
                    LogWriter.Log(e, "Impossible to get the cursor");
                }
            }
        }
예제 #2
0
        public override int CaptureWithCursor(FrameInfo frame)
        {
            try
            {
                new System.Security.Permissions.UIPermission(System.Security.Permissions.UIPermissionWindow.AllWindows).Demand();

                //var success = Native.BitBlt(CompatibleDeviceContext, 0, 0, Width, Height, WindowDeviceContext, Left, Top, Native.CopyPixelOperation.SourceCopy | Native.CopyPixelOperation.CaptureBlt);
                var success = Native.StretchBlt(CompatibleDeviceContext, 0, 0, StartWidth, StartHeight, WindowDeviceContext, Left, Top, Width, Height, Native.CopyPixelOperation.SourceCopy | Native.CopyPixelOperation.CaptureBlt);

                if (!success)
                {
                    return(FrameCount);
                }

                #region Cursor

                try
                {
                    var cursorInfo = new Native.CursorInfo();
                    cursorInfo.cbSize = Marshal.SizeOf(cursorInfo);

                    if (Native.GetCursorInfo(out cursorInfo))
                    {
                        if (cursorInfo.flags == Native.CursorShowing)
                        {
                            var hicon = Native.CopyIcon(cursorInfo.hCursor);

                            if (hicon != IntPtr.Zero)
                            {
                                if (Native.GetIconInfo(hicon, out var iconInfo))
                                {
                                    frame.CursorX = cursorInfo.ptScreenPos.X - Left;
                                    frame.CursorY = cursorInfo.ptScreenPos.Y - Top;

                                    //If the cursor rate needs to be precisely captured.
                                    //https://source.winehq.org/source/dlls/user32/cursoricon.c#2325
                                    //int rate = 0, num = 0;
                                    //var ok1 = Native.GetCursorFrameInfo(cursorInfo.hCursor, IntPtr.Zero, 17, ref rate, ref num);

                                    //CursorStep
                                    var ok = Native.DrawIconEx(CompatibleDeviceContext, frame.CursorX - iconInfo.xHotspot, frame.CursorY - iconInfo.yHotspot, cursorInfo.hCursor, 0, 0, CursorStep, IntPtr.Zero, 0x0003);

                                    if (!ok)
                                    {
                                        CursorStep = 0;
                                        Native.DrawIconEx(CompatibleDeviceContext, frame.CursorX - iconInfo.xHotspot, frame.CursorY - iconInfo.yHotspot, cursorInfo.hCursor, 0, 0, CursorStep, IntPtr.Zero, 0x0003);
                                    }
                                    else
                                    {
                                        CursorStep++;
                                    }

                                    //Set to fix all alpha bits back to 255.
                                    //frame.RemoveAnyTransparency = iconInfo.hbmMask != IntPtr.Zero;
                                }

                                Native.DeleteObject(iconInfo.hbmColor);
                                Native.DeleteObject(iconInfo.hbmMask);
                            }

                            Native.DestroyIcon(hicon);
                        }

                        Native.DeleteObject(cursorInfo.hCursor);
                    }
                }
                catch (Exception e)
                {
                    //LogWriter.Log(e, "Impossible to get the cursor");
                }

                #endregion

                //Set frame details.
                FrameCount++;
                frame.Path       = $"{Project.FullPath}{FrameCount}.png";
                frame.Delay      = FrameRate.GetMilliseconds(SnapDelay);
                frame.DataLength = _byteLength;
                frame.Data       = new byte[_byteLength];

                Native.GetDIBits(WindowDeviceContext, CompatibleBitmap, 0, (uint)StartHeight, frame.Data, ref _infoHeader, Native.DibColorMode.DibRgbColors);

                BlockingCollection.Add(frame);
            }
            catch (Exception e)
            {
                //LogWriter.Log(ex, "Impossible to get the screenshot of the screen");
            }

            return(FrameCount);
        }
예제 #3
0
        public override int CaptureWithCursor(FrameInfo frame)
        {
            try
            {
                new System.Security.Permissions.UIPermission(System.Security.Permissions.UIPermissionWindow.AllWindows).Demand();

                var success = Native.BitBlt(CompatibleDeviceContext, 0, 0, Width, Height, WindowDeviceContext, Left, Top, Native.CopyPixelOperation.SourceCopy | Native.CopyPixelOperation.CaptureBlt);

                if (!success)
                {
                    return(FrameCount);
                }

                #region Cursor

                try
                {
                    var cursorInfo = new Native.CursorInfo();
                    cursorInfo.cbSize = Marshal.SizeOf(cursorInfo);

                    if (Native.GetCursorInfo(out cursorInfo))
                    {
                        if (cursorInfo.flags == Native.CursorShowing)
                        {
                            var hicon = Native.CopyIcon(cursorInfo.hCursor);

                            if (hicon != IntPtr.Zero)
                            {
                                if (Native.GetIconInfo(hicon, out var iconInfo))
                                {
                                    frame.CursorX = cursorInfo.ptScreenPos.X - Left;
                                    frame.CursorY = cursorInfo.ptScreenPos.Y - Top;

                                    var ok = Native.DrawIconEx(CompatibleDeviceContext, frame.CursorX - iconInfo.xHotspot, frame.CursorY - iconInfo.yHotspot, cursorInfo.hCursor, 0, 0, CursorStep, IntPtr.Zero, 0x0003);

                                    if (!ok)
                                    {
                                        CursorStep = 0;
                                        Native.DrawIconEx(CompatibleDeviceContext, frame.CursorX - iconInfo.xHotspot, frame.CursorY - iconInfo.yHotspot, cursorInfo.hCursor, 0, 0, CursorStep, IntPtr.Zero, 0x0003);
                                    }
                                    else
                                    {
                                        CursorStep++;
                                    }
                                }

                                Native.DeleteObject(iconInfo.hbmColor);
                                Native.DeleteObject(iconInfo.hbmMask);
                            }

                            Native.DestroyIcon(hicon);
                        }

                        Native.DeleteObject(cursorInfo.hCursor);
                    }
                }
                catch (Exception)
                {
                    //LogWriter.Log(e, "Impossible to get the cursor");
                }

                #endregion

                //Set frame details.
                FrameCount++;
                frame.Path  = $"{Project.FullPath}{FrameCount}.png";
                frame.Delay = FrameRate.GetMilliseconds(SnapDelay);
                frame.Image = Image.FromHbitmap(CompatibleBitmap);

                BlockingCollection.Add(frame);
            }
            catch (Exception)
            {
                //LogWriter.Log(ex, "Impossible to get the screenshot of the screen");
            }

            return(FrameCount);
        }
예제 #4
0
        /// <summary>
        /// Gets the position and Bitmap of the system cursor.
        /// </summary>
        /// <param name="point"><code>ref</code> parameter, only to return a second value.</param>
        /// <returns>The current Icon of the cursor</returns>
        public static Bitmap CaptureImageCursor(ref Point point)
        {
            var cursorInfo = new Native.CursorInfo();

            cursorInfo.cbSize = Marshal.SizeOf(cursorInfo);

            if (!Native.GetCursorInfo(out cursorInfo))
            {
                return(null);
            }

            if (cursorInfo.flags != Native.CursorShowing)
            {
                return(null);
            }

            var hicon = Native.CopyIcon(cursorInfo.hCursor);

            if (hicon == IntPtr.Zero)
            {
                return(null);
            }

            Native.ICONINFO iconInfo;
            if (!Native.GetIconInfo(hicon, out iconInfo))
            {
                return(null);
            }

            point.X = cursorInfo.ptScreenPos.X - ((int)iconInfo.xHotspot);
            point.Y = cursorInfo.ptScreenPos.Y - ((int)iconInfo.yHotspot);

            try
            {
                using (var maskBitmap = Image.FromHbitmap(iconInfo.hbmMask))
                {
                    //Is this a monochrome cursor?
                    //if (maskBitmap.Height == maskBitmap.Width * 2)
                    if (maskBitmap.Height == maskBitmap.Width * 2 && iconInfo.hbmColor == IntPtr.Zero)
                    {
                        var resultBitmap = new Bitmap(maskBitmap.Width, maskBitmap.Width);

                        using (var desktopGraphics = Graphics.FromHwnd(Native.GetDesktopWindow()))
                        {
                            var desktopHdc = desktopGraphics.GetHdc();

                            var maskHdc = Native.CreateCompatibleDC(desktopHdc);
                            var oldPtr  = Native.SelectObject(maskHdc, maskBitmap.GetHbitmap());

                            using (var resultGraphics = Graphics.FromImage(resultBitmap))
                            {
                                var 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.
                                // They take two pieces from a single image and merge into one.

                                //Bottom part
                                Native.BitBlt(resultHdc, 0, 0, resultBitmap.Width, resultBitmap.Height, maskHdc, 0, resultBitmap.Height, Native.CopyPixelOperation.SourceCopy); //SourceCopy
                                //Top part.
                                Native.BitBlt(resultHdc, 0, 0, resultBitmap.Width, resultBitmap.Height, maskHdc, 0, 0, Native.CopyPixelOperation.PatInvert);                    //SourceInvert

                                //BUG: It still don't take into account the background color (from the desktop) with the I-bean cursor, the one that inverts its color.
                                resultGraphics.ReleaseHdc(resultHdc);
                            }

                            var newPtr = Native.SelectObject(maskHdc, oldPtr);

                            Native.DeleteObject(newPtr);
                            Native.DeleteDC(maskHdc);
                            desktopGraphics.ReleaseHdc(desktopHdc);
                        }

                        // Remove the white background from the BitBlt calls,
                        // resulting in a black cursor over a transparent background.
                        resultBitmap.MakeTransparent(Color.White);
                        return(resultBitmap);
                    }
                }
            }
            catch (Exception ex)
            {
                LogWriter.Log(ex, "Impossible to get the icon.");
            }

            var icon = Icon.FromHandle(hicon);

            return(icon.ToBitmap());
        }