示例#1
0
        public static void DoubleBufferPaint(IntPtr hDC, int x, int y, int width, int height, PaintCoreProc paintCore)
        {
            IntPtr hDC2 = Gdi32.CreateCompatibleDC(hDC);

            IntPtr hBmp = Gdi32.CreateCompatibleBitmap(hDC, width, height);

            Gdi32.SelectObject(hDC2, hBmp);
            Gdi32.DeleteObject(hBmp);

            Graphics g = Graphics.FromHdc(hDC2);

            paintCore(g);
            g.Dispose();

            Gdi32.BitBlt(hDC, x, y, width, height, hDC2, 0, 0, Gdi32.SRCCOPY);

            Gdi32.DeleteDC(hDC2);
        }
示例#2
0
        private static Bitmap CaptureDesktopToBitmap(int width, int height, Action <IntPtr, IntPtr> action)
        {
            // Use P/Invoke because of: https://stackoverflow.com/a/3072580/1069200
            var hDesk    = User32.GetDesktopWindow();
            var hSrc     = User32.GetWindowDC(hDesk);
            var hDest    = Gdi32.CreateCompatibleDC(hSrc);
            var hBmp     = Gdi32.CreateCompatibleBitmap(hSrc, width, height);
            var hPrevBmp = Gdi32.SelectObject(hDest, hBmp);

            action(hDest, hSrc);
            var bmp = Image.FromHbitmap(hBmp);

            Gdi32.SelectObject(hDest, hPrevBmp);
            Gdi32.DeleteObject(hBmp);
            Gdi32.DeleteDC(hDest);
            User32.ReleaseDC(hDesk, hSrc);
            return(bmp);
        }
        public static Bitmap TakeSnapshot(IViewObject obj, int width, int height)
        {
            // draw the view on a Bitmap
            IntPtr hBitmapDC       = IntPtr.Zero;
            IntPtr hBitmap         = IntPtr.Zero;
            IntPtr hPreviousObject = IntPtr.Zero;
            Bitmap bitmap          = null;

            try
            {
                // create GDI objects used for drawing
                hBitmapDC       = Gdi32.CreateCompatibleDC(User32.GetDC(IntPtr.Zero));
                hBitmap         = Gdi32.CreateCompatibleBitmap(User32.GetDC(IntPtr.Zero), width, height);
                hPreviousObject = Gdi32.SelectObject(hBitmapDC, hBitmap);

                RECT sourceRect = new RECT();
                sourceRect.right  = width;
                sourceRect.bottom = height;

                // draw the bitmap
                obj.Draw(DVASPECT.CONTENT, 1, IntPtr.Zero, IntPtr.Zero, User32.GetDC(IntPtr.Zero),
                         hBitmapDC, ref sourceRect, IntPtr.Zero, IntPtr.Zero, 0);

                // convert to a managed bitmap
                bitmap = Bitmap.FromHbitmap(hBitmap);
            }
            finally
            {
                // restore previous object
                Gdi32.SelectObject(hBitmapDC, hPreviousObject);

                if (hBitmapDC != IntPtr.Zero)
                {
                    Gdi32.DeleteDC(hBitmapDC);
                }

                if (hBitmap != IntPtr.Zero)
                {
                    Gdi32.DeleteObject(hBitmap);
                }
            }

            return(bitmap);
        }
示例#4
0
        /// <summary>
        /// Creates a new instance of <see cref="WindowProvider"/>.
        /// </summary>
        public WindowProvider(IWindow Window, bool IncludeCursor, out Func <Point, Point> Transform)
        {
            _window        = Window ?? throw new ArgumentNullException(nameof(Window));
            _includeCursor = IncludeCursor;

            var size = Window.Rectangle.Even().Size;

            Width  = size.Width;
            Height = size.Height;

            Transform = _transform = GetTransformer(Window);

            _hdcSrc = User32.GetDC(IntPtr.Zero);

            _hdcDest = Gdi32.CreateCompatibleDC(_hdcSrc);
            _hBitmap = Gdi32.CreateCompatibleBitmap(_hdcSrc, Width, Height);

            Gdi32.SelectObject(_hdcDest, _hBitmap);
        }
示例#5
0
        public static Bitmap CaptureDesktop()
        {
            IntPtr hDC     = User32.GetWindowDC(IntPtr.Zero),
                   hMemDC  = Gdi32.CreateCompatibleDC(hDC),
                   hBitmap = Gdi32.CreateCompatibleBitmap(hDC, SystemParams.ScreenWidth, SystemParams.ScreenHeight);

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

            var hOld = Gdi32.SelectObject(hMemDC, hBitmap);

            Gdi32.BitBlt(hMemDC, 0, 0, SystemParams.ScreenWidth, SystemParams.ScreenHeight, hDC, 0, 0, CopyPixelOperation.SourceCopy);

            Gdi32.SelectObject(hMemDC, hOld);

            return(Bitmap.FromHbitmap(hBitmap));
        }
示例#6
0
        /// <summary>
        /// Captures a specific area from the screen.
        /// </summary>
        public static CaptureImage Rectangle(Rectangle bounds)
        {
            // Use P/Invoke because of: https://stackoverflow.com/a/3072580/1069200
            var sz      = new System.Drawing.Size(bounds.Width, bounds.Height);
            var hDesk   = User32.GetDesktopWindow();
            var hSrce   = User32.GetWindowDC(hDesk);
            var hDest   = Gdi32.CreateCompatibleDC(hSrce);
            var hBmp    = Gdi32.CreateCompatibleBitmap(hSrce, sz.Width, sz.Height);
            var hOldBmp = Gdi32.SelectObject(hDest, hBmp);

            Gdi32.BitBlt(hDest, 0, 0, sz.Width, sz.Height, hSrce, bounds.X, bounds.Y, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);
            var bmp = Image.FromHbitmap(hBmp);

            Gdi32.SelectObject(hDest, hOldBmp);
            Gdi32.DeleteObject(hBmp);
            Gdi32.DeleteDC(hDest);
            User32.ReleaseDC(hDesk, hSrce);
            return(new CaptureImage(bmp, bounds));
        }
示例#7
0
        private void Render()
        {
            RECT rect = new RECT();

            User32.GetWindowRect(_handle, ref rect);



            int width  = rect.right - rect.left;
            int height = rect.bottom - rect.top;

            if (width == 0 || height == 0)
            {
                return;
            }

            IntPtr screenDc = User32.GetDC(IntPtr.Zero);
            IntPtr memDc    = Gdi32.CreateCompatibleDC(screenDc);

            POINT newLocation = new POINT(rect.left, rect.top);
            SIZE  newSize     = new SIZE(width, height);


            using (Bitmap bmp = GetBitmap(width, height))
            {
                IntPtr hBitmap    = bmp.GetHbitmap(_transparent);
                IntPtr hOldBitmap = Gdi32.SelectObject(memDc, hBitmap);

                User32.UpdateLayeredWindow(_handle, screenDc, ref newLocation, ref newSize, memDc, ref _ptZero, 0, ref _blend, 0x02);

                User32.ReleaseDC(IntPtr.Zero, screenDc);
                if (hBitmap != IntPtr.Zero)
                {
                    Gdi32.SelectObject(memDc, hOldBitmap);
                    Gdi32.DeleteObject(hBitmap);
                }
            }

            Gdi32.DeleteDC(memDc);

            GC.Collect();
        }
示例#8
0
        //This class is used to take screen shots of the desktop and convert them to the BitmapSource


        //This method takes screen shot of the specified region of the desktop
        public BitmapSource CaptureRegion(IntPtr hWnd, int x, int y, int width, int height, bool addToClipboard)
        {
            IntPtr       sourceDC = IntPtr.Zero;
            IntPtr       targetDC = IntPtr.Zero;
            IntPtr       compatibleBitmapHandle = IntPtr.Zero;
            BitmapSource bitmap = null;

            try
            {
                // gets the main desktop and all open windows
                sourceDC = User32.GetDC(User32.GetDesktopWindow());
                targetDC = Gdi32.CreateCompatibleDC(sourceDC);

                // create a bitmap compatible with our target DC
                compatibleBitmapHandle = Gdi32.CreateCompatibleBitmap(sourceDC, width, height);

                // gets the bitmap into the target device context
                Gdi32.SelectObject(targetDC, compatibleBitmapHandle);

                // copy from source to destination
                Gdi32.BitBlt(targetDC, 0, 0, width, height, sourceDC, x, y, Gdi32.SRCCOPY);

                // Here's the WPF glue to make it all work. It converts from an
                // hBitmap to a BitmapSource. Love the WPF interop functions
                bitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                    compatibleBitmapHandle, IntPtr.Zero, Int32Rect.Empty,
                    BitmapSizeOptions.FromEmptyOptions());
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("Error capturing region {0},{1},{2},{3}", x, y, width, height), ex);
            }
            finally
            {
                Gdi32.DeleteObject(compatibleBitmapHandle);

                User32.ReleaseDC(IntPtr.Zero, sourceDC);
                User32.ReleaseDC(IntPtr.Zero, targetDC);
            }

            return(bitmap);
        }
            internal MetafileDCWrapper(IntPtr hOriginalDC, Size size)
            {
                Debug.Assert(Gdi32.GetObjectType(hOriginalDC) == Gdi32.ObjectType.OBJ_ENHMETADC,
                             "Why wrap a non-Enhanced MetaFile DC?");

                if (size.Width < 0 || size.Height < 0)
                {
                    throw new ArgumentException(SR.ControlMetaFileDCWrapperSizeInvalid, nameof(size));
                }

                _hMetafileDC = hOriginalDC;
                _destRect    = new RECT(0, 0, size.Width, size.Height);
                HDC          = Gdi32.CreateCompatibleDC(IntPtr.Zero);

                int planes    = Gdi32.GetDeviceCaps(HDC, Gdi32.DeviceCapability.PLANES);
                int bitsPixel = Gdi32.GetDeviceCaps(HDC, Gdi32.DeviceCapability.BITSPIXEL);

                _hBitmap      = SafeNativeMethods.CreateBitmap(size.Width, size.Height, planes, bitsPixel, IntPtr.Zero);
                _hOriginalBmp = Gdi32.SelectObject(HDC, _hBitmap);
            }
示例#10
0
            /// <summary>
            /// Gets Image object containing screen shot
            /// </summary>
            /// <param name="handle">The handle to the window.
            /// <returns></returns>
            public Image CaptureWindow(IntPtr handle)
            {
                var hdcSrc     = User32.GetWindowDC(handle);
                var windowRect = new User32.Rect();

                User32.GetWindowRect(handle, ref windowRect);
                var width   = windowRect.right - windowRect.left;
                var height  = windowRect.bottom - windowRect.top;
                var hdcDest = Gdi32.CreateCompatibleDC(hdcSrc);
                var hBitmap = Gdi32.CreateCompatibleBitmap(hdcSrc, width, height);
                var hOld    = Gdi32.SelectObject(hdcDest, hBitmap);

                Gdi32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, Gdi32.Srccopy);
                Gdi32.SelectObject(hdcDest, hOld);
                Gdi32.DeleteDC(hdcDest);
                User32.ReleaseDC(handle, hdcSrc);
                Image img = Image.FromHbitmap(hBitmap);

                Gdi32.DeleteObject(hBitmap);
                return(img);
            }
示例#11
0
 virtual public Bitmap this[IntPtr hWnd, int x, int y, int width, int height]
 {
     get{
         IntPtr wndHDC = GetDC(hWnd);
         IntPtr capHDC = Gdi32.CreateCompatibleDC(wndHDC);
         IntPtr capBMP = Gdi32.CreateCompatibleBitmap(wndHDC, width, height);
         if (capBMP == IntPtr.Zero)
         {
             ReleaseDC(hWnd, wndHDC);
             Gdi32.DeleteDC(capHDC); return(null);
         }
         IntPtr prvHDC = (IntPtr)Gdi32.SelectObject(capHDC, capBMP);
         Gdi32.BitBlt(capHDC, 0, 0, width, height, wndHDC, x, y, Gdi32.SRCCOPY);             // managed: CompositeMode
         Gdi32.SelectObject(capHDC, prvHDC);
         Bitmap bmp = System.Drawing.Image.FromHbitmap(capBMP);
         ReleaseDC(hWnd, wndHDC);                    // release window context
         Gdi32.DeleteDC(capHDC);                     // delete capture context
         Gdi32.DeleteObject(capBMP);                 // delete capture bitmap
         return(bmp);                                // return bitmap
     }
 }
    public static Image CaptureWindow(IntPtr handle)
    {
        IntPtr hdcSrc     = User32.GetWindowDC(handle);
        RECT   windowRect = new RECT();

        User32.GetWindowRect(handle, ref windowRect);
        int    width   = windowRect.right - windowRect.left;
        int    height  = windowRect.bottom - windowRect.top;
        IntPtr hdcDest = Gdi32.CreateCompatibleDC(hdcSrc);
        IntPtr hBitmap = Gdi32.CreateCompatibleBitmap(hdcSrc, width, height);
        IntPtr hOld    = Gdi32.SelectObject(hdcDest, hBitmap);

        Gdi32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, ApiConstants.SRCCOPY);
        Gdi32.SelectObject(hdcDest, hOld);
        Gdi32.DeleteDC(hdcDest);
        User32.ReleaseDC(handle, hdcSrc);
        Image image = Image.FromHbitmap(hBitmap);

        Gdi32.DeleteObject(hBitmap);
        return(image);
    }
示例#13
0
        /// <summary>
        /// Windows only window capture by handle
        /// </summary>
        /// <param name="handle"></param>
        /// <returns></returns>
        private static byte[] CaptureWindowPng(IntPtr handle)
        {
            // get te hDC of the target window
            IntPtr hdcSrc = User32.GetWindowDC(handle);

            // get the size
            User32.RECT windowRect = new User32.RECT();
            User32.GetWindowRect(handle, ref windowRect);
            int width  = windowRect.right - windowRect.left;
            int height = windowRect.bottom - windowRect.top;
            // create a device context we can copy to
            IntPtr hdcDest = Gdi32.CreateCompatibleDC(hdcSrc);
            // create a bitmap we can copy it to,
            // using GetDeviceCaps to get the width/height
            IntPtr hBitmap = Gdi32.CreateCompatibleBitmap(hdcSrc, width, height);
            // select the bitmap object
            IntPtr hOld = Gdi32.SelectObject(hdcDest, hBitmap);

            // bitblt over
            Gdi32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, Gdi32.SRCCOPY);
            // restore selection
            Gdi32.SelectObject(hdcDest, hOld);
            // clean up
            Gdi32.DeleteDC(hdcDest);
            User32.ReleaseDC(handle, hdcSrc);
            byte[] ret = null;
            // get a .NET image object for it
            using (Bitmap img = Image.FromHbitmap(hBitmap))
            {
                // free up the Bitmap object
                Gdi32.DeleteObject(hBitmap);
                // Saving to stream
                using (var m = new MemoryStream())
                {
                    img.Save(m, ImageFormat.Png);
                    ret = m.ToArray();
                }
            }
            return(ret);
        }
示例#14
0
        private IntPtr GetCompatibleBitmap(Bitmap bm)
        {
            using ScreenDC hDC = ScreenDC.Create();

            // GDI+ returns a DIBSECTION based HBITMAP. The clipboard deals well
            // only with bitmaps created using CreateCompatibleBitmap(). So, we
            // convert the DIBSECTION into a compatible bitmap.
            IntPtr hBitmap = bm.GetHbitmap();

            // Create a compatible DC to render the source bitmap.
            IntPtr dcSrc  = Gdi32.CreateCompatibleDC(hDC);
            IntPtr srcOld = Gdi32.SelectObject(dcSrc, hBitmap);

            // Create a compatible DC and a new compatible bitmap.
            IntPtr dcDest     = Gdi32.CreateCompatibleDC(hDC);
            IntPtr hBitmapNew = Gdi32.CreateCompatibleBitmap(hDC, bm.Size.Width, bm.Size.Height);

            // Select the new bitmap into a compatible DC and render the blt the original bitmap.
            IntPtr destOld = Gdi32.SelectObject(dcDest, hBitmapNew);

            Gdi32.BitBlt(
                dcDest,
                0,
                0,
                bm.Size.Width,
                bm.Size.Height,
                dcSrc,
                0,
                0,
                Gdi32.ROP.SRCCOPY);

            // Clear the source and destination compatible DCs.
            Gdi32.SelectObject(dcSrc, srcOld);
            Gdi32.SelectObject(dcDest, destOld);

            Gdi32.DeleteDC(dcSrc);
            Gdi32.DeleteDC(dcDest);

            return(hBitmapNew);
        }
示例#15
0
        /// <summary>
        /// Gets Image object containing screen shot
        /// </summary>
        /// <param name="handle">The handle to the window.
        /// <returns></returns>
        public void CaptureScreenshot(ref byte[] byteImage)
        {
            if (ProcessPtr == null)
            {
                byteImage = null;
                return;
            }

            var hdcSrc     = User32.GetWindowDC(ProcessPtr);
            var windowRect = new User32.Rect();

            User32.GetWindowRect(ProcessPtr, ref windowRect);
            var destinationPtr = Gdi32.CreateCompatibleDC(hdcSrc);
            var bitmapPtr      = Gdi32.CreateCompatibleBitmap(hdcSrc, ScreenOptions.ScreenWidth, ScreenOptions.ScreenHeight);
            var hOld           = Gdi32.SelectObject(destinationPtr, bitmapPtr);

            try
            {
                Gdi32.BitBlt(destinationPtr, 0, 0, ScreenOptions.ScreenWidth, ScreenOptions.ScreenHeight, hdcSrc, 0, 0, Gdi32.Srccopy);
                Gdi32.SelectObject(destinationPtr, hOld);

                using (var screenCaptureImage = Image.FromHbitmap(bitmapPtr))
                    using (var bitmap = new Bitmap(screenCaptureImage))
                        using (var memoryStream = new MemoryStream())
                        {
                            screenCaptureImage.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Tiff);

                            byteImage = new byte[memoryStream.Length];
                            byteImage = memoryStream.ToArray();
                        }
            }
            finally
            {
                Gdi32.DeleteDC(destinationPtr);
                User32.ReleaseDC(ProcessPtr, hdcSrc);
                Gdi32.DeleteObject(bitmapPtr);
                Gdi32.DeleteObject(hOld);
            }
        }
示例#16
0
        /// <summary>
        /// Creates bitmap by image pointer
        /// </summary>
        /// <param name="ptr"></param>
        /// <returns></returns>
        public static Bitmap GetImage(IntPtr ptr)
        {
            SIZE size;

            IntPtr hBitmap;

            IntPtr hDC = user32.GetDC(ptr);

            IntPtr hMemDC = Gdi32.CreateCompatibleDC(hDC);

            size.cx = user32.GetSystemMetrics(user32.SM_CXSCREEN);

            size.cy = user32.GetSystemMetrics(user32.SM_CYSCREEN);

            hBitmap = Gdi32.CreateCompatibleBitmap(hDC, size.cx, size.cy);

            if (hBitmap != IntPtr.Zero)
            {
                IntPtr hOld = (IntPtr)Gdi32.SelectObject(hMemDC, hBitmap);

                Gdi32.BitBlt(hMemDC, 0, 0, size.cx, size.cy, hDC, 0, 0, Gdi32.SRCCOPY);

                Gdi32.SelectObject(hMemDC, hOld);

                Gdi32.DeleteDC(hMemDC);

                user32.ReleaseDC(ptr, hDC);

                Bitmap bmp = Image.FromHbitmap(hBitmap);

                Gdi32.DeleteObject(hBitmap);

                GC.Collect();

                return(bmp);
            }

            return(null);
        }
示例#17
0
        /// <summary>
        /// 根据窗口名称截图
        /// </summary>
        /// <param name="windowName">窗口名称</param>
        /// <returns></returns>
        public static Image ByName(string windowName)
        {
            IntPtr handle = User32.FindWindow(null, windowName);
            IntPtr hdcSrc = User32.GetWindowDC(handle);

            User32.RECT windowRect = new User32.RECT();
            User32.GetWindowRect(handle, ref windowRect);
            int    width   = windowRect.right - windowRect.left;
            int    height  = windowRect.bottom - windowRect.top;
            IntPtr hdcDest = Gdi32.CreateCompatibleDC(hdcSrc);
            IntPtr hBitmap = Gdi32.CreateCompatibleBitmap(hdcSrc, width, height);
            IntPtr hOld    = Gdi32.SelectObject(hdcDest, hBitmap);

            Gdi32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, Gdi32.SRCCOPY);
            Gdi32.SelectObject(hdcDest, hOld);
            Gdi32.DeleteDC(hdcDest);
            User32.ReleaseDC(handle, hdcSrc);
            Image img = Image.FromHbitmap(hBitmap);

            Gdi32.DeleteObject(hBitmap);
            return(img);
        }
示例#18
0
            virtual public Bitmap Dc2Bmp(IntPtr hWnd, int Bit)
            {
                IntPtr  wndHDC = GetDC(hWnd);
                IntPtr  capHDC = Gdi32.CreateCompatibleDC(wndHDC);
                HBITMAP capBMP = Gdi32.CreateCompatibleBitmap(wndHDC, Size.Width, Size.Height);

                if (capBMP == IntPtr.Zero)
                {
                    ReleaseDC(hWnd, wndHDC);
                    Gdi32.DeleteDC(capHDC); return(null);
                }
                IntPtr prvHDC = (IntPtr)Gdi32.SelectObject(capHDC, capBMP);

                Gdi32.BitBlt(capHDC, 0, 0, Size.Width, Size.Height, wndHDC, Rect.X, Rect.Y, Bit);         // managed: CompositeModeGDI.SRCCOPY
                Gdi32.SelectObject(capHDC, prvHDC);
                Bitmap bmp = System.Drawing.Image.FromHbitmap(capBMP);

                ReleaseDC(hWnd, wndHDC);                // release window context
                Gdi32.DeleteDC(capHDC);                 // delete capture context
                Gdi32.DeleteObject(capBMP);             // delete capture bitmap
                return(bmp);                            // return bitmap
            }
示例#19
0
        public IEnumerable <Image> Record()
        {
            recording = true;

            IntPtr hDesk  = User32.GetDesktopWindow();
            IntPtr hdcSrc = User32.GetWindowDC(hDesk);

            User32.GetWindowRect(hDesk, out RECT rect);

            int w = rect.Width;
            int h = rect.Height;

            IntPtr hdcDest = Gdi32.CreateCompatibleDC(hdcSrc);
            IntPtr hBitmap = Gdi32.CreateCompatibleBitmap(hdcSrc, w, h);
            IntPtr hOld    = Gdi32.SelectObject(hdcDest, hBitmap);

            AsyncThread.Start(CalcFPS);

            while (recording)
            {
                Gdi32.BitBlt(hdcDest, 0, 0, w, h, hdcSrc, 0, 0, Constants.SRCCOPY);
                //Gdi32.SelectObject(hdcDest, hOld);


                yield return(Image.FromHbitmap(hBitmap));

                ImageCount += 1;

                //Gdi32.DeleteObject(hBitmap);

                //hBitmap = Gdi32.CreateCompatibleBitmap(hdcSrc, w, h);
                //hOld = Gdi32.SelectObject(hdcDest, hBitmap);
            }

            Gdi32.DeleteDC(hdcDest);
            User32.ReleaseDC(hDesk, hdcSrc);
            Gdi32.DeleteObject(hBitmap);
        }
        public static Bitmap CreateBitmapFromGraphics(Graphics source, Rectangle bounds)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            IntPtr hDCSource      = source.GetHdc();
            IntPtr hDCDestination = Gdi32.CreateCompatibleDC(hDCSource);
            IntPtr hBitmap        = Gdi32.CreateCompatibleBitmap(hDCSource, bounds.Width, bounds.Height);

            Gdi32.SelectObject(hDCDestination, hBitmap);
            Gdi32.BitBlt(hDCDestination, bounds.X, bounds.Y, bounds.Width, bounds.Height, hDCSource, bounds.X, bounds.Y, WinGdi.SRCCOPY);

            Bitmap bitmap = Bitmap.FromHbitmap(hBitmap);

            Gdi32.DeleteObject(hDCDestination);
            Gdi32.DeleteObject(hBitmap);

            source.ReleaseHdc(hDCSource);

            return(bitmap);
        }
示例#21
0
        void IconPanelPaint(object sender, PaintEventArgs e)
        {
            const int drawOffset = 1;

            if (maskBitmap != null)
            {
                IntPtr destDC = e.Graphics.GetHdc();
                {                 // AND blitting
                    IntPtr memDC      = Gdi32.CreateCompatibleDC(destDC);
                    IntPtr srcHBitmap = maskBitmap.GetHbitmap();
                    IntPtr oldHBitmap = Gdi32.SelectObject(memDC, srcHBitmap);
                    Gdi32.BitBlt(destDC, drawOffset, drawOffset, iconSize.Width, iconSize.Height, memDC, 0, 0, Gdi32.SRCAND);

                    // TODO: review if the objects get destroyed correctly
                    Gdi32.SelectObject(memDC, oldHBitmap);
                    Gdi32.DeleteObject(srcHBitmap);
                    Gdi32.DeleteDC(memDC);
                    Gdi32.DeleteDC(oldHBitmap);
                }
                {                 // XOR blitting
                    IntPtr memDC      = Gdi32.CreateCompatibleDC(destDC);
                    IntPtr srcHBitmap = bitmap.GetHbitmap();
                    IntPtr oldHBitmap = Gdi32.SelectObject(memDC, srcHBitmap);
                    Gdi32.BitBlt(destDC, drawOffset, drawOffset, iconSize.Width, iconSize.Height, memDC, 0, 0, Gdi32.SRCINVERT);

                    Gdi32.SelectObject(memDC, oldHBitmap);
                    Gdi32.DeleteObject(srcHBitmap);
                    Gdi32.DeleteDC(memDC);
                    Gdi32.DeleteDC(oldHBitmap);
                }
                Gdi32.DeleteDC(destDC);
            }
            else if (bitmap != null)
            {
                e.Graphics.DrawImageUnscaled(bitmap, drawOffset, drawOffset);
            }
        }
示例#22
0
        public override Mat ExecuteCaptureWindow(IntPtr hWnd)
        {
            var windowDc   = User32.GetWindowDC(hWnd);
            var windowSize = GetWindowSize(hWnd);
            var width      = windowSize.Width;
            var height     = windowSize.Height;
            var memDc      = Gdi32.CreateCompatibleDC(windowDc);
            var memBmp     = Gdi32.CreateCompatibleBitmap(windowDc, width, height);
            var oldMemBmp  = Gdi32.SelectObject(memDc, memBmp);
            var result     = Gdi32.BitBlt(memDc.DangerousGetHandle(), 0, 0, width, height, windowDc.DangerousGetHandle(), 0, 0,
                                          (int)TernaryRasterOperations.SRCCOPY);

            Mat mat   = null;
            var bytes = new byte[width * height * 3];

            //获取位图像素RGB数据
            if (result)
            {
                var bitmapInfo = new BITMAPINFOHEADER()
                {
                    biWidth       = width,
                    biHeight      = -height,
                    biPlanes      = 1,
                    biBitCount    = 24,
                    biCompression = BitmapCompressionMode.BI_RGB
                };
                bitmapInfo.Init();
                Gdi32Extension.GetDIBits(memDc.DangerousGetHandle(), memBmp, 0, (uint)height, bytes, ref bitmapInfo, DIB_Color_Mode.DIB_RGB_COLORS);
                mat = new Mat(height, width, MatType.CV_8UC3, bytes);
            }

            Gdi32.SelectObject(memDc, oldMemBmp);
            Gdi32.DeleteObject(memBmp);
            Gdi32.DeleteDC(memDc);
            User32.ReleaseDC(hWnd, windowDc.HWnd);
            return(mat);
        }
示例#23
0
        /// <summary>
        /// Renders the tab thumbnail (<paramref name="image" />) using the given dimensions and coordinates and blends it properly with the underlying desktop elements
        /// </summary>
        /// <param name="image">Thumbnail to display</param>
        /// <param name="opacity">Opacity that <paramref name="image"/> should be displayed with</param>
        /// <param name="width">Width of <paramref name="image"/></param>
        /// <param name="height">Height of <paramref name="image"/></param>
        /// <param name="position">Screen position that <paramref name="image"/> should be displayed at</param>
        public void UpdateWindow(Bitmap image, byte opacity, int width, int height, POINT position)
        {
            IntPtr windowHandle        = User32.GetWindowDC(Handle);
            IntPtr deviceContextHandle = Gdi32.CreateCompatibleDC(windowHandle);
            IntPtr bitmapHandle        = image.GetHbitmap(Color.FromArgb(0));
            IntPtr oldBitmapHandle     = Gdi32.SelectObject(deviceContextHandle, bitmapHandle);
            SIZE   size = new SIZE {
                cx = 0, cy = 0
            };
            POINT destinationPosition = new POINT {
                x = 0, y = 0
            };

            if (width == -1 || height == -1)
            {
                // No width and height specified, use the size of the image
                size.cx = image.Width;
                size.cy = image.Height;
            }
            else
            {
                // Use whichever size is smallest, so that the image will be clipped if necessary
                size.cx = Math.Min(image.Width, width);
                size.cy = Math.Min(image.Height, height);
            }
            // Set the opacity and blend the image with the underlying desktop elements using User32.UpdateLayeredWindow
            BLENDFUNCTION blendFunction = new BLENDFUNCTION {
                BlendOp = Convert.ToByte((int)AC.AC_SRC_OVER), SourceConstantAlpha = opacity, AlphaFormat = Convert.ToByte((int)AC.AC_SRC_ALPHA), BlendFlags = 0
            };

            User32.UpdateLayeredWindow(Handle, windowHandle, ref position, ref size, deviceContextHandle, ref destinationPosition, 0, ref blendFunction, ULW.ULW_ALPHA);

            Gdi32.SelectObject(deviceContextHandle, oldBitmapHandle);
            Gdi32.DeleteObject(bitmapHandle);
            Gdi32.DeleteDC(deviceContextHandle);
            User32.ReleaseDC(Handle, windowHandle);
        }
示例#24
0
        //通过句柄来获取图片
        public Image GetPic_ByHwnd(IntPtr hWnd, User32.RECT rect)
        {
            // 根据句柄获取设备上下文句柄
            IntPtr hdcSrc = User32.GetWindowDC(hWnd);
            // 创建与指定设备兼容的存储器设备上下文(DC)
            IntPtr hdcDest = Gdi32.CreateCompatibleDC(hdcSrc);

            //设置长宽
            int width  = rect.right - rect.left;
            int height = rect.bottom - rect.top;

            //图片长宽和起点赋值
            this.width  = width;
            this.height = height;


            // 使用bitmap对象来存设备上下文数据
            IntPtr hBitmap = Gdi32.CreateCompatibleBitmap(hdcSrc, width, height);
            // 选择bitmap对象到指定设备上下文环境中
            IntPtr hOld = Gdi32.SelectObject(hdcDest, hBitmap);

            // 执行与指定源设备上下文的像素矩形对应的颜色数据的位块传输到目标设备上下文。
            Gdi32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, Gdi32.SRCCOPY);

            // 恢复设备上下文环境
            Gdi32.SelectObject(hdcDest, hOld);
            // 释放句柄
            Gdi32.DeleteDC(hdcDest);
            User32.ReleaseDC(hWnd, hdcSrc);
            // 将数据流转换成图
            Image img = Image.FromHbitmap(hBitmap);

            // 释放bitmap对象
            Gdi32.DeleteObject(hBitmap);
            return(img);
        }
示例#25
0
        public static byte[] Capture(Screen monitor)
        {
            byte[] imageBytes = null;
            try
            {
                Bitmap    resultBmp     = null;
                Rectangle monitorRect   = monitor.Bounds;
                HWND      desktopWindow = User32.GetDesktopWindow();
                HDC       windowDc      = User32.GetWindowDC(desktopWindow);
                HDC       memDc         = Gdi32.CreateCompatibleDC(windowDc);
                var       bitmap        = Gdi32.CreateCompatibleBitmap(windowDc, monitorRect.Width, monitorRect.Height);
                var       oldBitmap     = Gdi32.SelectObject(memDc, bitmap);

                bool result = Gdi32.BitBlt(memDc, 0, 0, monitorRect.Width, monitorRect.Height, windowDc, monitorRect.X, monitorRect.Y, Gdi32.RasterOperationMode.SRCCOPY);

                User32.CURSORINFO pci = new();
                pci.cbSize = (uint)Marshal.SizeOf(typeof(User32.CURSORINFO));

                if (User32.GetCursorInfo(ref pci))
                {
                    if (pci.flags == User32.CursorState.CURSOR_SHOWING)
                    {
                        User32.DrawIcon(memDc, pci.ptScreenPos.X - monitorRect.X, pci.ptScreenPos.Y - monitorRect.Y, pci.hCursor.DangerousGetHandle());
                    }
                }

                if (result)
                {
                    resultBmp = bitmap.ToBitmap();
                }

                Gdi32.SelectObject(memDc, oldBitmap);
                Gdi32.DeleteObject(bitmap);
                Gdi32.DeleteDC(memDc);
                User32.ReleaseDC(desktopWindow, windowDc);

                var shrunkImage = resultBmp.GetThumbnailImage(320, 240, null, IntPtr.Zero);
                resultBmp.Dispose();

                var cloned = shrunkImage.ConvertPixelFormatAsync(PixelFormat.Format8bppIndexed, OptimizedPaletteQuantizer.Octree(), ErrorDiffusionDitherer.FloydSteinberg, new TaskConfig()).GetAwaiter().GetResult();
                shrunkImage.Dispose();

                short[] colors = new short[256];

                var pal = (Color[])cloned.Palette.Entries.Clone();
                Parallel.For(0, cloned.Palette.Entries.Length, i =>
                {
                    colors[i] = ConvertColor(pal[i].R, pal[i].G, pal[i].B);
                });

                imageBytes = new byte[colors.Length * sizeof(short) + cloned.Width * cloned.Height];
                Buffer.BlockCopy(colors, 0, imageBytes, 0, colors.Length * sizeof(short));

                BitmapData imageData = cloned.LockBits(new Rectangle(0, 0, cloned.Width, cloned.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
                Marshal.Copy(imageData.Scan0, imageBytes, colors.Length * sizeof(short), cloned.Width * cloned.Height);
                cloned.UnlockBits(imageData);
                cloned.Dispose();

                _errorCount = 0;
            }
            catch (Exception ex)
            {
                _errorCount++;
                return(CaptureErr(monitor, ex));
            }

            return(imageBytes);
        }
示例#26
0
    private static Monitor ParseMonitor(IntPtr monitorHandle, IntPtr hdc)
    {
        var info = new MonitorInfoEx(); //TODO: MonitorInfo not getting filled with data.
        var a    = User32.GetMonitorInfo(new HandleRef(null, monitorHandle), info);

        var name = new string(info.szDevice).TrimEnd((char)0);

        var monitor = new Monitor
        {
            Handle       = monitorHandle,
            Name         = name,
            FriendlyName = name,
            NativeBounds = new Rect(info.rcMonitor.Left, info.rcMonitor.Top,
                                    info.rcMonitor.Right - info.rcMonitor.Left,
                                    info.rcMonitor.Bottom - info.rcMonitor.Top),
            Bounds = new Rect(info.rcMonitor.Left, info.rcMonitor.Top,
                              info.rcMonitor.Right - info.rcMonitor.Left,
                              info.rcMonitor.Bottom - info.rcMonitor.Top),
            WorkingArea = new Rect(info.rcWork.Left, info.rcWork.Top,
                                   info.rcWork.Right - info.rcWork.Left,
                                   info.rcWork.Bottom - info.rcWork.Top),
            IsPrimary = (info.dwFlags & Constants.MonitorinfoPrimary) != 0
        };

        #region Extra details

        try
        {
            var display = new DisplayDevices(true);

            for (uint id = 0; User32.EnumDisplayDevices(null, id, ref display, 0); id++)
            {
                var found   = display.DeviceName == monitor.Name;
                var adapter = display.DeviceString;

                User32.EnumDisplayDevices(display.DeviceName, id, ref display, 0);

                if (!found)
                {
                    continue;
                }

                monitor.AdapterName  = adapter;
                monitor.FriendlyName = string.IsNullOrWhiteSpace(display.DeviceString) ? LocalizationHelper.Get("S.Recorder.Screen.Name.Internal") :
                                       display.DeviceString == "Generic PnP Monitor" ? LocalizationHelper.Get("S.Recorder.Screen.Name.Generic") : display.DeviceString;
                break;
            }
        }
        catch (Exception ex)
        {
            LogWriter.Log(ex, "Impossible to get extra details of screen.");
        }

        #endregion

        #region Screen DPI

        try
        {
            ShCore.GetDpiForMonitor(monitorHandle, DpiTypes.Effective, out var aux, out _);
            monitor.Dpi = aux > 0 ? (int)aux : 96;
        }
        catch (Exception ex)
        {
            LogWriter.Log(ex, "Impossible to detect screen DPI.");

            try
            {
                var h = Gdi32.CreateCompatibleDC(IntPtr.Zero);
                monitor.Dpi = Gdi32.GetDeviceCaps(h, (int)DeviceCaps.LogPixelsX);
                Gdi32.DeleteDC(h);
            }
            catch (Exception e)
            {
                LogWriter.Log(e, "Error getting fallback of screen DPI.");
            }
        }

        #endregion

        return(monitor);
    }
示例#27
0
        private void CreateWindow(string className)
        {
            if (className == null)
            {
                throw new Exception("class_name is null");
            }
            if (className == String.Empty)
            {
                throw new Exception("class_name is empty");
            }

            _wndProcDelegate = CustomWndProc;

            gcHandle = GCHandle.Alloc(_wndProcDelegate);

            WNDCLASS windClass = new WNDCLASS
            {
                lpszClassName = className,
                lpfnWndProc   = Marshal.GetFunctionPointerForDelegate(_wndProcDelegate)
            };

            ushort classAtom = User32.RegisterClassW(ref windClass);

            int lastError = Marshal.GetLastWin32Error();

            if (classAtom == 0 && lastError != ERROR_CLASS_ALREADY_EXISTS)
            {
                throw new Exception("Could not register window class");
            }

            uint extendedStyle = (uint)(
                WindowExStyles.WS_EX_LEFT |
                WindowExStyles.WS_EX_LTRREADING |
                WindowExStyles.WS_EX_RIGHTSCROLLBAR |
                WindowExStyles.WS_EX_TOOLWINDOW);



            const uint style = (uint)(
                WindowStyles.WS_CLIPSIBLINGS |
                WindowStyles.WS_CLIPCHILDREN |
                WindowStyles.WS_POPUP);


            // Create window
            Handle = User32.CreateWindowExW(
                extendedStyle,
                className,
                className,
                style,
                0,
                0,
                0,
                0,
                IntPtr.Zero,
                IntPtr.Zero,
                IntPtr.Zero,
                IntPtr.Zero
                );

            if (Handle == IntPtr.Zero)
            {
                return;
            }

            var styles = (int)User32.GetWindowLongPtr(Handle, WindowLongFlags.GWL_EXSTYLE);

            //var owner = User32.GetWindow(_parentHandle, 4);

            //User32.SetWindowLong(Handle, GetWindowLongFlags.GWL_HWNDPARENT, owner);

            styles |= (int)(WindowExStyles.WS_EX_LAYERED | WindowExStyles.WS_EX_NOACTIVATE | WindowExStyles.WS_EX_NOPARENTNOTIFY);

            if (!_decorator.Resizable)
            {
                styles |= (int)WindowExStyles.WS_EX_TRANSPARENT;
            }

            User32.SetWindowLongPtr(Handle, WindowLongFlags.GWL_EXSTYLE, new IntPtr(styles));

            _screenDC = User32.GetDC(IntPtr.Zero);
            _memDC    = Gdi32.CreateCompatibleDC(_screenDC);

            D2D1.D2D1CreateFactory(FactoryType.SingleThreaded, out _d2dFactory);
        }
示例#28
0
        public static Bitmap?ToBitmap(this Graphics graphics, bool visibleClipOnly)
        {
            if (!OSUtils.IsWindows)
            {
                throw new PlatformNotSupportedException(Res.RequiresWindows);
            }

            if (graphics == null)
            {
                throw new ArgumentNullException(nameof(graphics), PublicResources.ArgumentNull);
            }

            if (visibleClipOnly && graphics.IsVisibleClipEmpty)
            {
                return(null);
            }

            Bitmap        result;
            RectangleF    visibleRect;
            int           sourceLeft, sourceTop, targetWidth, targetHeight;
            GraphicsState state = graphics.Save();

            try
            {
                // resetting the identity matrix so VisibleClipBounds will be correct
                graphics.Transform = new Matrix();

                // obtaining size in pixels
                graphics.PageUnit = GraphicsUnit.Pixel;
                visibleRect       = graphics.VisibleClipBounds;
                sourceLeft        = (int)visibleRect.Left;
                sourceTop         = (int)visibleRect.Top;
                targetWidth       = (int)visibleRect.Width;
                targetHeight      = (int)visibleRect.Height;

                // there is a source image: copying so transparency is preserved
                Image?imgSource = graphics.GetBackingImage();
                if (imgSource != null)
                {
                    if (imgSource is Metafile)
                    {
                        throw new NotSupportedException(Res.GraphicsExtensionsToBitmapMetafileNotSupported);
                    }
                    if (!visibleClipOnly)
                    {
                        return((Bitmap)imgSource.Clone());
                    }

                    if (targetWidth == 0 || targetHeight == 0)
                    {
                        return(null);
                    }

                    result = new Bitmap(targetWidth, targetHeight, imgSource.PixelFormat);
                    using IReadableBitmapData src = ((Bitmap)imgSource).GetReadableBitmapData();
                    using IWritableBitmapData dst = result.GetWritableBitmapData();
                    src.CopyTo(dst, new Rectangle(sourceLeft, sourceTop, targetWidth, targetHeight), Point.Empty);
                    return(result);
                }
            }
            finally
            {
                graphics.Restore(state);
            }

            IntPtr dcSource = graphics.GetHdc();

            if (!visibleClipOnly)
            {
                sourceLeft = 0;
                sourceTop  = 0;

                // obtaining container Window
                IntPtr hwnd = User32.WindowFromDC(dcSource);
                if (hwnd != IntPtr.Zero)
                {
                    //// Show in whole screen
                    //RECT rect;
                    //GetWindowRect(hwnd, out rect); // the full rect of self control on screen
                    //// Show in screen
                    //GetWindowRect(hwnd, out rect);
                    //left = -rect.Left;
                    //top = -rect.Top;
                    //width = GetDeviceCaps(dcSource, DeviceCap.HORZRES);
                    //height = GetDeviceCaps(dcSource, DeviceCap.VERTRES);
                    //visibleRect.Offset(rect.Left, rect.Top);

                    //// Show in parent control
                    //IntPtr hwndParent = GetParent(hwnd);
                    //if (hwndParent != IntPtr.Zero)
                    //{
                    //    RECT rectParent;
                    //    GetWindowRect(hwndParent, out rectParent);
                    //    left = rectParent.Left - rect.Left;
                    //    top = rectParent.Top - rect.Top;
                    //    width = rectParent.Right - rectParent.Left;
                    //    height = rectParent.Bottom - rectParent.Top;
                    //    visibleRect.Offset(-left, -top);
                    //}
                    //else

                    // Show in container control
                    Rectangle rect = User32.GetClientRect(hwnd);
                    if (rect.Right < visibleRect.Right && rect.Bottom < visibleRect.Bottom)
                    {
                        // Visible rect is larger than client rect: calculating from full size.
                        // This is usually the case when Graphics is created for nonclient area
                        rect = User32.GetWindowRect(hwnd);
                    }

                    targetWidth  = rect.Right - rect.Left;
                    targetHeight = rect.Bottom - rect.Top;
                }
                else if (visibleRect.Location != Point.Empty)
                {
                    // no window: surrounding symmetrically or max 100 px
                    targetWidth  = (int)(visibleRect.Right + Math.Min(visibleRect.Left, 100f));
                    targetHeight = (int)(visibleRect.Bottom + Math.Min(visibleRect.Top, 100f));
                }
            }

            // the container control is too small
            if (targetWidth <= 0 || targetHeight <= 0)
            {
                graphics.ReleaseHdc(dcSource);
                return(null);
            }

            // creating a compatible bitmap
            IntPtr dcTarget  = Gdi32.CreateCompatibleDC(dcSource);
            IntPtr hbmResult = Gdi32.CreateCompatibleBitmap(dcSource, targetWidth, targetHeight);

            Gdi32.SelectObject(dcTarget, hbmResult);

            // Copy content
            Gdi32.BitBlt(dcTarget, 0, 0, targetWidth, targetHeight, dcSource, sourceLeft, sourceTop);
            result = Image.FromHbitmap(hbmResult);

            //cleanup
            graphics.ReleaseHdc(dcSource);
            Gdi32.DeleteDC(dcTarget);
            Gdi32.DeleteObject(hbmResult);

            return(result);
        }
示例#29
0
		public static Image StretchImage( Image sourceImage, Point p, Rectangle zoomRegion, Size desiredSize ) {

			Image myImage = new Bitmap( desiredSize.Width, desiredSize.Height );
	
			using ( Graphics g = Graphics.FromImage( myImage ) ) {
		
				// use the DrawImage method in the framework to achieve a 
				// similar, but not as pixelated effect.
//				g.DrawImage( sourceImage, 
//					new Rectangle( new Point( 0 ), desiredSize ),
//					zoomRegion,
//					GraphicsUnit.Pixel );

				// we're dealing with memory device contexts here. first, a 
				// device context for the screen is retrieved. this serves as the
				// handle to the device context. we then create a memory device 
				// context that is compatible with the device context of the
				// screen (desktop).
				
				IntPtr hdc = User32.GetDC( IntPtr.Zero );
				IntPtr memoryDC = Gdi32.CreateCompatibleDC( hdc );

				// we retrieve a handle to the source bitmap object. this is 
				// then used to select the bitmap into the memory device 
				// context.
				
				IntPtr hBitmap = ( ( Bitmap ) sourceImage ).GetHbitmap();
				IntPtr oldObject = Gdi32.SelectObject( memoryDC, hBitmap );
				
				// Delete the object that was previously selected into the 
				// memory device context (there is a default bitmap object
				// that is encapsulated by the returned object, so we need
				// to make sure we get rid of that, otherwise we'll have
				// gdi object leaks).

				Gdi32.DeleteObject( oldObject );

				// the handle to the destination device context is retrieved.
				IntPtr destDeviceContext = g.GetHdc();

				// the source bitmap is stretched and its bits are blitted to 
				// the canvas represented by the destination device context.

				int result = Gdi32.StretchBlt( destDeviceContext, 0, 0, desiredSize.Width, desiredSize.Height, memoryDC, p.X, p.Y, zoomRegion.Width, zoomRegion.Height, RasterOperationCodes.SRCCOPY );				

				// error checking - StretchBlt returns non-zero on success.

				if ( result == 0 ) {

					// TODO: call GetLastError to dig down to the core of the problem.
					throw new ImageManipulationException( "There was a problem with the StretchBlt function call." );
				
				}
				
				// release everything
				g.ReleaseHdc( destDeviceContext );

				// clear the previously selected bitmap object from the memory
				// device context.
				Gdi32.DeleteObject( hBitmap );

				// get rid of the memory device context.
				Gdi32.DeleteDC( memoryDC );

				// return the device context to the device context pool.
				User32.ReleaseDC( IntPtr.Zero, hdc );

			} // dispose the Graphics object

			return myImage;

		}
        /// <summary>
        /// Renders the tabs and then calls <see cref="User32.UpdateLayeredWindow" /> to blend the tab content with the underlying window (
        /// <see cref="_parentForm" />).
        /// </summary>
        /// <param name="cursorPosition">Current position of the cursor.</param>
        /// <param name="forceRedraw">Flag indicating whether a full render should be forced.</param>
        public void Render(Point cursorPosition, bool forceRedraw = false)
        {
            if (!IsDisposed && _parentForm.TabRenderer != null && _parentForm.WindowState != FormWindowState.Minimized && _parentForm.ClientRectangle.Width > 0)
            {
                cursorPosition = GetRelativeCursorPosition(cursorPosition);

                using (Bitmap bitmap = new Bitmap(Width, Height, PixelFormat.Format32bppArgb))
                {
                    using (Graphics graphics = Graphics.FromImage(bitmap))
                    {
                        DrawTitleBarBackground(graphics);

                        // Since classic mode themes draw over the *entire* titlebar, not just the area immediately behind the tabs, we have to offset the tabs
                        // when rendering in the window
                        Point offset = _parentForm.WindowState != FormWindowState.Maximized && DisplayType == DisplayType.Classic
                                                        ? new Point(0, SystemInformation.CaptionButtonSize.Height)
                                                        : _parentForm.WindowState != FormWindowState.Maximized
                                                                ? new Point(0, SystemInformation.VerticalResizeBorderThickness - SystemInformation.BorderSize.Height)
                                                                : new Point(0, 0);

                        // Render the tabs into the bitmap
                        _parentForm.TabRenderer.Render(_parentForm.Tabs, graphics, offset, cursorPosition, forceRedraw);

                        // Cut out a hole in the background so that the control box on the underlying window can be shown
                        if (DisplayType == DisplayType.Classic && (_parentForm.ControlBox || _parentForm.MaximizeBox || _parentForm.MinimizeBox))
                        {
                            int boxWidth = 0;

                            if (_parentForm.ControlBox)
                            {
                                boxWidth += SystemInformation.CaptionButtonSize.Width;
                            }

                            if (_parentForm.MinimizeBox)
                            {
                                boxWidth += SystemInformation.CaptionButtonSize.Width;
                            }

                            if (_parentForm.MaximizeBox)
                            {
                                boxWidth += SystemInformation.CaptionButtonSize.Width;
                            }

                            CompositingMode oldCompositingMode = graphics.CompositingMode;

                            graphics.CompositingMode = CompositingMode.SourceCopy;
                            graphics.FillRectangle(
                                new SolidBrush(Color.Transparent), Width - boxWidth, 0, boxWidth, SystemInformation.CaptionButtonSize.Height);
                            graphics.CompositingMode = oldCompositingMode;
                        }

                        IntPtr screenDc     = User32.GetDC(IntPtr.Zero);
                        IntPtr memDc        = Gdi32.CreateCompatibleDC(screenDc);
                        IntPtr oldBitmap    = IntPtr.Zero;
                        IntPtr bitmapHandle = IntPtr.Zero;

                        try
                        {
                            // Copy the contents of the bitmap into memDc
                            bitmapHandle = bitmap.GetHbitmap(Color.FromArgb(0));
                            oldBitmap    = Gdi32.SelectObject(memDc, bitmapHandle);

                            SIZE size = new SIZE
                            {
                                cx = bitmap.Width,
                                cy = bitmap.Height
                            };

                            POINT pointSource = new POINT
                            {
                                x = 0,
                                y = 0
                            };
                            POINT topPos = new POINT
                            {
                                x = Left,
                                y = Top
                            };
                            BLENDFUNCTION blend = new BLENDFUNCTION
                            {
                                // We want to blend the bitmap's content with the screen content under it
                                BlendOp    = Convert.ToByte((int)AC.AC_SRC_OVER),
                                BlendFlags = 0,
                                // Follow the parent forms' opacity level
                                SourceConstantAlpha = (byte)(_parentForm.Opacity * 255),
                                // We use the bitmap's alpha channel for blending instead of a pre-defined transparency key
                                AlphaFormat = Convert.ToByte((int)AC.AC_SRC_ALPHA)
                            };

                            // Blend the tab content with the underlying content
                            if (!User32.UpdateLayeredWindow(
                                    Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, ULW.ULW_ALPHA))
                            {
                                int error = Marshal.GetLastWin32Error();
                                throw new Win32Exception(error, "Error while calling UpdateLayeredWindow().");
                            }
                        }

                        // Clean up after ourselves
                        finally
                        {
                            User32.ReleaseDC(IntPtr.Zero, screenDc);

                            if (bitmapHandle != IntPtr.Zero)
                            {
                                Gdi32.SelectObject(memDc, oldBitmap);
                                Gdi32.DeleteObject(bitmapHandle);
                            }

                            Gdi32.DeleteDC(memDc);
                        }
                    }
                }
            }
        }