使用BitBlt截屏在Windows 10上显示黑色图像 [英] Screenshot with BitBlt results in black image on Windows 10

查看:68
本文介绍了使用BitBlt截屏在Windows 10上显示黑色图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用下面的代码来捕获当前活动窗口的屏幕截图.此代码来自捕获屏幕截图,包括.NET中的半透明窗口,一些小的补充,即它使用GetForegroundWindow和一个计时器,以便我可以选择所需的窗口.

I am using the code below to capture a screenshot of the currently active window. This code comes from Capture screenshot Including Semitransparent windows in .NET, with a few small additions, i.e. it uses GetForegroundWindow and also a timer so that I can select the desired window.

在Windows 10(x64)上,此功能可在Firefox浏览器上正常运行,但不适用于Chrome或Edge.

On Windows 10 (x64) this works fine for Firefox browser, but it does not work with Chrome or Edge.

我感到奇怪的是,

I find it strange that Screenshot captured using BitBlt in C# results a black image on Windows 10 [duplicate] is marked as a duplicate, because the answer from above (first link) does not solve this problem.

有什么想法为什么不适用于Chrome或Edge?

Any ideas why it does not work for Chrome or Edge?

代码:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace App1
{
    /// <summary>
    /// Description of MainForm.
    /// </summary>
    public partial class MainForm : Form
    {
        public MainForm()
        {
            //
            // The InitializeComponent() call is required for Windows Forms designer support.
            //
            InitializeComponent();

            //
            // TODO: Add constructor code after the InitializeComponent() call.
            //
        }

        void DoCapture()
        {
            label1.Text = "Capturing...";

              try
              {
              IntPtr hDesk = GetForegroundWindow();
              //IntPtr hDesk = GetDesktopWindow();

              var windowRect = new RECT();
              GetWindowRect(hDesk, out windowRect);

              int width = (int)(windowRect.Right - windowRect.Left);
              int height = (int)(windowRect.Bottom - windowRect.Top);      

              Size sz = new Size(width, height);
              sz.Width = (int)(sz.Width * 1.25); // this is just an adjustment for the Windows zoom factor of 125%
              sz.Height = (int)(sz.Height * 1.25);

              IntPtr hSrce = GetWindowDC(hDesk);
              IntPtr hDest = CreateCompatibleDC(hSrce);
              IntPtr hBmp = CreateCompatibleBitmap(hSrce, sz.Width, sz.Height);
              IntPtr hOldBmp = SelectObject(hDest, hBmp);
              bool b = BitBlt(hDest, 0,0, sz.Width, sz.Height, hSrce, 
                   0, 0, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);
              Bitmap bmp = Bitmap.FromHbitmap(hBmp);
              SelectObject(hDest, hOldBmp);
              DeleteObject(hBmp);
              DeleteDC(hDest);
              ReleaseDC(hDesk, hSrce);
              bmp.Save(@"c:\temp\test.png");
              bmp.Dispose();
              label1.Text = "Done";
              }
              catch (Exception e){
                label1.Text = "Exception Occurred";
                textBox1.Text = e.ToString();
              }
        }

        void Button1Click(object sender, EventArgs e)
        {
            timer1.Enabled = true;
        }

        // P/Invoke declarations
        [DllImport("gdi32.dll")]
        static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int
        wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, CopyPixelOperation rop);
        [DllImport("user32.dll")]
        static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDc);
        [DllImport("gdi32.dll")]
        static extern IntPtr DeleteDC(IntPtr hDc);
        [DllImport("gdi32.dll")]
        static extern IntPtr DeleteObject(IntPtr hDc);
        [DllImport("gdi32.dll")]
        static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
        [DllImport("gdi32.dll")]
        static extern IntPtr CreateCompatibleDC(IntPtr hdc);
        [DllImport("gdi32.dll")]
        static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);
        [DllImport("user32.dll")]
        public static extern IntPtr GetDesktopWindow();
        [DllImport("user32.dll")]
        public static extern IntPtr GetForegroundWindow();      
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowDC(IntPtr ptr);
        [DllImport("user32.dll")]
        static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left;        // x position of upper-left corner
            public int Top;         // y position of upper-left corner
            public int Right;       // x position of lower-right corner
            public int Bottom;      // y position of lower-right corner
        }

        void Timer1Tick(object sender, EventArgs e)
        {
            timer1.Enabled = false;
            DoCapture();
        }       
    }
}

在SharpDevelop 5.1中运行它

Running this in SharpDevelop 5.1

推荐答案

我可以建议一个简单的解决方法:

I can suggest a simple workaround:

首先使用 GetForegroundWindow 获取活动窗口rect.然后调用 GetDesktopWindow 并将该句柄与对BitBlt的调用一起使用:

First use GetForegroundWindow to get the active window rect. Then call GetDesktopWindow and use that handle with the call to BitBlt:

只需在上面的代码中添加一行:

Just add a single line to above code:

          IntPtr hDesk = GetForegroundWindow();
          ...       // get dimensions of active window    
          hDesk = GetDesktopWindow();  // add this line
          IntPtr hSrce = GetWindowDC(hDesk);
          IntPtr hDest = CreateCompatibleDC(hSrce);

工作正常.

这篇关于使用BitBlt截屏在Windows 10上显示黑色图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆