private void CaptureScreenArea(int x, int y, int w, int h, ref HBITMAP hBitmap) { hBitmap = NativeMethods.CreateCompatibleBitmap(m_hdcSource, w, h); m_hBitmapTemp = NativeMethods.SelectObject(m_hdcSrcTemp, hBitmap); NativeMethods.BitBlt(m_hdcSrcTemp, 0, 0, w, h, m_hdcSource, x, y, SRCCOPY); hBitmap = NativeMethods.SelectObject(m_hdcSrcTemp, m_hBitmapTemp); }
private void CloneArea(int x, int y, int w, int h, bool preserveAspectRatio = false) { CaptureScreenArea(x, y, w, h, ref m_hBitmapSource); // Invalidate but don`t erase, it helps to avoid blinks caused by background color. We also set it to null just in case. NativeMethods.InvalidateRect(m_hwndNotOverlay, IntPtr.Zero, false); // Tells that the window should be repainted m_hdcDestination = NativeMethods.BeginPaint(m_hwndNotOverlay, out PAINTSTRUCT m_paintStruct); m_hdcDstTemp = NativeMethods.CreateCompatibleDC(m_hdcDestination); m_hBitmapTemp = NativeMethods.SelectObject(m_hdcDstTemp, m_hBitmapSource); // No resizing (ideal when same resolution) //// NativeMethods.BitBlt(m_hdcDestination, 0, 0, w, h, m_hdcDstTemp, 0, 0, SRCCOPY); // Resizing (ideal when resolutions are different) NativeMethods.GetClientRect(m_hwndNotOverlay, ref m_windowSize); NativeMethods.SetStretchBltMode(m_hdcDestination, (int)Enum.Parse(typeof(StretchBltModes), "COLORONCOLOR")); // Use HALFTONE for better image quality (but slower) // https://www.experts-exchange.com/questions/24774563/StretchBlt-in-C-Csharp-trying-to-copy-a-bitmap-image-to-screen.html if (preserveAspectRatio) { if (scaleAspectRatio == 0) { scaleAspectRatio = Math.Round((double)w / h, 2); } int m_windowSizeNewX; int m_windowSizeNewY; if (m_windowSize.right > m_windowSize.bottom) { m_windowSizeNewY = Math.Min(m_windowSize.bottom, (int)Math.Round(m_windowSize.right / scaleAspectRatio)); m_windowSizeNewX = (int)Math.Round(m_windowSizeNewY * scaleAspectRatio, 2); } else { m_windowSizeNewX = Math.Min(m_windowSize.right, (int)Math.Round(m_windowSize.bottom * scaleAspectRatio)); m_windowSizeNewY = (int)Math.Round(m_windowSizeNewX / scaleAspectRatio, 2); } NativeMethods.StretchBlt(m_hdcDestination, 0, 0, m_windowSizeNewX, m_windowSizeNewY, m_hdcDstTemp, x, y, w, h, SRCCOPY); } else { NativeMethods.StretchBlt(m_hdcDestination, 0, 0, m_windowSize.right, m_windowSize.bottom, m_hdcDstTemp, x, y, w, h, SRCCOPY); } NativeMethods.EndPaint(m_hwndNotOverlay, ref m_paintStruct); NativeMethods.UpdateWindow(m_hwndNotOverlay); // Force direct repaint window // Without it memory leak will occurr. C++ version needs this too. NativeMethods.DeleteObject(m_hBitmapSource); NativeMethods.DeleteObject(m_hBitmapTemp); NativeMethods.DeleteDC(m_hdcDstTemp); }
internal static extern bool DeleteObject(HBITMAP hObject);
internal static extern HBITMAP SelectObject(HDC hdc, HBITMAP hgdiobj);