Захват экрана BitBlt не работает в Windows 10

Я использую этот код для захвата окна процесса в фоновом режиме:

IntPtr = Process.GetProcessByName("memu")[0].MainWindowHandle;
RECT rc;
GetClientRect(hwnd, out rc);

IntPtr hdcFrom = GetDC(hwnd);
IntPtr hdcTo = CreateCompatibleDC(hdcFrom);

int Width = rc.right;
int Height = rc.bottom;

Bitmap bmp = null;

IntPtr hBitmap = CreateCompatibleBitmap(hdcFrom, Width, Height);
if (hBitmap != IntPtr.Zero) {
   IntPtr hLocalBitmap = SelectObject(hdcTo, hBitmap);

   BitBlt(hdcTo, 0, 0, Width, Height, hdcFrom, 0, 0, CopyPixelOperation.SourceCopy);
   SelectObject(hdcTo, hLocalBitmap);

   DeleteDC(hdcTo);
   ReleaseDC(hwnd, hdcFrom);

   bmp = Image.FromHbitmap(hBitmap);
   DeleteObject(hBitmap);
   return bmp;
}

Этот код захватывает эмулятор Android под названием MEmu, он использует DirectX для рендеринга контента. Но этот код перестает работать после обновления Windows 10 до версии 16299 (он работал обычно раньше), он все еще работает в Windows 7 с включенным режимом Aero.

Когда я использую этот метод в Windows 10 Pro v16299.X, он просто возвращает белое изображение или возвращает экран загрузки "эмулятор", а не текущее содержимое. В Windows 7, если я удалю режим Aero, он будет действовать одинаково, захватив "экран загрузки", поэтому выглядит так, как изменилось прозрачность в новом обновлении Windows 10 pro.

Я пробовал все, попробовал установить некоторые модули, чтобы заставить Aero Mode работать в Windows 10, попробовал PrintWindow, чтобы захватить экран в фоновом режиме, но все тот же.

Любые идеи, что может произойти? Или возможное решение? Или что изменилось в этой последней версии Windows 10 Pro, которая может сломать этот код?

Спасибо!

Ответ 1

Надеюсь, это решит проблему. Существует способ захвата экрана, встроенного в .net framework, который может работать. Не уверен, что он будет захватывать содержимое DirectX, но, возможно, стоит попробовать.

Обратите внимание, что это решение захватывает текущий экран, но вы, вероятно, сможете изменить его, чтобы захватить только интересующую вас область.

Я нашел это решение здесь: https://www.c-sharpcorner.com/UploadFile/2d2d83/how-to-capture-a-screen-using-C-Sharp/

private void CaptureMyScreen()
{
      try
      {
           //Creating a new Bitmap object
          Bitmap captureBitmap = new Bitmap(1024, 768, PixelFormat.Format32bppArgb);

         //Bitmap captureBitmap = new Bitmap(int width, int height, PixelFormat);
         //Creating a Rectangle object which will  
         //capture our Current Screen
         Rectangle captureRectangle = Screen.AllScreens[0].Bounds;

         //Creating a New Graphics Object
         Graphics captureGraphics = Graphics.FromImage(captureBitmap);

        //Copying Image from The Screen
        captureGraphics.CopyFromScreen(captureRectangle.Left,captureRectangle.Top,0,0,captureRectangle.Size);

        //Saving the Image File (I am here Saving it in My E drive).
        captureBitmap.Save(@"E:\Capture.jpg",ImageFormat.Jpeg);

        //Displaying the Successfull Result

        MessageBox.Show("Screen Captured");
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}