如何在C#中捕获Windows应用商店应用的窗口内容

时间:2016-06-20 21:10:54

标签: c# windows-store-apps screen-capture

我有一些代码可以捕获Windows桌面应用程序内容并保存到.NET中的Bitmap对象。它使用User32.dll和Gdi32.dll(BitBlt)并且工作得很好。但是,当我为代码提供一个包含Windows应用商店应用程序的窗口的句柄时,代码会生成全黑位图。我不确定这是安全功能还是什么。我不能使用ScreenCapture api作为窗口的内容,在调整大小后,几乎总是比屏幕更高/更大。对于Windows应用商店应用,有没有人有幸获取窗口内容,即使它们比屏幕更大?

编辑:就像一张纸条,我试图捕捉一个不同的程序窗口,而不是我自己的程序。我的程序可以假定为.NET 4.6.1 / C#

中的Windows控制台应用程序

此外,我知道在Windows API中必须以某种方式实现这一点,因为Aero Peek功能,如果将鼠标悬停在正在运行的程序的任务栏上,则会显示窗口的完整高度,包括屏幕外组件。 (见右侧的高窗,设置为比我的显示器高出6000px)

see tall window on right, set to 6000px much higher than my display

2 个答案:

答案 0 :(得分:3)

从Windows 8.1开始,您可以使用Windows.UI.Xaml.Media.Imaging.RenderTargetBitmap将元素渲染到位图。对此有几点需要注意:

  1. 您可以捕获屏幕外的元素,只要它们位于XAML可视树中并且Visibility设置为Visible而不是Collapsed
  2. 某些元素(如视频)将无法捕获。
  3. 有关详细信息,请参阅API:

    https://msdn.microsoft.com/library/windows/apps/xaml/windows.ui.xaml.media.imaging.rendertargetbitmap.aspx

答案 1 :(得分:2)

这可能会成功。基本上获取应用程序的窗口句柄,调用它上面的本机函数来找出应用程序窗口位置,提供那些做图形类并从屏幕复制。

class Program
{
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr FindWindow(string strClassName, string strWindowName);

    [DllImport("user32.dll")]
    public static extern bool GetWindowRect(IntPtr hwnd, ref Rect rectangle);

    public struct Rect
    {
        public int Left { get; set; }
        public int Top { get; set; }
        public int Right { get; set; }
        public int Bottom { get; set; }
    }


    static void Main(string[] args)
    {
        /// Give this your app's process name.
        Process[] processes = Process.GetProcessesByName("yourapp");
        Process lol = processes[0];
        IntPtr ptr = lol.MainWindowHandle;
        Rect AppRect = new Rect();
        GetWindowRect(ptr, ref AppRect);
        Rectangle rect = new Rectangle(AppRect.Left, AppRect.Top, (AppRect.Right - AppRect.Left), (AppRect.Bottom - AppRect.Top));
        Bitmap bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
        Graphics g = Graphics.FromImage(bmp);
        g.CopyFromScreen(rect.Left, rect.Top, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);

        // make sure temp directory is there or it will throw.
        bmp.Save(@"c:\temp\test.jpg", ImageFormat.Jpeg);
    }
}